Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'hyperv-fixes-signed-20210111' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv fixes from Wei Liu:

- fix kexec panic/hang (Dexuan Cui)

- fix occasional crashes when flushing TLB (Wei Liu)

* tag 'hyperv-fixes-signed-20210111' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
x86/hyperv: check cpu mask after interrupt has been disabled
x86/hyperv: Fix kexec panic/hang issues

+33 -5
+4
arch/x86/hyperv/hv_init.c
··· 16 16 #include <asm/hyperv-tlfs.h> 17 17 #include <asm/mshyperv.h> 18 18 #include <asm/idtentry.h> 19 + #include <linux/kexec.h> 19 20 #include <linux/version.h> 20 21 #include <linux/vmalloc.h> 21 22 #include <linux/mm.h> ··· 26 25 #include <linux/cpuhotplug.h> 27 26 #include <linux/syscore_ops.h> 28 27 #include <clocksource/hyperv_timer.h> 28 + 29 + int hyperv_init_cpuhp; 29 30 30 31 void *hv_hypercall_pg; 31 32 EXPORT_SYMBOL_GPL(hv_hypercall_pg); ··· 404 401 405 402 register_syscore_ops(&hv_syscore_ops); 406 403 404 + hyperv_init_cpuhp = cpuhp; 407 405 return; 408 406 409 407 remove_cpuhp_state:
+9 -3
arch/x86/hyperv/mmu.c
··· 66 66 if (!hv_hypercall_pg) 67 67 goto do_native; 68 68 69 - if (cpumask_empty(cpus)) 70 - return; 71 - 72 69 local_irq_save(flags); 70 + 71 + /* 72 + * Only check the mask _after_ interrupt has been disabled to avoid the 73 + * mask changing under our feet. 74 + */ 75 + if (cpumask_empty(cpus)) { 76 + local_irq_restore(flags); 77 + return; 78 + } 73 79 74 80 flush_pcpu = (struct hv_tlb_flush **) 75 81 this_cpu_ptr(hyperv_pcpu_input_arg);
+2
arch/x86/include/asm/mshyperv.h
··· 74 74 75 75 76 76 #if IS_ENABLED(CONFIG_HYPERV) 77 + extern int hyperv_init_cpuhp; 78 + 77 79 extern void *hv_hypercall_pg; 78 80 extern void __percpu **hyperv_pcpu_input_arg; 79 81
+18
arch/x86/kernel/cpu/mshyperv.c
··· 135 135 { 136 136 if (kexec_in_progress && hv_kexec_handler) 137 137 hv_kexec_handler(); 138 + 139 + /* 140 + * Call hv_cpu_die() on all the CPUs, otherwise later the hypervisor 141 + * corrupts the old VP Assist Pages and can crash the kexec kernel. 142 + */ 143 + if (kexec_in_progress && hyperv_init_cpuhp > 0) 144 + cpuhp_remove_state(hyperv_init_cpuhp); 145 + 146 + /* The function calls stop_other_cpus(). */ 138 147 native_machine_shutdown(); 148 + 149 + /* Disable the hypercall page when there is only 1 active CPU. */ 150 + if (kexec_in_progress) 151 + hyperv_cleanup(); 139 152 } 140 153 141 154 static void hv_machine_crash_shutdown(struct pt_regs *regs) 142 155 { 143 156 if (hv_crash_handler) 144 157 hv_crash_handler(regs); 158 + 159 + /* The function calls crash_smp_send_stop(). */ 145 160 native_machine_crash_shutdown(regs); 161 + 162 + /* Disable the hypercall page when there is only 1 active CPU. */ 163 + hyperv_cleanup(); 146 164 } 147 165 #endif /* CONFIG_KEXEC_CORE */ 148 166 #endif /* CONFIG_HYPERV */
-2
drivers/hv/vmbus_drv.c
··· 2550 2550 /* Make sure conn_state is set as hv_synic_cleanup checks for it */ 2551 2551 mb(); 2552 2552 cpuhp_remove_state(hyperv_cpuhp_online); 2553 - hyperv_cleanup(); 2554 2553 }; 2555 2554 2556 2555 static void hv_crash_handler(struct pt_regs *regs) ··· 2565 2566 cpu = smp_processor_id(); 2566 2567 hv_stimer_cleanup(cpu); 2567 2568 hv_synic_disable_regs(cpu); 2568 - hyperv_cleanup(); 2569 2569 }; 2570 2570 2571 2571 static int hv_synic_suspend(void)