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 17 #include "xen-ops.h" 18 19 static DEFINE_PER_CPU(u64, spec_ctrl); 20 21 void xen_arch_pre_suspend(void) 22 { 23 xen_save_time_memory_area(); 24 25 if (xen_pv_domain()) 26 xen_pv_pre_suspend(); 27 } 28 29 void xen_arch_post_suspend(int cancelled) 30 { 31 if (xen_pv_domain()) 32 xen_pv_post_suspend(cancelled); 33 else 34 xen_hvm_post_suspend(cancelled); 35 36 xen_restore_time_memory_area(); 37 } 38 39 static void xen_vcpu_notify_restore(void *data) 40 { 41 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) 42 wrmsrl(MSR_IA32_SPEC_CTRL, this_cpu_read(spec_ctrl)); 43 44 /* Boot processor notified via generic timekeeping_resume() */ 45 if (smp_processor_id() == 0) 46 return; 47 48 tick_resume_local(); 49 } 50 51 static void xen_vcpu_notify_suspend(void *data) 52 { 53 u64 tmp; 54 55 tick_suspend_local(); 56 57 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { 58 rdmsrl(MSR_IA32_SPEC_CTRL, tmp); 59 this_cpu_write(spec_ctrl, tmp); 60 wrmsrl(MSR_IA32_SPEC_CTRL, 0); 61 } 62 } 63 64 void xen_arch_resume(void) 65 { 66 int cpu; 67 68 on_each_cpu(xen_vcpu_notify_restore, NULL, 1); 69 70 for_each_online_cpu(cpu) 71 xen_pmu_init(cpu); 72 } 73 74 void xen_arch_suspend(void) 75 { 76 int cpu; 77 78 for_each_online_cpu(cpu) 79 xen_pmu_finish(cpu); 80 81 on_each_cpu(xen_vcpu_notify_suspend, NULL, 1); 82 } 83