aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2007-05-02 13:27:12 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:12 -0400
commitf039b754714a422959027cb18bb33760eb8153f0 (patch)
treec5f28502adf35f5ea7738a974cd7c4fc81e1dd21
parentc169859d6dfc7471ef9f2dbd720936e17906a084 (diff)
[PATCH] x86: Don't use MWAIT on AMD Family 10
It doesn't put the CPU into deeper sleep states, so it's better to use the standard idle loop to save power. But allow to reenable it anyways for benchmarking. I also removed the obsolete idle=halt on i386 Cc: andreas.herrmann@amd.com Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--arch/i386/kernel/cpu/amd.c5
-rw-r--r--arch/i386/kernel/process.c17
-rw-r--r--arch/x86_64/kernel/process.c12
-rw-r--r--arch/x86_64/kernel/setup.c6
-rw-r--r--include/asm-i386/processor.h2
-rw-r--r--include/asm-x86_64/proto.h2
7 files changed, 39 insertions, 16 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4287696f18dd..94ce0d20253d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -695,8 +695,15 @@ and is between 256 and 4096 characters. It is defined in the file
695 idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed 695 idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed
696 See Documentation/ide.txt. 696 See Documentation/ide.txt.
697 697
698 idle= [HW] 698 idle= [X86]
699 Format: idle=poll or idle=halt 699 Format: idle=poll or idle=mwait
700 Poll forces a polling idle loop that can slightly improves the performance
701 of waking up a idle CPU, but will use a lot of power and make the system
702 run hot. Not recommended.
703 idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
704 to not use it because it doesn't save as much power as a normal idle
705 loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
706 as idle=poll.
700 707
701 ignore_loglevel [KNL] 708 ignore_loglevel [KNL]
702 Ignore loglevel setting - this will print /all/ 709 Ignore loglevel setting - this will print /all/
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 2d47db482972..197cda62caa3 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -53,6 +53,8 @@ static __cpuinit int amd_apic_timer_broken(void)
53 return 0; 53 return 0;
54} 54}
55 55
56int force_mwait __cpuinitdata;
57
56static void __cpuinit init_amd(struct cpuinfo_x86 *c) 58static void __cpuinit init_amd(struct cpuinfo_x86 *c)
57{ 59{
58 u32 l, h; 60 u32 l, h;
@@ -275,6 +277,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
275 277
276 if (amd_apic_timer_broken()) 278 if (amd_apic_timer_broken())
277 set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability); 279 set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability);
280
281 if (c->x86 == 0x10 && !force_mwait)
282 clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
278} 283}
279 284
280static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) 285static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 393a67d5d943..7e8e129b3d7d 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -272,25 +272,24 @@ void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
272 } 272 }
273} 273}
274 274
275static int __init idle_setup (char *str) 275static int __init idle_setup(char *str)
276{ 276{
277 if (!strncmp(str, "poll", 4)) { 277 if (!strcmp(str, "poll")) {
278 printk("using polling idle threads.\n"); 278 printk("using polling idle threads.\n");
279 pm_idle = poll_idle; 279 pm_idle = poll_idle;
280#ifdef CONFIG_X86_SMP 280#ifdef CONFIG_X86_SMP
281 if (smp_num_siblings > 1) 281 if (smp_num_siblings > 1)
282 printk("WARNING: polling idle and HT enabled, performance may degrade.\n"); 282 printk("WARNING: polling idle and HT enabled, performance may degrade.\n");
283#endif 283#endif
284 } else if (!strncmp(str, "halt", 4)) { 284 } else if (!strcmp(str, "mwait"))
285 printk("using halt in idle threads.\n"); 285 force_mwait = 1;
286 pm_idle = default_idle; 286 else
287 } 287 return -1;
288 288
289 boot_option_idle_override = 1; 289 boot_option_idle_override = 1;
290 return 1; 290 return 0;
291} 291}
292 292early_param("idle", idle_setup);
293__setup("idle=", idle_setup);
294 293
295void show_regs(struct pt_regs * regs) 294void show_regs(struct pt_regs * regs)
296{ 295{
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index d8d5ccc245c8..4f21765078b7 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -288,16 +288,18 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
288 288
289static int __init idle_setup (char *str) 289static int __init idle_setup (char *str)
290{ 290{
291 if (!strncmp(str, "poll", 4)) { 291 if (!strcmp(str, "poll")) {
292 printk("using polling idle threads.\n"); 292 printk("using polling idle threads.\n");
293 pm_idle = poll_idle; 293 pm_idle = poll_idle;
294 } 294 } else if (!strcmp(str, "mwait"))
295 force_mwait = 1;
296 else
297 return -1;
295 298
296 boot_option_idle_override = 1; 299 boot_option_idle_override = 1;
297 return 1; 300 return 0;
298} 301}
299 302early_param("idle", idle_setup);
300__setup("idle=", idle_setup);
301 303
302/* Prints also some state that isn't saved in the pt_regs */ 304/* Prints also some state that isn't saved in the pt_regs */
303void __show_regs(struct pt_regs * regs) 305void __show_regs(struct pt_regs * regs)
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 0a1d539149df..db30b5bcef61 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -79,6 +79,8 @@ int bootloader_type;
79 79
80unsigned long saved_video_mode; 80unsigned long saved_video_mode;
81 81
82int force_mwait __cpuinitdata;
83
82/* 84/*
83 * Early DMI memory 85 * Early DMI memory
84 */ 86 */
@@ -604,6 +606,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
604 606
605 /* RDTSC can be speculated around */ 607 /* RDTSC can be speculated around */
606 clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); 608 clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
609
610 /* Family 10 doesn't support C states in MWAIT so don't use it */
611 if (c->x86 == 0x10 && !force_mwait)
612 clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
607} 613}
608 614
609static void __cpuinit detect_ht(struct cpuinfo_x86 *c) 615static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 9d895cc2f312..882d3f8fbbac 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -779,4 +779,6 @@ extern int sysenter_setup(void);
779extern void cpu_set_gdt(int); 779extern void cpu_set_gdt(int);
780extern void cpu_init(void); 780extern void cpu_init(void);
781 781
782extern int force_mwait;
783
782#endif /* __ASM_I386_PROCESSOR_H */ 784#endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 3f8f285138d2..98063bcb3b33 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -119,6 +119,8 @@ extern int gsi_irq_sharing(int gsi);
119 119
120extern void smp_local_timer_interrupt(void); 120extern void smp_local_timer_interrupt(void);
121 121
122extern int force_mwait;
123
122long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); 124long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
123 125
124void i8254_timer_resume(void); 126void i8254_timer_resume(void);