| // SPDX-License-Identifier: GPL-2.0 | 
 | #include <linux/types.h> | 
 | #include <linux/tick.h> | 
 | #include <linux/percpu-defs.h> | 
 |  | 
 | #include <xen/xen.h> | 
 | #include <xen/interface/xen.h> | 
 | #include <xen/grant_table.h> | 
 | #include <xen/events.h> | 
 |  | 
 | #include <asm/cpufeatures.h> | 
 | #include <asm/msr-index.h> | 
 | #include <asm/xen/hypercall.h> | 
 | #include <asm/xen/page.h> | 
 | #include <asm/fixmap.h> | 
 |  | 
 | #include "xen-ops.h" | 
 | #include "mmu.h" | 
 | #include "pmu.h" | 
 |  | 
 | static DEFINE_PER_CPU(u64, spec_ctrl); | 
 |  | 
 | void xen_arch_pre_suspend(void) | 
 | { | 
 | 	xen_save_time_memory_area(); | 
 |  | 
 | 	if (xen_pv_domain()) | 
 | 		xen_pv_pre_suspend(); | 
 | } | 
 |  | 
 | void xen_arch_post_suspend(int cancelled) | 
 | { | 
 | 	if (xen_pv_domain()) | 
 | 		xen_pv_post_suspend(cancelled); | 
 | 	else | 
 | 		xen_hvm_post_suspend(cancelled); | 
 |  | 
 | 	xen_restore_time_memory_area(); | 
 | } | 
 |  | 
 | static void xen_vcpu_notify_restore(void *data) | 
 | { | 
 | 	if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) | 
 | 		wrmsrl(MSR_IA32_SPEC_CTRL, this_cpu_read(spec_ctrl)); | 
 |  | 
 | 	/* Boot processor notified via generic timekeeping_resume() */ | 
 | 	if (smp_processor_id() == 0) | 
 | 		return; | 
 |  | 
 | 	tick_resume_local(); | 
 | } | 
 |  | 
 | static void xen_vcpu_notify_suspend(void *data) | 
 | { | 
 | 	u64 tmp; | 
 |  | 
 | 	tick_suspend_local(); | 
 |  | 
 | 	if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { | 
 | 		rdmsrl(MSR_IA32_SPEC_CTRL, tmp); | 
 | 		this_cpu_write(spec_ctrl, tmp); | 
 | 		wrmsrl(MSR_IA32_SPEC_CTRL, 0); | 
 | 	} | 
 | } | 
 |  | 
 | void xen_arch_resume(void) | 
 | { | 
 | 	int cpu; | 
 |  | 
 | 	on_each_cpu(xen_vcpu_notify_restore, NULL, 1); | 
 |  | 
 | 	for_each_online_cpu(cpu) | 
 | 		xen_pmu_init(cpu); | 
 | } | 
 |  | 
 | void xen_arch_suspend(void) | 
 | { | 
 | 	int cpu; | 
 |  | 
 | 	for_each_online_cpu(cpu) | 
 | 		xen_pmu_finish(cpu); | 
 |  | 
 | 	on_each_cpu(xen_vcpu_notify_suspend, NULL, 1); | 
 | } |