aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kvmclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/kvmclock.c')
-rw-r--r--arch/x86/kernel/kvmclock.c114
1 files changed, 12 insertions, 102 deletions
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 220a360010f..44842d756b2 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -22,8 +22,6 @@
22#include <asm/msr.h> 22#include <asm/msr.h>
23#include <asm/apic.h> 23#include <asm/apic.h>
24#include <linux/percpu.h> 24#include <linux/percpu.h>
25#include <linux/hardirq.h>
26#include <linux/memblock.h>
27 25
28#include <asm/x86_init.h> 26#include <asm/x86_init.h>
29#include <asm/reboot.h> 27#include <asm/reboot.h>
@@ -40,7 +38,7 @@ static int parse_no_kvmclock(char *arg)
40early_param("no-kvmclock", parse_no_kvmclock); 38early_param("no-kvmclock", parse_no_kvmclock);
41 39
42/* The hypervisor will put information about time periodically here */ 40/* The hypervisor will put information about time periodically here */
43static struct pvclock_vsyscall_time_info *hv_clock; 41static DEFINE_PER_CPU_SHARED_ALIGNED(struct pvclock_vcpu_time_info, hv_clock);
44static struct pvclock_wall_clock wall_clock; 42static struct pvclock_wall_clock wall_clock;
45 43
46/* 44/*
@@ -53,20 +51,15 @@ static unsigned long kvm_get_wallclock(void)
53 struct pvclock_vcpu_time_info *vcpu_time; 51 struct pvclock_vcpu_time_info *vcpu_time;
54 struct timespec ts; 52 struct timespec ts;
55 int low, high; 53 int low, high;
56 int cpu;
57 54
58 low = (int)__pa_symbol(&wall_clock); 55 low = (int)__pa_symbol(&wall_clock);
59 high = ((u64)__pa_symbol(&wall_clock) >> 32); 56 high = ((u64)__pa_symbol(&wall_clock) >> 32);
60 57
61 native_write_msr(msr_kvm_wall_clock, low, high); 58 native_write_msr(msr_kvm_wall_clock, low, high);
62 59
63 preempt_disable(); 60 vcpu_time = &get_cpu_var(hv_clock);
64 cpu = smp_processor_id();
65
66 vcpu_time = &hv_clock[cpu].pvti;
67 pvclock_read_wallclock(&wall_clock, vcpu_time, &ts); 61 pvclock_read_wallclock(&wall_clock, vcpu_time, &ts);
68 62 put_cpu_var(hv_clock);
69 preempt_enable();
70 63
71 return ts.tv_sec; 64 return ts.tv_sec;
72} 65}
@@ -80,11 +73,9 @@ static cycle_t kvm_clock_read(void)
80{ 73{
81 struct pvclock_vcpu_time_info *src; 74 struct pvclock_vcpu_time_info *src;
82 cycle_t ret; 75 cycle_t ret;
83 int cpu;
84 76
85 preempt_disable_notrace(); 77 preempt_disable_notrace();
86 cpu = smp_processor_id(); 78 src = &__get_cpu_var(hv_clock);
87 src = &hv_clock[cpu].pvti;
88 ret = pvclock_clocksource_read(src); 79 ret = pvclock_clocksource_read(src);
89 preempt_enable_notrace(); 80 preempt_enable_notrace();
90 return ret; 81 return ret;
@@ -107,15 +98,8 @@ static cycle_t kvm_clock_get_cycles(struct clocksource *cs)
107static unsigned long kvm_get_tsc_khz(void) 98static unsigned long kvm_get_tsc_khz(void)
108{ 99{
109 struct pvclock_vcpu_time_info *src; 100 struct pvclock_vcpu_time_info *src;
110 int cpu; 101 src = &per_cpu(hv_clock, 0);
111 unsigned long tsc_khz; 102 return pvclock_tsc_khz(src);
112
113 preempt_disable();
114 cpu = smp_processor_id();
115 src = &hv_clock[cpu].pvti;
116 tsc_khz = pvclock_tsc_khz(src);
117 preempt_enable();
118 return tsc_khz;
119} 103}
120 104
121static void kvm_get_preset_lpj(void) 105static void kvm_get_preset_lpj(void)
@@ -130,24 +114,6 @@ static void kvm_get_preset_lpj(void)
130 preset_lpj = lpj; 114 preset_lpj = lpj;
131} 115}
132 116
133bool kvm_check_and_clear_guest_paused(void)
134{
135 bool ret = false;
136 struct pvclock_vcpu_time_info *src;
137 int cpu = smp_processor_id();
138
139 if (!hv_clock)
140 return ret;
141
142 src = &hv_clock[cpu].pvti;
143 if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) {
144 src->flags &= ~PVCLOCK_GUEST_STOPPED;
145 ret = true;
146 }
147
148 return ret;
149}
150
151static struct clocksource kvm_clock = { 117static struct clocksource kvm_clock = {
152 .name = "kvm-clock", 118 .name = "kvm-clock",
153 .read = kvm_clock_get_cycles, 119 .read = kvm_clock_get_cycles,
@@ -160,10 +126,9 @@ int kvm_register_clock(char *txt)
160{ 126{
161 int cpu = smp_processor_id(); 127 int cpu = smp_processor_id();
162 int low, high, ret; 128 int low, high, ret;
163 struct pvclock_vcpu_time_info *src = &hv_clock[cpu].pvti;
164 129
165 low = (int)__pa(src) | 1; 130 low = (int)__pa(&per_cpu(hv_clock, cpu)) | 1;
166 high = ((u64)__pa(src) >> 32); 131 high = ((u64)__pa(&per_cpu(hv_clock, cpu)) >> 32);
167 ret = native_write_msr_safe(msr_kvm_system_time, low, high); 132 ret = native_write_msr_safe(msr_kvm_system_time, low, high);
168 printk(KERN_INFO "kvm-clock: cpu %d, msr %x:%x, %s\n", 133 printk(KERN_INFO "kvm-clock: cpu %d, msr %x:%x, %s\n",
169 cpu, high, low, txt); 134 cpu, high, low, txt);
@@ -171,15 +136,6 @@ int kvm_register_clock(char *txt)
171 return ret; 136 return ret;
172} 137}
173 138
174static void kvm_save_sched_clock_state(void)
175{
176}
177
178static void kvm_restore_sched_clock_state(void)
179{
180 kvm_register_clock("primary cpu clock, resume");
181}
182
183#ifdef CONFIG_X86_LOCAL_APIC 139#ifdef CONFIG_X86_LOCAL_APIC
184static void __cpuinit kvm_setup_secondary_clock(void) 140static void __cpuinit kvm_setup_secondary_clock(void)
185{ 141{
@@ -188,6 +144,8 @@ static void __cpuinit kvm_setup_secondary_clock(void)
188 * we shouldn't fail. 144 * we shouldn't fail.
189 */ 145 */
190 WARN_ON(kvm_register_clock("secondary cpu clock")); 146 WARN_ON(kvm_register_clock("secondary cpu clock"));
147 /* ok, done with our trickery, call native */
148 setup_secondary_APIC_clock();
191} 149}
192#endif 150#endif
193 151
@@ -217,8 +175,6 @@ static void kvm_shutdown(void)
217 175
218void __init kvmclock_init(void) 176void __init kvmclock_init(void)
219{ 177{
220 unsigned long mem;
221
222 if (!kvm_para_available()) 178 if (!kvm_para_available())
223 return; 179 return;
224 180
@@ -231,28 +187,16 @@ void __init kvmclock_init(void)
231 printk(KERN_INFO "kvm-clock: Using msrs %x and %x", 187 printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
232 msr_kvm_system_time, msr_kvm_wall_clock); 188 msr_kvm_system_time, msr_kvm_wall_clock);
233 189
234 mem = memblock_alloc(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS, 190 if (kvm_register_clock("boot clock"))
235 PAGE_SIZE);
236 if (!mem)
237 return;
238 hv_clock = __va(mem);
239
240 if (kvm_register_clock("boot clock")) {
241 hv_clock = NULL;
242 memblock_free(mem,
243 sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
244 return; 191 return;
245 }
246 pv_time_ops.sched_clock = kvm_clock_read; 192 pv_time_ops.sched_clock = kvm_clock_read;
247 x86_platform.calibrate_tsc = kvm_get_tsc_khz; 193 x86_platform.calibrate_tsc = kvm_get_tsc_khz;
248 x86_platform.get_wallclock = kvm_get_wallclock; 194 x86_platform.get_wallclock = kvm_get_wallclock;
249 x86_platform.set_wallclock = kvm_set_wallclock; 195 x86_platform.set_wallclock = kvm_set_wallclock;
250#ifdef CONFIG_X86_LOCAL_APIC 196#ifdef CONFIG_X86_LOCAL_APIC
251 x86_cpuinit.early_percpu_clock_init = 197 x86_cpuinit.setup_percpu_clockev =
252 kvm_setup_secondary_clock; 198 kvm_setup_secondary_clock;
253#endif 199#endif
254 x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
255 x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
256 machine_ops.shutdown = kvm_shutdown; 200 machine_ops.shutdown = kvm_shutdown;
257#ifdef CONFIG_KEXEC 201#ifdef CONFIG_KEXEC
258 machine_ops.crash_shutdown = kvm_crash_shutdown; 202 machine_ops.crash_shutdown = kvm_crash_shutdown;
@@ -265,37 +209,3 @@ void __init kvmclock_init(void)
265 if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)) 209 if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
266 pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); 210 pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
267} 211}
268
269int __init kvm_setup_vsyscall_timeinfo(void)
270{
271#ifdef CONFIG_X86_64
272 int cpu;
273 int ret;
274 u8 flags;
275 struct pvclock_vcpu_time_info *vcpu_time;
276 unsigned int size;
277
278 size = sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS;
279
280 preempt_disable();
281 cpu = smp_processor_id();
282
283 vcpu_time = &hv_clock[cpu].pvti;
284 flags = pvclock_read_flags(vcpu_time);
285
286 if (!(flags & PVCLOCK_TSC_STABLE_BIT)) {
287 preempt_enable();
288 return 1;
289 }
290
291 if ((ret = pvclock_init_vsyscall(hv_clock, size))) {
292 preempt_enable();
293 return ret;
294 }
295
296 preempt_enable();
297
298 kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK;
299#endif
300 return 0;
301}