aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@alien8.de>2016-12-09 13:29:11 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-12-09 15:23:21 -0500
commit07c94a38125376d70d156bd8bff98ddfe4c8ea95 (patch)
treea4e22b8100ea51e42f9f3841d94e5b8fb6416e8f
parente7ff3a47630d9512d0bcbdfa73660021087ba445 (diff)
x86/amd: Simplify AMD E400 aware idle routine
Reorganize the E400 detection now that we have everything in place: switch the CPUs to broadcast mode after the LAPIC has been initialized and remove the facilities that were used previously on the idle path. Unfortunately static_cpu_has_bug() cannpt be used in the E400 idle routine because alternatives have been applied when the actual detection happens, so the static switching does not take effect and the test will stay false. Use boot_cpu_has_bug() instead which is definitely an improvement over the RDMSR and the cpumask handling. Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/20161209182912.2726-5-bp@alien8.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/include/asm/acpi.h2
-rw-r--r--arch/x86/include/asm/processor.h3
-rw-r--r--arch/x86/kernel/apic/apic.c2
-rw-r--r--arch/x86/kernel/cpu/common.c1
-rw-r--r--arch/x86/kernel/process.c75
-rw-r--r--arch/x86/kernel/smpboot.c1
-rw-r--r--drivers/acpi/processor_idle.c2
7 files changed, 31 insertions, 55 deletions
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 5391b0ae7cc3..395b69551fce 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -94,7 +94,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
94 boot_cpu_data.x86_model <= 0x05 && 94 boot_cpu_data.x86_model <= 0x05 &&
95 boot_cpu_data.x86_mask < 0x0A) 95 boot_cpu_data.x86_mask < 0x0A)
96 return 1; 96 return 1;
97 else if (amd_e400_c1e_detected) 97 else if (boot_cpu_has(X86_BUG_AMD_APIC_C1E))
98 return 1; 98 return 1;
99 else 99 else
100 return max_cstate; 100 return max_cstate;
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 984a7bf17f6a..fa609c6f6ba9 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -621,10 +621,9 @@ static inline void sync_core(void)
621} 621}
622 622
623extern void select_idle_routine(const struct cpuinfo_x86 *c); 623extern void select_idle_routine(const struct cpuinfo_x86 *c);
624extern void init_amd_e400_c1e_mask(void); 624extern void amd_e400_c1e_apic_setup(void);
625 625
626extern unsigned long boot_option_idle_override; 626extern unsigned long boot_option_idle_override;
627extern bool amd_e400_c1e_detected;
628 627
629enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, 628enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
630 IDLE_POLL}; 629 IDLE_POLL};
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 88c657b057e2..cc89ce200183 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -894,11 +894,13 @@ void __init setup_boot_APIC_clock(void)
894 894
895 /* Setup the lapic or request the broadcast */ 895 /* Setup the lapic or request the broadcast */
896 setup_APIC_timer(); 896 setup_APIC_timer();
897 amd_e400_c1e_apic_setup();
897} 898}
898 899
899void setup_secondary_APIC_clock(void) 900void setup_secondary_APIC_clock(void)
900{ 901{
901 setup_APIC_timer(); 902 setup_APIC_timer();
903 amd_e400_c1e_apic_setup();
902} 904}
903 905
904/* 906/*
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 9bd910a7dd0a..e1f98ff9a3f0 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1144,7 +1144,6 @@ void enable_sep_cpu(void)
1144void __init identify_boot_cpu(void) 1144void __init identify_boot_cpu(void)
1145{ 1145{
1146 identify_cpu(&boot_cpu_data); 1146 identify_cpu(&boot_cpu_data);
1147 init_amd_e400_c1e_mask();
1148#ifdef CONFIG_X86_32 1147#ifdef CONFIG_X86_32
1149 sysenter_setup(); 1148 sysenter_setup();
1150 enable_sep_cpu(); 1149 enable_sep_cpu();
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index ced76f13d20d..2c2b55ab41e7 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -289,59 +289,33 @@ void stop_this_cpu(void *dummy)
289 halt(); 289 halt();
290} 290}
291 291
292bool amd_e400_c1e_detected;
293EXPORT_SYMBOL(amd_e400_c1e_detected);
294
295static cpumask_var_t amd_e400_c1e_mask;
296
297void amd_e400_remove_cpu(int cpu)
298{
299 if (amd_e400_c1e_mask != NULL)
300 cpumask_clear_cpu(cpu, amd_e400_c1e_mask);
301}
302
303/* 292/*
304 * AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt 293 * AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
305 * pending message MSR. If we detect C1E, then we handle it the same 294 * states (local apic timer and TSC stop).
306 * way as C3 power states (local apic timer and TSC stop)
307 */ 295 */
308static void amd_e400_idle(void) 296static void amd_e400_idle(void)
309{ 297{
310 if (!amd_e400_c1e_detected) { 298 /*
311 u32 lo, hi; 299 * We cannot use static_cpu_has_bug() here because X86_BUG_AMD_APIC_C1E
312 300 * gets set after static_cpu_has() places have been converted via
313 rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi); 301 * alternatives.
314 302 */
315 if (lo & K8_INTP_C1E_ACTIVE_MASK) { 303 if (!boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
316 amd_e400_c1e_detected = true; 304 default_idle();
317 if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) 305 return;
318 mark_tsc_unstable("TSC halt in AMD C1E");
319 pr_info("System has AMD C1E enabled\n");
320 }
321 } 306 }
322 307
323 if (amd_e400_c1e_detected) { 308 tick_broadcast_enter();
324 int cpu = smp_processor_id();
325 309
326 if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) { 310 default_idle();
327 cpumask_set_cpu(cpu, amd_e400_c1e_mask);
328 /* Force broadcast so ACPI can not interfere. */
329 tick_broadcast_force();
330 pr_info("Switch to broadcast mode on CPU%d\n", cpu);
331 }
332 tick_broadcast_enter();
333 311
334 default_idle(); 312 /*
335 313 * The switch back from broadcast mode needs to be called with
336 /* 314 * interrupts disabled.
337 * The switch back from broadcast mode needs to be 315 */
338 * called with interrupts disabled. 316 local_irq_disable();
339 */ 317 tick_broadcast_exit();
340 local_irq_disable(); 318 local_irq_enable();
341 tick_broadcast_exit();
342 local_irq_enable();
343 } else
344 default_idle();
345} 319}
346 320
347/* 321/*
@@ -411,11 +385,14 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
411 x86_idle = default_idle; 385 x86_idle = default_idle;
412} 386}
413 387
414void __init init_amd_e400_c1e_mask(void) 388void amd_e400_c1e_apic_setup(void)
415{ 389{
416 /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */ 390 if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
417 if (x86_idle == amd_e400_idle) 391 pr_info("Switch to broadcast mode on CPU%d\n", smp_processor_id());
418 zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); 392 local_irq_disable();
393 tick_broadcast_force();
394 local_irq_enable();
395 }
419} 396}
420 397
421void __init arch_post_acpi_subsys_init(void) 398void __init arch_post_acpi_subsys_init(void)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 42f5eb7b4f6c..0229ccbfcd66 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1575,7 +1575,6 @@ void play_dead_common(void)
1575{ 1575{
1576 idle_task_exit(); 1576 idle_task_exit();
1577 reset_lazy_tlbstate(); 1577 reset_lazy_tlbstate();
1578 amd_e400_remove_cpu(raw_smp_processor_id());
1579 1578
1580 /* Ack it */ 1579 /* Ack it */
1581 (void)cpu_report_death(); 1580 (void)cpu_report_death();
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2237d3f24f0e..5c8aa9cf62d7 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -141,7 +141,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
141 if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) 141 if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
142 return; 142 return;
143 143
144 if (amd_e400_c1e_detected) 144 if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E))
145 type = ACPI_STATE_C1; 145 type = ACPI_STATE_C1;
146 146
147 /* 147 /*