1 #include <linux/types.h> 2 #include <linux/tick.h> 3 4 #include <xen/interface/xen.h> 5 #include <xen/grant_table.h> 6 #include <xen/events.h> 7 8 #include <asm/xen/hypercall.h> 9 #include <asm/xen/page.h> 10 #include <asm/fixmap.h> 11 12 #include "xen-ops.h" 13 #include "mmu.h" 14 #include "pmu.h" 15 16 static void xen_pv_pre_suspend(void) 17 { 18 xen_mm_pin_all(); 19 20 xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); 21 xen_start_info->console.domU.mfn = 22 mfn_to_pfn(xen_start_info->console.domU.mfn); 23 24 BUG_ON(!irqs_disabled()); 25 26 HYPERVISOR_shared_info = &xen_dummy_shared_info; 27 if (HYPERVISOR_update_va_mapping(fix_to_virt(FIX_PARAVIRT_BOOTMAP), 28 __pte_ma(0), 0)) 29 BUG(); 30 } 31 32 static void xen_hvm_post_suspend(int suspend_cancelled) 33 { 34 #ifdef CONFIG_XEN_PVHVM 35 int cpu; 36 xen_hvm_init_shared_info(); 37 xen_callback_vector(); 38 xen_unplug_emulated_devices(); 39 if (xen_feature(XENFEAT_hvm_safe_pvclock)) { 40 for_each_online_cpu(cpu) { 41 xen_setup_runstate_info(cpu); 42 } 43 } 44 #endif 45 } 46 47 static void xen_pv_post_suspend(int suspend_cancelled) 48 { 49 xen_build_mfn_list_list(); 50 51 xen_setup_shared_info(); 52 53 if (suspend_cancelled) { 54 xen_start_info->store_mfn = 55 pfn_to_mfn(xen_start_info->store_mfn); 56 xen_start_info->console.domU.mfn = 57 pfn_to_mfn(xen_start_info->console.domU.mfn); 58 } else { 59 #ifdef CONFIG_SMP 60 BUG_ON(xen_cpu_initialized_map == NULL); 61 cpumask_copy(xen_cpu_initialized_map, cpu_online_mask); 62 #endif 63 xen_vcpu_restore(); 64 } 65 66 xen_mm_unpin_all(); 67 } 68 69 void xen_arch_pre_suspend(void) 70 { 71 int cpu; 72 73 for_each_online_cpu(cpu) 74 xen_pmu_finish(cpu); 75 76 if (xen_pv_domain()) 77 xen_pv_pre_suspend(); 78 } 79 80 void xen_arch_post_suspend(int cancelled) 81 { 82 int cpu; 83 84 if (xen_pv_domain()) 85 xen_pv_post_suspend(cancelled); 86 else 87 xen_hvm_post_suspend(cancelled); 88 89 for_each_online_cpu(cpu) 90 xen_pmu_init(cpu); 91 } 92 93 static void xen_vcpu_notify_restore(void *data) 94 { 95 /* Boot processor notified via generic timekeeping_resume() */ 96 if (smp_processor_id() == 0) 97 return; 98 99 tick_resume_local(); 100 } 101 102 static void xen_vcpu_notify_suspend(void *data) 103 { 104 tick_suspend_local(); 105 } 106 107 void xen_arch_resume(void) 108 { 109 on_each_cpu(xen_vcpu_notify_restore, NULL, 1); 110 } 111 112 void xen_arch_suspend(void) 113 { 114 on_each_cpu(xen_vcpu_notify_suspend, NULL, 1); 115 } 116