1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/types.h> 3 #include <linux/tick.h> 4 #include <linux/percpu-defs.h> 5 6 #include <xen/xen.h> 7 #include <xen/interface/xen.h> 8 #include <xen/grant_table.h> 9 #include <xen/events.h> 10 11 #include <asm/cpufeatures.h> 12 #include <asm/msr-index.h> 13 #include <asm/xen/hypercall.h> 14 #include <asm/xen/page.h> 15 #include <asm/fixmap.h> 16 #include <asm/msr.h> 17 18 #include "xen-ops.h" 19 20 static DEFINE_PER_CPU(u64, spec_ctrl); 21 22 void xen_arch_pre_suspend(void) 23 { 24 xen_save_time_memory_area(); 25 26 if (xen_pv_domain()) 27 xen_pv_pre_suspend(); 28 } 29 30 void xen_arch_post_suspend(int cancelled) 31 { 32 if (xen_pv_domain()) 33 xen_pv_post_suspend(cancelled); 34 else 35 xen_hvm_post_suspend(cancelled); 36 37 xen_restore_time_memory_area(); 38 } 39 40 static void xen_vcpu_notify_restore(void *data) 41 { 42 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) 43 wrmsrq(MSR_IA32_SPEC_CTRL, this_cpu_read(spec_ctrl)); 44 45 /* Boot processor notified via generic timekeeping_resume() */ 46 if (smp_processor_id() == 0) 47 return; 48 49 tick_resume_local(); 50 } 51 52 static void xen_vcpu_notify_suspend(void *data) 53 { 54 u64 tmp; 55 56 tick_suspend_local(); 57 58 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { 59 rdmsrq(MSR_IA32_SPEC_CTRL, tmp); 60 this_cpu_write(spec_ctrl, tmp); 61 wrmsrq(MSR_IA32_SPEC_CTRL, 0); 62 } 63 } 64 65 void xen_arch_resume(void) 66 { 67 int cpu; 68 69 on_each_cpu(xen_vcpu_notify_restore, NULL, 1); 70 71 for_each_online_cpu(cpu) 72 xen_pmu_init(cpu); 73 } 74 75 void xen_arch_suspend(void) 76 { 77 int cpu; 78 79 for_each_online_cpu(cpu) 80 xen_pmu_finish(cpu); 81 82 on_each_cpu(xen_vcpu_notify_suspend, NULL, 1); 83 } 84