From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 21:15:53 +0000 (+0100) Subject: 5.5-stable patches X-Git-Tag: v4.19.103~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da10970e789f63f44f8c0aeb0c65ca5e6f5889a4;p=thirdparty%2Fkernel%2Fstable-queue.git 5.5-stable patches added patches: x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch --- diff --git a/queue-5.5/series b/queue-5.5/series index 7afc82be5a9..71e2e0b176f 100644 --- a/queue-5.5/series +++ b/queue-5.5/series @@ -311,3 +311,4 @@ mfd-bd70528-fix-hour-register-mask.patch mfd-ab8500-fix-ab8500-clk-typo.patch bpf-fix-trampoline-usage-in-preempt.patch libbpf-extract-and-generalize-cpu-mask-parsing-logic.patch +x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch diff --git a/queue-5.5/x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch b/queue-5.5/x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch new file mode 100644 index 00000000000..f328c7f941f --- /dev/null +++ b/queue-5.5/x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch @@ -0,0 +1,177 @@ +From 979923871f69a4dc926658f9f9a1a4c1bde57552 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 23 Jan 2020 12:54:53 +0100 +Subject: x86/timer: Don't skip PIT setup when APIC is disabled or in legacy mode + +From: Thomas Gleixner + +commit 979923871f69a4dc926658f9f9a1a4c1bde57552 upstream. + +Tony reported a boot regression caused by the recent workaround for systems +which have a disabled (clock gate off) PIT. + +On his machine the kernel fails to initialize the PIT because +apic_needs_pit() does not take into account whether the local APIC +interrupt delivery mode will actually allow to setup and use the local +APIC timer. This should be easy to reproduce with acpi=off on the +command line which also disables HPET. + +Due to the way the PIT/HPET and APIC setup ordering works (APIC setup can +require working PIT/HPET) the information is not available at the point +where apic_needs_pit() makes this decision. + +To address this, split out the interrupt mode selection from +apic_intr_mode_init(), invoke the selection before making the decision +whether PIT is required or not, and add the missing checks into +apic_needs_pit(). + +Fixes: c8c4076723da ("x86/timer: Skip PIT initialization on modern chipsets") +Reported-by: Anthony Buckley +Tested-by: Anthony Buckley +Signed-off-by: Thomas Gleixner +Signed-off-by: Ingo Molnar +Cc: Daniel Drake +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206125 +Link: https://lore.kernel.org/r/87sgk6tmk2.fsf@nanos.tec.linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/apic.h | 2 ++ + arch/x86/include/asm/x86_init.h | 2 ++ + arch/x86/kernel/apic/apic.c | 23 ++++++++++++++++++----- + arch/x86/kernel/time.c | 12 ++++++++++-- + arch/x86/kernel/x86_init.c | 1 + + arch/x86/xen/enlighten_pv.c | 1 + + 6 files changed, 34 insertions(+), 7 deletions(-) + +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -140,6 +140,7 @@ extern void apic_soft_disable(void); + extern void lapic_shutdown(void); + extern void sync_Arb_IDs(void); + extern void init_bsp_APIC(void); ++extern void apic_intr_mode_select(void); + extern void apic_intr_mode_init(void); + extern void init_apic_mappings(void); + void register_lapic_address(unsigned long address); +@@ -188,6 +189,7 @@ static inline void disable_local_APIC(vo + # define setup_secondary_APIC_clock x86_init_noop + static inline void lapic_update_tsc_freq(void) { } + static inline void init_bsp_APIC(void) { } ++static inline void apic_intr_mode_select(void) { } + static inline void apic_intr_mode_init(void) { } + static inline void lapic_assign_system_vectors(void) { } + static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { } +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -51,12 +51,14 @@ struct x86_init_resources { + * are set up. + * @intr_init: interrupt init code + * @trap_init: platform specific trap setup ++ * @intr_mode_select: interrupt delivery mode selection + * @intr_mode_init: interrupt delivery mode setup + */ + struct x86_init_irqs { + void (*pre_vector_init)(void); + void (*intr_init)(void); + void (*trap_init)(void); ++ void (*intr_mode_select)(void); + void (*intr_mode_init)(void); + }; + +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -830,8 +830,17 @@ bool __init apic_needs_pit(void) + if (!tsc_khz || !cpu_khz) + return true; + +- /* Is there an APIC at all? */ +- if (!boot_cpu_has(X86_FEATURE_APIC)) ++ /* Is there an APIC at all or is it disabled? */ ++ if (!boot_cpu_has(X86_FEATURE_APIC) || disable_apic) ++ return true; ++ ++ /* ++ * If interrupt delivery mode is legacy PIC or virtual wire without ++ * configuration, the local APIC timer wont be set up. Make sure ++ * that the PIT is initialized. ++ */ ++ if (apic_intr_mode == APIC_PIC || ++ apic_intr_mode == APIC_VIRTUAL_WIRE_NO_CONFIG) + return true; + + /* Virt guests may lack ARAT, but still have DEADLINE */ +@@ -1322,7 +1331,7 @@ void __init sync_Arb_IDs(void) + + enum apic_intr_mode_id apic_intr_mode __ro_after_init; + +-static int __init apic_intr_mode_select(void) ++static int __init __apic_intr_mode_select(void) + { + /* Check kernel option */ + if (disable_apic) { +@@ -1384,6 +1393,12 @@ static int __init apic_intr_mode_select( + return APIC_SYMMETRIC_IO; + } + ++/* Select the interrupt delivery mode for the BSP */ ++void __init apic_intr_mode_select(void) ++{ ++ apic_intr_mode = __apic_intr_mode_select(); ++} ++ + /* + * An initial setup of the virtual wire mode. + */ +@@ -1440,8 +1455,6 @@ void __init apic_intr_mode_init(void) + { + bool upmode = IS_ENABLED(CONFIG_UP_LATE_INIT); + +- apic_intr_mode = apic_intr_mode_select(); +- + switch (apic_intr_mode) { + case APIC_PIC: + pr_info("APIC: Keep in PIC mode(8259)\n"); +--- a/arch/x86/kernel/time.c ++++ b/arch/x86/kernel/time.c +@@ -91,10 +91,18 @@ void __init hpet_time_init(void) + + static __init void x86_late_time_init(void) + { ++ /* ++ * Before PIT/HPET init, select the interrupt mode. This is required ++ * to make the decision whether PIT should be initialized correct. ++ */ ++ x86_init.irqs.intr_mode_select(); ++ ++ /* Setup the legacy timers */ + x86_init.timers.timer_init(); ++ + /* +- * After PIT/HPET timers init, select and setup +- * the final interrupt mode for delivering IRQs. ++ * After PIT/HPET timers init, set up the final interrupt mode for ++ * delivering IRQs. + */ + x86_init.irqs.intr_mode_init(); + tsc_init(); +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -80,6 +80,7 @@ struct x86_init_ops x86_init __initdata + .pre_vector_init = init_ISA_irqs, + .intr_init = native_init_IRQ, + .trap_init = x86_init_noop, ++ .intr_mode_select = apic_intr_mode_select, + .intr_mode_init = apic_intr_mode_init + }, + +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -1205,6 +1205,7 @@ asmlinkage __visible void __init xen_sta + x86_platform.get_nmi_reason = xen_get_nmi_reason; + + x86_init.resources.memory_setup = xen_memory_setup; ++ x86_init.irqs.intr_mode_select = x86_init_noop; + x86_init.irqs.intr_mode_init = x86_init_noop; + x86_init.oem.arch_setup = xen_arch_setup; + x86_init.oem.banner = xen_banner;