Commit c84cb373 authored by Thomas Gleixner's avatar Thomas Gleixner

x86/apic: Move TSC deadline timer debug printk

Leon reported that the printk_once() in __setup_APIC_LVTT() triggers a
lockdep splat due to a lock order violation between hrtimer_base::lock and
console_sem, when the 'once' condition is reset via
/sys/kernel/debug/clear_warn_once after boot.

The initial printk cannot trigger this because that happens during boot
when the local APIC timer is set up on the boot CPU.

Prevent it by moving the printk to a place which is guaranteed to be only
called once during boot.

Mark the deadline timer check related functions and data __init while at
it.
Reported-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87y2qhoshi.fsf@nanos.tec.linutronix.de
parent fdc63ff0
...@@ -352,8 +352,6 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) ...@@ -352,8 +352,6 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
* According to Intel, MFENCE can do the serialization here. * According to Intel, MFENCE can do the serialization here.
*/ */
asm volatile("mfence" : : : "memory"); asm volatile("mfence" : : : "memory");
printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
return; return;
} }
...@@ -546,7 +544,7 @@ static struct clock_event_device lapic_clockevent = { ...@@ -546,7 +544,7 @@ static struct clock_event_device lapic_clockevent = {
}; };
static DEFINE_PER_CPU(struct clock_event_device, lapic_events); static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
static u32 hsx_deadline_rev(void) static __init u32 hsx_deadline_rev(void)
{ {
switch (boot_cpu_data.x86_stepping) { switch (boot_cpu_data.x86_stepping) {
case 0x02: return 0x3a; /* EP */ case 0x02: return 0x3a; /* EP */
...@@ -556,7 +554,7 @@ static u32 hsx_deadline_rev(void) ...@@ -556,7 +554,7 @@ static u32 hsx_deadline_rev(void)
return ~0U; return ~0U;
} }
static u32 bdx_deadline_rev(void) static __init u32 bdx_deadline_rev(void)
{ {
switch (boot_cpu_data.x86_stepping) { switch (boot_cpu_data.x86_stepping) {
case 0x02: return 0x00000011; case 0x02: return 0x00000011;
...@@ -568,7 +566,7 @@ static u32 bdx_deadline_rev(void) ...@@ -568,7 +566,7 @@ static u32 bdx_deadline_rev(void)
return ~0U; return ~0U;
} }
static u32 skx_deadline_rev(void) static __init u32 skx_deadline_rev(void)
{ {
switch (boot_cpu_data.x86_stepping) { switch (boot_cpu_data.x86_stepping) {
case 0x03: return 0x01000136; case 0x03: return 0x01000136;
...@@ -581,7 +579,7 @@ static u32 skx_deadline_rev(void) ...@@ -581,7 +579,7 @@ static u32 skx_deadline_rev(void)
return ~0U; return ~0U;
} }
static const struct x86_cpu_id deadline_match[] = { static const struct x86_cpu_id deadline_match[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL( HASWELL_X, &hsx_deadline_rev), X86_MATCH_INTEL_FAM6_MODEL( HASWELL_X, &hsx_deadline_rev),
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_X, 0x0b000020), X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_X, 0x0b000020),
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_D, &bdx_deadline_rev), X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_D, &bdx_deadline_rev),
...@@ -603,18 +601,19 @@ static const struct x86_cpu_id deadline_match[] = { ...@@ -603,18 +601,19 @@ static const struct x86_cpu_id deadline_match[] = {
{}, {},
}; };
static void apic_check_deadline_errata(void) static __init bool apic_validate_deadline_timer(void)
{ {
const struct x86_cpu_id *m; const struct x86_cpu_id *m;
u32 rev; u32 rev;
if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) || if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
boot_cpu_has(X86_FEATURE_HYPERVISOR)) return false;
return; if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
return true;
m = x86_match_cpu(deadline_match); m = x86_match_cpu(deadline_match);
if (!m) if (!m)
return; return true;
/* /*
* Function pointers will have the MSB set due to address layout, * Function pointers will have the MSB set due to address layout,
...@@ -626,11 +625,12 @@ static void apic_check_deadline_errata(void) ...@@ -626,11 +625,12 @@ static void apic_check_deadline_errata(void)
rev = (u32)m->driver_data; rev = (u32)m->driver_data;
if (boot_cpu_data.microcode >= rev) if (boot_cpu_data.microcode >= rev)
return; return true;
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; " pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
"please update microcode to version: 0x%x (or later)\n", rev); "please update microcode to version: 0x%x (or later)\n", rev);
return false;
} }
/* /*
...@@ -2092,7 +2092,8 @@ void __init init_apic_mappings(void) ...@@ -2092,7 +2092,8 @@ void __init init_apic_mappings(void)
{ {
unsigned int new_apicid; unsigned int new_apicid;
apic_check_deadline_errata(); if (apic_validate_deadline_timer())
pr_debug("TSC deadline timer available\n");
if (x2apic_mode) { if (x2apic_mode) {
boot_cpu_physical_apicid = read_apic_id(); boot_cpu_physical_apicid = read_apic_id();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment