From: Sasha Levin Date: Wed, 20 Jan 2021 23:43:34 +0000 (-0500) Subject: Fixes for 5.10 X-Git-Tag: v4.4.253~25^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=78c5411be133b69eb9c0509478d0b34ea6575ea8;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/series b/queue-5.10/series index 3a029d03eee..f3a2ebb2128 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 00000000000..a8de60662b9 --- /dev/null +++ b/queue-5.10/x86-hyperv-initialize-clockevents-after-lapic-is-ini.patch @@ -0,0 +1,114 @@ +From 9afc1d6f5aa8bce4c67532b35fd6219c7064bd7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Jan 2021 14:31:36 -0800 +Subject: x86/hyperv: Initialize clockevents after LAPIC is initialized + +From: Dexuan Cui + +[ 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 +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20210116223136.13892-1-decui@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + 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 +