diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-05-14 07:48:19 -0400 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2010-07-27 02:13:25 -0400 |
commit | 409771d258e9dd71c30f3c9520fd2b796ffc40f0 (patch) | |
tree | 68678275563114e9d381ae587fc80bd4d34a7e90 /arch/x86/xen | |
parent | 99ad198c4978036bb9f7ebd11618b225b77046da (diff) |
x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock.
Use xen_vcpuop_clockevent instead of hpet and APIC timers as main
clockevent device on all vcpus, use the xen wallclock time as wallclock
instead of rtc and use xen_clocksource as clocksource.
The pv clock algorithm needs to work correctly for the xen_clocksource
and xen wallclock to be usable, only modern Xen versions offer a
reliable pv clock in HVM guests (XENFEAT_hvm_safe_pvclock).
Using the hpet as clocksource means a VMEXIT every time we read/write to
the hpet mmio addresses, pvclock give us a better rating without
VMEXITs. Same goes for the xen wallclock and xen_vcpuop_clockevent
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Don Dutile <ddutile@redhat.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/enlighten.c | 14 | ||||
-rw-r--r-- | arch/x86/xen/suspend.c | 6 | ||||
-rw-r--r-- | arch/x86/xen/time.c | 58 | ||||
-rw-r--r-- | arch/x86/xen/xen-ops.h | 7 |
4 files changed, 63 insertions, 22 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 127c95c8d15e..a90172963884 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -935,10 +935,6 @@ static const struct pv_init_ops xen_init_ops __initdata = { | |||
935 | .patch = xen_patch, | 935 | .patch = xen_patch, |
936 | }; | 936 | }; |
937 | 937 | ||
938 | static const struct pv_time_ops xen_time_ops __initdata = { | ||
939 | .sched_clock = xen_sched_clock, | ||
940 | }; | ||
941 | |||
942 | static const struct pv_cpu_ops xen_cpu_ops __initdata = { | 938 | static const struct pv_cpu_ops xen_cpu_ops __initdata = { |
943 | .cpuid = xen_cpuid, | 939 | .cpuid = xen_cpuid, |
944 | 940 | ||
@@ -1076,7 +1072,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1076 | /* Install Xen paravirt ops */ | 1072 | /* Install Xen paravirt ops */ |
1077 | pv_info = xen_info; | 1073 | pv_info = xen_info; |
1078 | pv_init_ops = xen_init_ops; | 1074 | pv_init_ops = xen_init_ops; |
1079 | pv_time_ops = xen_time_ops; | ||
1080 | pv_cpu_ops = xen_cpu_ops; | 1075 | pv_cpu_ops = xen_cpu_ops; |
1081 | pv_apic_ops = xen_apic_ops; | 1076 | pv_apic_ops = xen_apic_ops; |
1082 | 1077 | ||
@@ -1084,13 +1079,7 @@ asmlinkage void __init xen_start_kernel(void) | |||
1084 | x86_init.oem.arch_setup = xen_arch_setup; | 1079 | x86_init.oem.arch_setup = xen_arch_setup; |
1085 | x86_init.oem.banner = xen_banner; | 1080 | x86_init.oem.banner = xen_banner; |
1086 | 1081 | ||
1087 | x86_init.timers.timer_init = xen_time_init; | 1082 | xen_init_time_ops(); |
1088 | x86_init.timers.setup_percpu_clockev = x86_init_noop; | ||
1089 | x86_cpuinit.setup_percpu_clockev = x86_init_noop; | ||
1090 | |||
1091 | x86_platform.calibrate_tsc = xen_tsc_khz; | ||
1092 | x86_platform.get_wallclock = xen_get_wallclock; | ||
1093 | x86_platform.set_wallclock = xen_set_wallclock; | ||
1094 | 1083 | ||
1095 | /* | 1084 | /* |
1096 | * Set up some pagetable state before starting to set any ptes. | 1085 | * Set up some pagetable state before starting to set any ptes. |
@@ -1327,6 +1316,7 @@ static void __init xen_hvm_guest_init(void) | |||
1327 | register_cpu_notifier(&xen_hvm_cpu_notifier); | 1316 | register_cpu_notifier(&xen_hvm_cpu_notifier); |
1328 | have_vcpu_info_placement = 0; | 1317 | have_vcpu_info_placement = 0; |
1329 | x86_init.irqs.intr_init = xen_init_IRQ; | 1318 | x86_init.irqs.intr_init = xen_init_IRQ; |
1319 | xen_hvm_init_time_ops(); | ||
1330 | } | 1320 | } |
1331 | 1321 | ||
1332 | static bool __init xen_hvm_platform(void) | 1322 | static bool __init xen_hvm_platform(void) |
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index d07479c340f5..1d789d56877c 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c | |||
@@ -28,8 +28,14 @@ void xen_pre_suspend(void) | |||
28 | 28 | ||
29 | void xen_hvm_post_suspend(int suspend_cancelled) | 29 | void xen_hvm_post_suspend(int suspend_cancelled) |
30 | { | 30 | { |
31 | int cpu; | ||
31 | xen_hvm_init_shared_info(); | 32 | xen_hvm_init_shared_info(); |
32 | xen_callback_vector(); | 33 | xen_callback_vector(); |
34 | if (xen_feature(XENFEAT_hvm_safe_pvclock)) { | ||
35 | for_each_online_cpu(cpu) { | ||
36 | xen_setup_runstate_info(cpu); | ||
37 | } | ||
38 | } | ||
33 | } | 39 | } |
34 | 40 | ||
35 | void xen_post_suspend(int suspend_cancelled) | 41 | void xen_post_suspend(int suspend_cancelled) |
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index b3c6c59ed302..4780e55886a5 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/xen/hypercall.h> | 20 | #include <asm/xen/hypercall.h> |
21 | 21 | ||
22 | #include <xen/events.h> | 22 | #include <xen/events.h> |
23 | #include <xen/features.h> | ||
23 | #include <xen/interface/xen.h> | 24 | #include <xen/interface/xen.h> |
24 | #include <xen/interface/vcpu.h> | 25 | #include <xen/interface/vcpu.h> |
25 | 26 | ||
@@ -160,7 +161,7 @@ static void do_stolen_accounting(void) | |||
160 | * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED | 161 | * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED |
161 | * states. | 162 | * states. |
162 | */ | 163 | */ |
163 | unsigned long long xen_sched_clock(void) | 164 | static unsigned long long xen_sched_clock(void) |
164 | { | 165 | { |
165 | struct vcpu_runstate_info state; | 166 | struct vcpu_runstate_info state; |
166 | cycle_t now; | 167 | cycle_t now; |
@@ -195,7 +196,7 @@ unsigned long long xen_sched_clock(void) | |||
195 | 196 | ||
196 | 197 | ||
197 | /* Get the TSC speed from Xen */ | 198 | /* Get the TSC speed from Xen */ |
198 | unsigned long xen_tsc_khz(void) | 199 | static unsigned long xen_tsc_khz(void) |
199 | { | 200 | { |
200 | struct pvclock_vcpu_time_info *info = | 201 | struct pvclock_vcpu_time_info *info = |
201 | &HYPERVISOR_shared_info->vcpu_info[0].time; | 202 | &HYPERVISOR_shared_info->vcpu_info[0].time; |
@@ -230,7 +231,7 @@ static void xen_read_wallclock(struct timespec *ts) | |||
230 | put_cpu_var(xen_vcpu); | 231 | put_cpu_var(xen_vcpu); |
231 | } | 232 | } |
232 | 233 | ||
233 | unsigned long xen_get_wallclock(void) | 234 | static unsigned long xen_get_wallclock(void) |
234 | { | 235 | { |
235 | struct timespec ts; | 236 | struct timespec ts; |
236 | 237 | ||
@@ -238,7 +239,7 @@ unsigned long xen_get_wallclock(void) | |||
238 | return ts.tv_sec; | 239 | return ts.tv_sec; |
239 | } | 240 | } |
240 | 241 | ||
241 | int xen_set_wallclock(unsigned long now) | 242 | static int xen_set_wallclock(unsigned long now) |
242 | { | 243 | { |
243 | /* do nothing for domU */ | 244 | /* do nothing for domU */ |
244 | return -1; | 245 | return -1; |
@@ -473,7 +474,11 @@ void xen_timer_resume(void) | |||
473 | } | 474 | } |
474 | } | 475 | } |
475 | 476 | ||
476 | __init void xen_time_init(void) | 477 | static const struct pv_time_ops xen_time_ops __initdata = { |
478 | .sched_clock = xen_sched_clock, | ||
479 | }; | ||
480 | |||
481 | static __init void xen_time_init(void) | ||
477 | { | 482 | { |
478 | int cpu = smp_processor_id(); | 483 | int cpu = smp_processor_id(); |
479 | struct timespec tp; | 484 | struct timespec tp; |
@@ -497,3 +502,46 @@ __init void xen_time_init(void) | |||
497 | xen_setup_timer(cpu); | 502 | xen_setup_timer(cpu); |
498 | xen_setup_cpu_clockevents(); | 503 | xen_setup_cpu_clockevents(); |
499 | } | 504 | } |
505 | |||
506 | __init void xen_init_time_ops(void) | ||
507 | { | ||
508 | pv_time_ops = xen_time_ops; | ||
509 | |||
510 | x86_init.timers.timer_init = xen_time_init; | ||
511 | x86_init.timers.setup_percpu_clockev = x86_init_noop; | ||
512 | x86_cpuinit.setup_percpu_clockev = x86_init_noop; | ||
513 | |||
514 | x86_platform.calibrate_tsc = xen_tsc_khz; | ||
515 | x86_platform.get_wallclock = xen_get_wallclock; | ||
516 | x86_platform.set_wallclock = xen_set_wallclock; | ||
517 | } | ||
518 | |||
519 | static void xen_hvm_setup_cpu_clockevents(void) | ||
520 | { | ||
521 | int cpu = smp_processor_id(); | ||
522 | xen_setup_runstate_info(cpu); | ||
523 | xen_setup_timer(cpu); | ||
524 | xen_setup_cpu_clockevents(); | ||
525 | } | ||
526 | |||
527 | __init void xen_hvm_init_time_ops(void) | ||
528 | { | ||
529 | /* vector callback is needed otherwise we cannot receive interrupts | ||
530 | * on cpu > 0 */ | ||
531 | if (!xen_have_vector_callback && num_present_cpus() > 1) | ||
532 | return; | ||
533 | if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { | ||
534 | printk(KERN_INFO "Xen doesn't support pvclock on HVM," | ||
535 | "disable pv timer\n"); | ||
536 | return; | ||
537 | } | ||
538 | |||
539 | pv_time_ops = xen_time_ops; | ||
540 | x86_init.timers.setup_percpu_clockev = xen_time_init; | ||
541 | x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents; | ||
542 | |||
543 | x86_platform.calibrate_tsc = xen_tsc_khz; | ||
544 | x86_platform.get_wallclock = xen_get_wallclock; | ||
545 | x86_platform.set_wallclock = xen_set_wallclock; | ||
546 | } | ||
547 | |||
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 01c9dd386522..089d18923d2b 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -49,11 +49,8 @@ void xen_setup_runstate_info(int cpu); | |||
49 | void xen_teardown_timer(int cpu); | 49 | void xen_teardown_timer(int cpu); |
50 | cycle_t xen_clocksource_read(void); | 50 | cycle_t xen_clocksource_read(void); |
51 | void xen_setup_cpu_clockevents(void); | 51 | void xen_setup_cpu_clockevents(void); |
52 | unsigned long xen_tsc_khz(void); | 52 | void __init xen_init_time_ops(void); |
53 | void __init xen_time_init(void); | 53 | void __init xen_hvm_init_time_ops(void); |
54 | unsigned long xen_get_wallclock(void); | ||
55 | int xen_set_wallclock(unsigned long time); | ||
56 | unsigned long long xen_sched_clock(void); | ||
57 | 54 | ||
58 | irqreturn_t xen_debug_interrupt(int irq, void *dev_id); | 55 | irqreturn_t xen_debug_interrupt(int irq, void *dev_id); |
59 | 56 | ||