Commit c1e3b377ad48febba6f91b8ae42c44ee4d4ab45e

Authored by Zhao Yakui
Committed by Andi Kleen
1 parent 5b53496a5a

ACPI: Create "idle=halt" bootparam

"idle=halt" limits the idle loop to using
the halt instruction.  No MWAIT, no IO accesses,
no C-states deeper than C1.

If something is broken in the idle code,
"idle=halt" is a less severe workaround
than "idle=poll" which disables all power savings.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>

Showing 6 changed files with 45 additions and 2 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -818,7 +818,7 @@
818 818 See Documentation/ide/ide.txt.
819 819  
820 820 idle= [X86]
821   - Format: idle=poll or idle=mwait
  821 + Format: idle=poll or idle=mwait, idle=halt
822 822 Poll forces a polling idle loop that can slightly improves the performance
823 823 of waking up a idle CPU, but will use a lot of power and make the system
824 824 run hot. Not recommended.
... ... @@ -826,6 +826,8 @@
826 826 to not use it because it doesn't save as much power as a normal idle
827 827 loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
828 828 as idle=poll.
  829 + idle=halt. Halt is forced to be used for CPU idle.
  830 + In such case C2/C3 won't be used again.
829 831  
830 832 ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
831 833 Claim all unknown PCI IDE storage controllers.
arch/ia64/kernel/process.c
... ... @@ -55,6 +55,8 @@
55 55  
56 56 unsigned long boot_option_idle_override = 0;
57 57 EXPORT_SYMBOL(boot_option_idle_override);
  58 +unsigned long idle_halt;
  59 +EXPORT_SYMBOL(idle_halt);
58 60  
59 61 void
60 62 ia64_do_show_stack (struct unw_frame_info *info, void *arg)
arch/x86/kernel/process.c
... ... @@ -7,7 +7,11 @@
7 7 #include <linux/module.h>
8 8 #include <linux/pm.h>
9 9 #include <linux/clockchips.h>
  10 +#include <asm/system.h>
10 11  
  12 +unsigned long idle_halt;
  13 +EXPORT_SYMBOL(idle_halt);
  14 +
11 15 struct kmem_cache *task_xstate_cachep;
12 16  
13 17 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
... ... @@ -325,7 +329,18 @@
325 329 pm_idle = poll_idle;
326 330 } else if (!strcmp(str, "mwait"))
327 331 force_mwait = 1;
328   - else
  332 + else if (!strcmp(str, "halt")) {
  333 + /*
  334 + * When the boot option of idle=halt is added, halt is
  335 + * forced to be used for CPU idle. In such case CPU C2/C3
  336 + * won't be used again.
  337 + * To continue to load the CPU idle driver, don't touch
  338 + * the boot_option_idle_override.
  339 + */
  340 + pm_idle = default_idle;
  341 + idle_halt = 1;
  342 + return 0;
  343 + } else
329 344 return -1;
330 345  
331 346 boot_option_idle_override = 1;
drivers/acpi/processor_idle.c
... ... @@ -41,6 +41,7 @@
41 41 #include <linux/pm_qos_params.h>
42 42 #include <linux/clockchips.h>
43 43 #include <linux/cpuidle.h>
  44 +#include <linux/cpuidle.h>
44 45  
45 46 /*
46 47 * Include the apic definitions for x86 to have the APIC timer related defines
... ... @@ -57,6 +58,7 @@
57 58  
58 59 #include <acpi/acpi_bus.h>
59 60 #include <acpi/processor.h>
  61 +#include <asm/processor.h>
60 62  
61 63 #define ACPI_PROCESSOR_COMPONENT 0x01000000
62 64 #define ACPI_PROCESSOR_CLASS "processor"
... ... @@ -955,6 +957,17 @@
955 957 } else {
956 958 continue;
957 959 }
  960 + if (cx.type == ACPI_STATE_C1 && idle_halt) {
  961 + /*
  962 + * In most cases the C1 space_id obtained from
  963 + * _CST object is FIXED_HARDWARE access mode.
  964 + * But when the option of idle=halt is added,
  965 + * the entry_method type should be changed from
  966 + * CSTATE_FFH to CSTATE_HALT.
  967 + */
  968 + cx.entry_method = ACPI_CSTATE_HALT;
  969 + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
  970 + }
958 971 } else {
959 972 snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
960 973 cx.address);
... ... @@ -1780,6 +1793,15 @@
1780 1793 return 0;
1781 1794  
1782 1795 if (!first_run) {
  1796 + if (idle_halt) {
  1797 + /*
  1798 + * When the boot option of "idle=halt" is added, halt
  1799 + * is used for CPU IDLE.
  1800 + * In such case C2/C3 is meaningless. So the max_cstate
  1801 + * is set to one.
  1802 + */
  1803 + max_cstate = 1;
  1804 + }
1783 1805 dmi_check_system(processor_power_dmi_table);
1784 1806 max_cstate = acpi_processor_cstate_check(max_cstate);
1785 1807 if (max_cstate < ACPI_C_STATES_MAX)
include/asm-ia64/processor.h
... ... @@ -763,6 +763,7 @@
763 763 #define spin_lock_prefetch(x) prefetchw(x)
764 764  
765 765 extern unsigned long boot_option_idle_override;
  766 +extern unsigned long idle_halt;
766 767  
767 768 #endif /* !__ASSEMBLY__ */
768 769  
include/asm-x86/processor.h
... ... @@ -727,6 +727,7 @@
727 727 extern void select_idle_routine(const struct cpuinfo_x86 *c);
728 728  
729 729 extern unsigned long boot_option_idle_override;
  730 +extern unsigned long idle_halt;
730 731  
731 732 extern void enable_sep_cpu(void);
732 733 extern int sysenter_setup(void);