summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/xen/manage.c7
-rw-r--r--drivers/xen/time.c72
-rw-r--r--include/xen/xen-ops.h1
3 files changed, 73 insertions, 7 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index c425d03d37d2..8835065029d3 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -72,18 +72,15 @@ static int xen_suspend(void *data)
72 } 72 }
73 73
74 gnttab_suspend(); 74 gnttab_suspend();
75 xen_manage_runstate_time(-1);
75 xen_arch_pre_suspend(); 76 xen_arch_pre_suspend();
76 77
77 /*
78 * This hypercall returns 1 if suspend was cancelled
79 * or the domain was merely checkpointed, and 0 if it
80 * is resuming in a new domain.
81 */
82 si->cancelled = HYPERVISOR_suspend(xen_pv_domain() 78 si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
83 ? virt_to_gfn(xen_start_info) 79 ? virt_to_gfn(xen_start_info)
84 : 0); 80 : 0);
85 81
86 xen_arch_post_suspend(si->cancelled); 82 xen_arch_post_suspend(si->cancelled);
83 xen_manage_runstate_time(si->cancelled ? 1 : 0);
87 gnttab_resume(); 84 gnttab_resume();
88 85
89 if (!si->cancelled) { 86 if (!si->cancelled) {
diff --git a/drivers/xen/time.c b/drivers/xen/time.c
index ac5f23fcafc2..8c46f555d82a 100644
--- a/drivers/xen/time.c
+++ b/drivers/xen/time.c
@@ -5,6 +5,7 @@
5#include <linux/kernel_stat.h> 5#include <linux/kernel_stat.h>
6#include <linux/math64.h> 6#include <linux/math64.h>
7#include <linux/gfp.h> 7#include <linux/gfp.h>
8#include <linux/slab.h>
8 9
9#include <asm/paravirt.h> 10#include <asm/paravirt.h>
10#include <asm/xen/hypervisor.h> 11#include <asm/xen/hypervisor.h>
@@ -19,6 +20,8 @@
19/* runstate info updated by Xen */ 20/* runstate info updated by Xen */
20static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); 21static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
21 22
23static DEFINE_PER_CPU(u64[4], old_runstate_time);
24
22/* return an consistent snapshot of 64-bit time/counter value */ 25/* return an consistent snapshot of 64-bit time/counter value */
23static u64 get64(const u64 *p) 26static u64 get64(const u64 *p)
24{ 27{
@@ -47,8 +50,8 @@ static u64 get64(const u64 *p)
47 return ret; 50 return ret;
48} 51}
49 52
50static void xen_get_runstate_snapshot_cpu(struct vcpu_runstate_info *res, 53static void xen_get_runstate_snapshot_cpu_delta(
51 unsigned int cpu) 54 struct vcpu_runstate_info *res, unsigned int cpu)
52{ 55{
53 u64 state_time; 56 u64 state_time;
54 struct vcpu_runstate_info *state; 57 struct vcpu_runstate_info *state;
@@ -66,6 +69,71 @@ static void xen_get_runstate_snapshot_cpu(struct vcpu_runstate_info *res,
66 (state_time & XEN_RUNSTATE_UPDATE)); 69 (state_time & XEN_RUNSTATE_UPDATE));
67} 70}
68 71
72static void xen_get_runstate_snapshot_cpu(struct vcpu_runstate_info *res,
73 unsigned int cpu)
74{
75 int i;
76
77 xen_get_runstate_snapshot_cpu_delta(res, cpu);
78
79 for (i = 0; i < 4; i++)
80 res->time[i] += per_cpu(old_runstate_time, cpu)[i];
81}
82
83void xen_manage_runstate_time(int action)
84{
85 static struct vcpu_runstate_info *runstate_delta;
86 struct vcpu_runstate_info state;
87 int cpu, i;
88
89 switch (action) {
90 case -1: /* backup runstate time before suspend */
91 if (unlikely(runstate_delta))
92 pr_warn_once("%s: memory leak as runstate_delta is not NULL\n",
93 __func__);
94
95 runstate_delta = kmalloc_array(num_possible_cpus(),
96 sizeof(*runstate_delta),
97 GFP_ATOMIC);
98 if (unlikely(!runstate_delta)) {
99 pr_warn("%s: failed to allocate runstate_delta\n",
100 __func__);
101 return;
102 }
103
104 for_each_possible_cpu(cpu) {
105 xen_get_runstate_snapshot_cpu_delta(&state, cpu);
106 memcpy(runstate_delta[cpu].time, state.time,
107 sizeof(runstate_delta[cpu].time));
108 }
109
110 break;
111
112 case 0: /* backup runstate time after resume */
113 if (unlikely(!runstate_delta)) {
114 pr_warn("%s: cannot accumulate runstate time as runstate_delta is NULL\n",
115 __func__);
116 return;
117 }
118
119 for_each_possible_cpu(cpu) {
120 for (i = 0; i < 4; i++)
121 per_cpu(old_runstate_time, cpu)[i] +=
122 runstate_delta[cpu].time[i];
123 }
124
125 break;
126
127 default: /* do not accumulate runstate time for checkpointing */
128 break;
129 }
130
131 if (action != -1 && runstate_delta) {
132 kfree(runstate_delta);
133 runstate_delta = NULL;
134 }
135}
136
69/* 137/*
70 * Runstate accounting 138 * Runstate accounting
71 */ 139 */
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 218e6aae5433..09072271f122 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -32,6 +32,7 @@ void xen_resume_notifier_unregister(struct notifier_block *nb);
32bool xen_vcpu_stolen(int vcpu); 32bool xen_vcpu_stolen(int vcpu);
33void xen_setup_runstate_info(int cpu); 33void xen_setup_runstate_info(int cpu);
34void xen_time_setup_guest(void); 34void xen_time_setup_guest(void);
35void xen_manage_runstate_time(int action);
35void xen_get_runstate_snapshot(struct vcpu_runstate_info *res); 36void xen_get_runstate_snapshot(struct vcpu_runstate_info *res);
36u64 xen_steal_clock(int cpu); 37u64 xen_steal_clock(int cpu);
37 38