]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Wed, 20 Jan 2021 23:43:34 +0000 (18:43 -0500)
committerSasha Levin <sashal@kernel.org>
Wed, 20 Jan 2021 23:43:34 +0000 (18:43 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/series
queue-5.10/x86-hyperv-initialize-clockevents-after-lapic-is-ini.patch [new file with mode: 0644]

index 3a029d03eeeb21f2acb52e1c10c42ea1482d70c7..f3a2ebb21287e9b01991c71290ed63cf0d720e00 100644 (file)
@@ -1 +1,2 @@
 revert-kconfig-remove-kvmconfig-and-xenconfig-shorthands.patch
+x86-hyperv-initialize-clockevents-after-lapic-is-ini.patch
diff --git a/queue-5.10/x86-hyperv-initialize-clockevents-after-lapic-is-ini.patch b/queue-5.10/x86-hyperv-initialize-clockevents-after-lapic-is-ini.patch
new file mode 100644 (file)
index 0000000..a8de606
--- /dev/null
@@ -0,0 +1,114 @@
+From 9afc1d6f5aa8bce4c67532b35fd6219c7064bd7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Jan 2021 14:31:36 -0800
+Subject: x86/hyperv: Initialize clockevents after LAPIC is initialized
+
+From: Dexuan Cui <decui@microsoft.com>
+
+[ Upstream commit fff7b5e6ee63c5d20406a131b260c619cdd24fd1 ]
+
+With commit 4df4cb9e99f8, the Hyper-V direct-mode STIMER is actually
+initialized before LAPIC is initialized: see
+
+  apic_intr_mode_init()
+
+    x86_platform.apic_post_init()
+      hyperv_init()
+        hv_stimer_alloc()
+
+    apic_bsp_setup()
+      setup_local_APIC()
+
+setup_local_APIC() temporarily disables LAPIC, initializes it and
+re-eanble it.  The direct-mode STIMER depends on LAPIC, and when it's
+registered, it can be programmed immediately and the timer can fire
+very soon:
+
+  hv_stimer_init
+    clockevents_config_and_register
+      clockevents_register_device
+        tick_check_new_device
+          tick_setup_device
+            tick_setup_periodic(), tick_setup_oneshot()
+              clockevents_program_event
+
+When the timer fires in the hypervisor, if the LAPIC is in the
+disabled state, new versions of Hyper-V ignore the event and don't inject
+the timer interrupt into the VM, and hence the VM hangs when it boots.
+
+Note: when the VM starts/reboots, the LAPIC is pre-enabled by the
+firmware, so the window of LAPIC being temporarily disabled is pretty
+small, and the issue can only happen once out of 100~200 reboots for
+a 40-vCPU VM on one dev host, and on another host the issue doesn't
+reproduce after 2000 reboots.
+
+The issue is more noticeable for kdump/kexec, because the LAPIC is
+disabled by the first kernel, and stays disabled until the kdump/kexec
+kernel enables it. This is especially an issue to a Generation-2 VM
+(for which Hyper-V doesn't emulate the PIT timer) when CONFIG_HZ=1000
+(rather than CONFIG_HZ=250) is used.
+
+Fix the issue by moving hv_stimer_alloc() to a later place where the
+LAPIC timer is initialized.
+
+Fixes: 4df4cb9e99f8 ("x86/hyperv: Initialize clockevents earlier in CPU onlining")
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Reviewed-by:  Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/20210116223136.13892-1-decui@microsoft.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/hyperv/hv_init.c | 29 ++++++++++++++++++++++++++---
+ 1 file changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
+index e04d90af4c27c..6fb8cb7b9bcc6 100644
+--- a/arch/x86/hyperv/hv_init.c
++++ b/arch/x86/hyperv/hv_init.c
+@@ -312,6 +312,25 @@ static struct syscore_ops hv_syscore_ops = {
+       .resume         = hv_resume,
+ };
++static void (* __initdata old_setup_percpu_clockev)(void);
++
++static void __init hv_stimer_setup_percpu_clockev(void)
++{
++      /*
++       * Ignore any errors in setting up stimer clockevents
++       * as we can run with the LAPIC timer as a fallback.
++       */
++      (void)hv_stimer_alloc();
++
++      /*
++       * Still register the LAPIC timer, because the direct-mode STIMER is
++       * not supported by old versions of Hyper-V. This also allows users
++       * to switch to LAPIC timer via /sys, if they want to.
++       */
++      if (old_setup_percpu_clockev)
++              old_setup_percpu_clockev();
++}
++
+ /*
+  * This function is to be invoked early in the boot sequence after the
+  * hypervisor has been detected.
+@@ -390,10 +409,14 @@ void __init hyperv_init(void)
+       wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+       /*
+-       * Ignore any errors in setting up stimer clockevents
+-       * as we can run with the LAPIC timer as a fallback.
++       * hyperv_init() is called before LAPIC is initialized: see
++       * apic_intr_mode_init() -> x86_platform.apic_post_init() and
++       * apic_bsp_setup() -> setup_local_APIC(). The direct-mode STIMER
++       * depends on LAPIC, so hv_stimer_alloc() should be called from
++       * x86_init.timers.setup_percpu_clockev.
+        */
+-      (void)hv_stimer_alloc();
++      old_setup_percpu_clockev = x86_init.timers.setup_percpu_clockev;
++      x86_init.timers.setup_percpu_clockev = hv_stimer_setup_percpu_clockev;
+       hv_apic_init();
+-- 
+2.27.0
+