2626#include <linux/kprobes.h>
2727#include <linux/nmi.h>
2828#include <linux/swait.h>
29+ #include <linux/syscore_ops.h>
2930#include <asm/timer.h>
3031#include <asm/cpu.h>
3132#include <asm/traps.h>
3738#include <asm/tlb.h>
3839#include <asm/cpuidle_haltpoll.h>
3940#include <asm/ptrace.h>
41+ #include <asm/reboot.h>
4042#include <asm/svm.h>
4143
4244DEFINE_STATIC_KEY_FALSE (kvm_async_pf_enabled );
@@ -345,7 +347,7 @@ static void kvm_guest_cpu_init(void)
345347
346348 wrmsrl (MSR_KVM_ASYNC_PF_EN , pa );
347349 __this_cpu_write (apf_reason .enabled , 1 );
348- pr_info ("KVM setup async PF for cpu %d\n" , smp_processor_id ());
350+ pr_info ("setup async PF for cpu %d\n" , smp_processor_id ());
349351 }
350352
351353 if (kvm_para_has_feature (KVM_FEATURE_PV_EOI )) {
@@ -371,34 +373,17 @@ static void kvm_pv_disable_apf(void)
371373 wrmsrl (MSR_KVM_ASYNC_PF_EN , 0 );
372374 __this_cpu_write (apf_reason .enabled , 0 );
373375
374- pr_info ("Unregister pv shared memory for cpu %d\n" , smp_processor_id ());
376+ pr_info ("disable async PF for cpu %d\n" , smp_processor_id ());
375377}
376378
377- static void kvm_pv_guest_cpu_reboot (void * unused )
379+ static void kvm_disable_steal_time (void )
378380{
379- /*
380- * We disable PV EOI before we load a new kernel by kexec,
381- * since MSR_KVM_PV_EOI_EN stores a pointer into old kernel's memory.
382- * New kernel can re-enable when it boots.
383- */
384- if (kvm_para_has_feature (KVM_FEATURE_PV_EOI ))
385- wrmsrl (MSR_KVM_PV_EOI_EN , 0 );
386- kvm_pv_disable_apf ();
387- kvm_disable_steal_time ();
388- }
381+ if (!has_steal_clock )
382+ return ;
389383
390- static int kvm_pv_reboot_notify (struct notifier_block * nb ,
391- unsigned long code , void * unused )
392- {
393- if (code == SYS_RESTART )
394- on_each_cpu (kvm_pv_guest_cpu_reboot , NULL , 1 );
395- return NOTIFY_DONE ;
384+ wrmsr (MSR_KVM_STEAL_TIME , 0 , 0 );
396385}
397386
398- static struct notifier_block kvm_pv_reboot_nb = {
399- .notifier_call = kvm_pv_reboot_notify ,
400- };
401-
402387static u64 kvm_steal_clock (int cpu )
403388{
404389 u64 steal ;
@@ -416,14 +401,6 @@ static u64 kvm_steal_clock(int cpu)
416401 return steal ;
417402}
418403
419- void kvm_disable_steal_time (void )
420- {
421- if (!has_steal_clock )
422- return ;
423-
424- wrmsr (MSR_KVM_STEAL_TIME , 0 , 0 );
425- }
426-
427404static inline void __set_percpu_decrypted (void * ptr , unsigned long size )
428405{
429406 early_set_memory_decrypted ((unsigned long ) ptr , size );
@@ -451,6 +428,27 @@ static void __init sev_map_percpu_data(void)
451428 }
452429}
453430
431+ static void kvm_guest_cpu_offline (bool shutdown )
432+ {
433+ kvm_disable_steal_time ();
434+ if (kvm_para_has_feature (KVM_FEATURE_PV_EOI ))
435+ wrmsrl (MSR_KVM_PV_EOI_EN , 0 );
436+ kvm_pv_disable_apf ();
437+ if (!shutdown )
438+ apf_task_wake_all ();
439+ kvmclock_disable ();
440+ }
441+
442+ static int kvm_cpu_online (unsigned int cpu )
443+ {
444+ unsigned long flags ;
445+
446+ local_irq_save (flags );
447+ kvm_guest_cpu_init ();
448+ local_irq_restore (flags );
449+ return 0 ;
450+ }
451+
454452#ifdef CONFIG_SMP
455453
456454static DEFINE_PER_CPU (cpumask_var_t , __pv_cpu_mask ) ;
@@ -635,31 +633,64 @@ static void __init kvm_smp_prepare_boot_cpu(void)
635633 kvm_spinlock_init ();
636634}
637635
638- static void kvm_guest_cpu_offline ( void )
636+ static int kvm_cpu_down_prepare ( unsigned int cpu )
639637{
640- kvm_disable_steal_time ();
641- if (kvm_para_has_feature (KVM_FEATURE_PV_EOI ))
642- wrmsrl (MSR_KVM_PV_EOI_EN , 0 );
643- kvm_pv_disable_apf ();
644- apf_task_wake_all ();
638+ unsigned long flags ;
639+
640+ local_irq_save (flags );
641+ kvm_guest_cpu_offline (false);
642+ local_irq_restore (flags );
643+ return 0 ;
645644}
646645
647- static int kvm_cpu_online (unsigned int cpu )
646+ #endif
647+
648+ static int kvm_suspend (void )
648649{
649- local_irq_disable ();
650- kvm_guest_cpu_init ();
651- local_irq_enable ();
650+ kvm_guest_cpu_offline (false);
651+
652652 return 0 ;
653653}
654654
655- static int kvm_cpu_down_prepare ( unsigned int cpu )
655+ static void kvm_resume ( void )
656656{
657- local_irq_disable ();
658- kvm_guest_cpu_offline ();
659- local_irq_enable ();
660- return 0 ;
657+ kvm_cpu_online (raw_smp_processor_id ());
658+ }
659+
660+ static struct syscore_ops kvm_syscore_ops = {
661+ .suspend = kvm_suspend ,
662+ .resume = kvm_resume ,
663+ };
664+
665+ static void kvm_pv_guest_cpu_reboot (void * unused )
666+ {
667+ kvm_guest_cpu_offline (true);
668+ }
669+
670+ static int kvm_pv_reboot_notify (struct notifier_block * nb ,
671+ unsigned long code , void * unused )
672+ {
673+ if (code == SYS_RESTART )
674+ on_each_cpu (kvm_pv_guest_cpu_reboot , NULL , 1 );
675+ return NOTIFY_DONE ;
661676}
662677
678+ static struct notifier_block kvm_pv_reboot_nb = {
679+ .notifier_call = kvm_pv_reboot_notify ,
680+ };
681+
682+ /*
683+ * After a PV feature is registered, the host will keep writing to the
684+ * registered memory location. If the guest happens to shutdown, this memory
685+ * won't be valid. In cases like kexec, in which you install a new kernel, this
686+ * means a random memory location will be kept being written.
687+ */
688+ #ifdef CONFIG_KEXEC_CORE
689+ static void kvm_crash_shutdown (struct pt_regs * regs )
690+ {
691+ kvm_guest_cpu_offline (true);
692+ native_machine_crash_shutdown (regs );
693+ }
663694#endif
664695
665696static void __init kvm_guest_init (void )
@@ -704,6 +735,12 @@ static void __init kvm_guest_init(void)
704735 kvm_guest_cpu_init ();
705736#endif
706737
738+ #ifdef CONFIG_KEXEC_CORE
739+ machine_ops .crash_shutdown = kvm_crash_shutdown ;
740+ #endif
741+
742+ register_syscore_ops (& kvm_syscore_ops );
743+
707744 /*
708745 * Hard lockup detection is enabled by default. Disable it, as guests
709746 * can get false positives too easily, for example if the host is
0 commit comments