]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.5-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 9 Feb 2020 21:15:53 +0000 (22:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 9 Feb 2020 21:15:53 +0000 (22:15 +0100)
added patches:
x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch

queue-5.5/series
queue-5.5/x86-timer-don-t-skip-pit-setup-when-apic-is-disabled-or-in-legacy-mode.patch [new file with mode: 0644]

index 7afc82be5a9eed554a56ad03e7d3fa7b321f66d5..71e2e0b176f14614b78489c3503cf870fe003153 100644 (file)
@@ -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 (file)
index 0000000..f328c7f
--- /dev/null
@@ -0,0 +1,177 @@
+From 979923871f69a4dc926658f9f9a1a4c1bde57552 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+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 <tglx@linutronix.de>
+
+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 <tony.buckley000@gmail.com>
+Tested-by: Anthony Buckley <tony.buckley000@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Daniel Drake <drake@endlessm.com>
+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 <gregkh@linuxfoundation.org>
+
+---
+ 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;