// 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); 
 | 
} 
 |