diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/x86/kernel/kvmclock.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'arch/x86/kernel/kvmclock.c')
-rw-r--r-- | arch/x86/kernel/kvmclock.c | 114 |
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) | |||
40 | early_param("no-kvmclock", parse_no_kvmclock); | 38 | early_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 */ |
43 | static struct pvclock_vsyscall_time_info *hv_clock; | 41 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct pvclock_vcpu_time_info, hv_clock); |
44 | static struct pvclock_wall_clock wall_clock; | 42 | static 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) | |||
107 | static unsigned long kvm_get_tsc_khz(void) | 98 | static 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 | ||
121 | static void kvm_get_preset_lpj(void) | 105 | static 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 | ||
133 | bool 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 | |||
151 | static struct clocksource kvm_clock = { | 117 | static 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 | ||
174 | static void kvm_save_sched_clock_state(void) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static 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 |
184 | static void __cpuinit kvm_setup_secondary_clock(void) | 140 | static 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 | ||
218 | void __init kvmclock_init(void) | 176 | void __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 | |||
269 | int __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 | } | ||