xref: /linux/arch/x86/xen/time.c (revision fdb9eb9f155bfc0f8dc2fc88f90448b30c78ad97)
19702785aSThomas Gleixner /*
29702785aSThomas Gleixner  * Xen time implementation.
39702785aSThomas Gleixner  *
49702785aSThomas Gleixner  * This is implemented in terms of a clocksource driver which uses
59702785aSThomas Gleixner  * the hypervisor clock as a nanosecond timebase, and a clockevent
69702785aSThomas Gleixner  * driver which uses the hypervisor's timer mechanism.
79702785aSThomas Gleixner  *
89702785aSThomas Gleixner  * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
99702785aSThomas Gleixner  */
109702785aSThomas Gleixner #include <linux/kernel.h>
119702785aSThomas Gleixner #include <linux/interrupt.h>
129702785aSThomas Gleixner #include <linux/clocksource.h>
139702785aSThomas Gleixner #include <linux/clockchips.h>
149702785aSThomas Gleixner #include <linux/kernel_stat.h>
15f595ec96SJeremy Fitzhardinge #include <linux/math64.h>
165a0e3ad6STejun Heo #include <linux/gfp.h>
179702785aSThomas Gleixner 
181c7b67f7SGerd Hoffmann #include <asm/pvclock.h>
199702785aSThomas Gleixner #include <asm/xen/hypervisor.h>
209702785aSThomas Gleixner #include <asm/xen/hypercall.h>
219702785aSThomas Gleixner 
229702785aSThomas Gleixner #include <xen/events.h>
23409771d2SStefano Stabellini #include <xen/features.h>
249702785aSThomas Gleixner #include <xen/interface/xen.h>
259702785aSThomas Gleixner #include <xen/interface/vcpu.h>
269702785aSThomas Gleixner 
279702785aSThomas Gleixner #include "xen-ops.h"
289702785aSThomas Gleixner 
299702785aSThomas Gleixner /* Xen may fire a timer up to this many ns early */
309702785aSThomas Gleixner #define TIMER_SLOP	100000
319702785aSThomas Gleixner #define NS_PER_TICK	(1000000000LL / HZ)
329702785aSThomas Gleixner 
339702785aSThomas Gleixner /* runstate info updated by Xen */
34c6e22f9eSTejun Heo static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
359702785aSThomas Gleixner 
369702785aSThomas Gleixner /* snapshots of runstate info */
37c6e22f9eSTejun Heo static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot);
389702785aSThomas Gleixner 
399702785aSThomas Gleixner /* unused ns of stolen and blocked time */
40c6e22f9eSTejun Heo static DEFINE_PER_CPU(u64, xen_residual_stolen);
41c6e22f9eSTejun Heo static DEFINE_PER_CPU(u64, xen_residual_blocked);
429702785aSThomas Gleixner 
439702785aSThomas Gleixner /* return an consistent snapshot of 64-bit time/counter value */
449702785aSThomas Gleixner static u64 get64(const u64 *p)
459702785aSThomas Gleixner {
469702785aSThomas Gleixner 	u64 ret;
479702785aSThomas Gleixner 
489702785aSThomas Gleixner 	if (BITS_PER_LONG < 64) {
499702785aSThomas Gleixner 		u32 *p32 = (u32 *)p;
509702785aSThomas Gleixner 		u32 h, l;
519702785aSThomas Gleixner 
529702785aSThomas Gleixner 		/*
539702785aSThomas Gleixner 		 * Read high then low, and then make sure high is
549702785aSThomas Gleixner 		 * still the same; this will only loop if low wraps
559702785aSThomas Gleixner 		 * and carries into high.
569702785aSThomas Gleixner 		 * XXX some clean way to make this endian-proof?
579702785aSThomas Gleixner 		 */
589702785aSThomas Gleixner 		do {
599702785aSThomas Gleixner 			h = p32[1];
609702785aSThomas Gleixner 			barrier();
619702785aSThomas Gleixner 			l = p32[0];
629702785aSThomas Gleixner 			barrier();
639702785aSThomas Gleixner 		} while (p32[1] != h);
649702785aSThomas Gleixner 
659702785aSThomas Gleixner 		ret = (((u64)h) << 32) | l;
669702785aSThomas Gleixner 	} else
679702785aSThomas Gleixner 		ret = *p;
689702785aSThomas Gleixner 
699702785aSThomas Gleixner 	return ret;
709702785aSThomas Gleixner }
719702785aSThomas Gleixner 
729702785aSThomas Gleixner /*
739702785aSThomas Gleixner  * Runstate accounting
749702785aSThomas Gleixner  */
759702785aSThomas Gleixner static void get_runstate_snapshot(struct vcpu_runstate_info *res)
769702785aSThomas Gleixner {
779702785aSThomas Gleixner 	u64 state_time;
789702785aSThomas Gleixner 	struct vcpu_runstate_info *state;
799702785aSThomas Gleixner 
809702785aSThomas Gleixner 	BUG_ON(preemptible());
819702785aSThomas Gleixner 
82c6e22f9eSTejun Heo 	state = &__get_cpu_var(xen_runstate);
839702785aSThomas Gleixner 
849702785aSThomas Gleixner 	/*
859702785aSThomas Gleixner 	 * The runstate info is always updated by the hypervisor on
869702785aSThomas Gleixner 	 * the current CPU, so there's no need to use anything
879702785aSThomas Gleixner 	 * stronger than a compiler barrier when fetching it.
889702785aSThomas Gleixner 	 */
899702785aSThomas Gleixner 	do {
909702785aSThomas Gleixner 		state_time = get64(&state->state_entry_time);
919702785aSThomas Gleixner 		barrier();
929702785aSThomas Gleixner 		*res = *state;
939702785aSThomas Gleixner 		barrier();
949702785aSThomas Gleixner 	} while (get64(&state->state_entry_time) != state_time);
959702785aSThomas Gleixner }
969702785aSThomas Gleixner 
97f0d73394SJeremy Fitzhardinge /* return true when a vcpu could run but has no real cpu to run on */
98f0d73394SJeremy Fitzhardinge bool xen_vcpu_stolen(int vcpu)
99f0d73394SJeremy Fitzhardinge {
100c6e22f9eSTejun Heo 	return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable;
101f0d73394SJeremy Fitzhardinge }
102f0d73394SJeremy Fitzhardinge 
103be012920SIan Campbell void xen_setup_runstate_info(int cpu)
1049702785aSThomas Gleixner {
1059702785aSThomas Gleixner 	struct vcpu_register_runstate_memory_area area;
1069702785aSThomas Gleixner 
107c6e22f9eSTejun Heo 	area.addr.v = &per_cpu(xen_runstate, cpu);
1089702785aSThomas Gleixner 
1099702785aSThomas Gleixner 	if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area,
1109702785aSThomas Gleixner 			       cpu, &area))
1119702785aSThomas Gleixner 		BUG();
1129702785aSThomas Gleixner }
1139702785aSThomas Gleixner 
1149702785aSThomas Gleixner static void do_stolen_accounting(void)
1159702785aSThomas Gleixner {
1169702785aSThomas Gleixner 	struct vcpu_runstate_info state;
1179702785aSThomas Gleixner 	struct vcpu_runstate_info *snap;
1189702785aSThomas Gleixner 	s64 blocked, runnable, offline, stolen;
1199702785aSThomas Gleixner 	cputime_t ticks;
1209702785aSThomas Gleixner 
1219702785aSThomas Gleixner 	get_runstate_snapshot(&state);
1229702785aSThomas Gleixner 
1239702785aSThomas Gleixner 	WARN_ON(state.state != RUNSTATE_running);
1249702785aSThomas Gleixner 
125c6e22f9eSTejun Heo 	snap = &__get_cpu_var(xen_runstate_snapshot);
1269702785aSThomas Gleixner 
1279702785aSThomas Gleixner 	/* work out how much time the VCPU has not been runn*ing*  */
1289702785aSThomas Gleixner 	blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked];
1299702785aSThomas Gleixner 	runnable = state.time[RUNSTATE_runnable] - snap->time[RUNSTATE_runnable];
1309702785aSThomas Gleixner 	offline = state.time[RUNSTATE_offline] - snap->time[RUNSTATE_offline];
1319702785aSThomas Gleixner 
1329702785aSThomas Gleixner 	*snap = state;
1339702785aSThomas Gleixner 
1349702785aSThomas Gleixner 	/* Add the appropriate number of ticks of stolen time,
13579741dd3SMartin Schwidefsky 	   including any left-overs from last time. */
136780f36d8SChristoph Lameter 	stolen = runnable + offline + __this_cpu_read(xen_residual_stolen);
1379702785aSThomas Gleixner 
1389702785aSThomas Gleixner 	if (stolen < 0)
1399702785aSThomas Gleixner 		stolen = 0;
1409702785aSThomas Gleixner 
141f595ec96SJeremy Fitzhardinge 	ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
142780f36d8SChristoph Lameter 	__this_cpu_write(xen_residual_stolen, stolen);
14379741dd3SMartin Schwidefsky 	account_steal_ticks(ticks);
1449702785aSThomas Gleixner 
1459702785aSThomas Gleixner 	/* Add the appropriate number of ticks of blocked time,
14679741dd3SMartin Schwidefsky 	   including any left-overs from last time. */
147780f36d8SChristoph Lameter 	blocked += __this_cpu_read(xen_residual_blocked);
1489702785aSThomas Gleixner 
1499702785aSThomas Gleixner 	if (blocked < 0)
1509702785aSThomas Gleixner 		blocked = 0;
1519702785aSThomas Gleixner 
152f595ec96SJeremy Fitzhardinge 	ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
153780f36d8SChristoph Lameter 	__this_cpu_write(xen_residual_blocked, blocked);
15479741dd3SMartin Schwidefsky 	account_idle_ticks(ticks);
1559702785aSThomas Gleixner }
1569702785aSThomas Gleixner 
157e93ef949SAlok Kataria /* Get the TSC speed from Xen */
158409771d2SStefano Stabellini static unsigned long xen_tsc_khz(void)
1599702785aSThomas Gleixner {
1603807f345SGlauber Costa 	struct pvclock_vcpu_time_info *info =
1619702785aSThomas Gleixner 		&HYPERVISOR_shared_info->vcpu_info[0].time;
1629702785aSThomas Gleixner 
1633807f345SGlauber Costa 	return pvclock_tsc_khz(info);
1649702785aSThomas Gleixner }
1659702785aSThomas Gleixner 
166ee7686bcSJeremy Fitzhardinge cycle_t xen_clocksource_read(void)
1679702785aSThomas Gleixner {
1681c7b67f7SGerd Hoffmann         struct pvclock_vcpu_time_info *src;
1699702785aSThomas Gleixner 	cycle_t ret;
1709702785aSThomas Gleixner 
1711c7b67f7SGerd Hoffmann 	src = &get_cpu_var(xen_vcpu)->time;
1721c7b67f7SGerd Hoffmann 	ret = pvclock_clocksource_read(src);
1731c7b67f7SGerd Hoffmann 	put_cpu_var(xen_vcpu);
1749702785aSThomas Gleixner 	return ret;
1759702785aSThomas Gleixner }
1769702785aSThomas Gleixner 
1778e19608eSMagnus Damm static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
1788e19608eSMagnus Damm {
1798e19608eSMagnus Damm 	return xen_clocksource_read();
1808e19608eSMagnus Damm }
1818e19608eSMagnus Damm 
1829702785aSThomas Gleixner static void xen_read_wallclock(struct timespec *ts)
1839702785aSThomas Gleixner {
1841c7b67f7SGerd Hoffmann 	struct shared_info *s = HYPERVISOR_shared_info;
1851c7b67f7SGerd Hoffmann 	struct pvclock_wall_clock *wall_clock = &(s->wc);
1861c7b67f7SGerd Hoffmann         struct pvclock_vcpu_time_info *vcpu_time;
1879702785aSThomas Gleixner 
1881c7b67f7SGerd Hoffmann 	vcpu_time = &get_cpu_var(xen_vcpu)->time;
1891c7b67f7SGerd Hoffmann 	pvclock_read_wallclock(wall_clock, vcpu_time, ts);
1901c7b67f7SGerd Hoffmann 	put_cpu_var(xen_vcpu);
1919702785aSThomas Gleixner }
1929702785aSThomas Gleixner 
193409771d2SStefano Stabellini static unsigned long xen_get_wallclock(void)
1949702785aSThomas Gleixner {
1959702785aSThomas Gleixner 	struct timespec ts;
1969702785aSThomas Gleixner 
1979702785aSThomas Gleixner 	xen_read_wallclock(&ts);
1989702785aSThomas Gleixner 	return ts.tv_sec;
1999702785aSThomas Gleixner }
2009702785aSThomas Gleixner 
201409771d2SStefano Stabellini static int xen_set_wallclock(unsigned long now)
2029702785aSThomas Gleixner {
203*fdb9eb9fSJeremy Fitzhardinge 	struct xen_platform_op op;
204*fdb9eb9fSJeremy Fitzhardinge 	int rc;
205*fdb9eb9fSJeremy Fitzhardinge 
2069702785aSThomas Gleixner 	/* do nothing for domU */
207*fdb9eb9fSJeremy Fitzhardinge 	if (!xen_initial_domain())
2089702785aSThomas Gleixner 		return -1;
209*fdb9eb9fSJeremy Fitzhardinge 
210*fdb9eb9fSJeremy Fitzhardinge 	op.cmd = XENPF_settime;
211*fdb9eb9fSJeremy Fitzhardinge 	op.u.settime.secs = now;
212*fdb9eb9fSJeremy Fitzhardinge 	op.u.settime.nsecs = 0;
213*fdb9eb9fSJeremy Fitzhardinge 	op.u.settime.system_time = xen_clocksource_read();
214*fdb9eb9fSJeremy Fitzhardinge 
215*fdb9eb9fSJeremy Fitzhardinge 	rc = HYPERVISOR_dom0_op(&op);
216*fdb9eb9fSJeremy Fitzhardinge 	WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now);
217*fdb9eb9fSJeremy Fitzhardinge 
218*fdb9eb9fSJeremy Fitzhardinge 	return rc;
2199702785aSThomas Gleixner }
2209702785aSThomas Gleixner 
2219702785aSThomas Gleixner static struct clocksource xen_clocksource __read_mostly = {
2229702785aSThomas Gleixner 	.name = "xen",
2239702785aSThomas Gleixner 	.rating = 400,
2248e19608eSMagnus Damm 	.read = xen_clocksource_get_cycles,
2259702785aSThomas Gleixner 	.mask = ~0,
2269702785aSThomas Gleixner 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
2279702785aSThomas Gleixner };
2289702785aSThomas Gleixner 
2299702785aSThomas Gleixner /*
2309702785aSThomas Gleixner    Xen clockevent implementation
2319702785aSThomas Gleixner 
2329702785aSThomas Gleixner    Xen has two clockevent implementations:
2339702785aSThomas Gleixner 
2349702785aSThomas Gleixner    The old timer_op one works with all released versions of Xen prior
2359702785aSThomas Gleixner    to version 3.0.4.  This version of the hypervisor provides a
2369702785aSThomas Gleixner    single-shot timer with nanosecond resolution.  However, sharing the
2379702785aSThomas Gleixner    same event channel is a 100Hz tick which is delivered while the
2389702785aSThomas Gleixner    vcpu is running.  We don't care about or use this tick, but it will
2399702785aSThomas Gleixner    cause the core time code to think the timer fired too soon, and
2409702785aSThomas Gleixner    will end up resetting it each time.  It could be filtered, but
2419702785aSThomas Gleixner    doing so has complications when the ktime clocksource is not yet
2429702785aSThomas Gleixner    the xen clocksource (ie, at boot time).
2439702785aSThomas Gleixner 
2449702785aSThomas Gleixner    The new vcpu_op-based timer interface allows the tick timer period
2459702785aSThomas Gleixner    to be changed or turned off.  The tick timer is not useful as a
2469702785aSThomas Gleixner    periodic timer because events are only delivered to running vcpus.
2479702785aSThomas Gleixner    The one-shot timer can report when a timeout is in the past, so
2489702785aSThomas Gleixner    set_next_event is capable of returning -ETIME when appropriate.
2499702785aSThomas Gleixner    This interface is used when available.
2509702785aSThomas Gleixner */
2519702785aSThomas Gleixner 
2529702785aSThomas Gleixner 
2539702785aSThomas Gleixner /*
2549702785aSThomas Gleixner   Get a hypervisor absolute time.  In theory we could maintain an
2559702785aSThomas Gleixner   offset between the kernel's time and the hypervisor's time, and
2569702785aSThomas Gleixner   apply that to a kernel's absolute timeout.  Unfortunately the
2579702785aSThomas Gleixner   hypervisor and kernel times can drift even if the kernel is using
2589702785aSThomas Gleixner   the Xen clocksource, because ntp can warp the kernel's clocksource.
2599702785aSThomas Gleixner */
2609702785aSThomas Gleixner static s64 get_abs_timeout(unsigned long delta)
2619702785aSThomas Gleixner {
2629702785aSThomas Gleixner 	return xen_clocksource_read() + delta;
2639702785aSThomas Gleixner }
2649702785aSThomas Gleixner 
2659702785aSThomas Gleixner static void xen_timerop_set_mode(enum clock_event_mode mode,
2669702785aSThomas Gleixner 				 struct clock_event_device *evt)
2679702785aSThomas Gleixner {
2689702785aSThomas Gleixner 	switch (mode) {
2699702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
2709702785aSThomas Gleixner 		/* unsupported */
2719702785aSThomas Gleixner 		WARN_ON(1);
2729702785aSThomas Gleixner 		break;
2739702785aSThomas Gleixner 
2749702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
2759702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
2769702785aSThomas Gleixner 		break;
2779702785aSThomas Gleixner 
2789702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
2799702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
2809702785aSThomas Gleixner 		HYPERVISOR_set_timer_op(0);  /* cancel timeout */
2819702785aSThomas Gleixner 		break;
2829702785aSThomas Gleixner 	}
2839702785aSThomas Gleixner }
2849702785aSThomas Gleixner 
2859702785aSThomas Gleixner static int xen_timerop_set_next_event(unsigned long delta,
2869702785aSThomas Gleixner 				      struct clock_event_device *evt)
2879702785aSThomas Gleixner {
2889702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
2899702785aSThomas Gleixner 
2909702785aSThomas Gleixner 	if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0)
2919702785aSThomas Gleixner 		BUG();
2929702785aSThomas Gleixner 
2939702785aSThomas Gleixner 	/* We may have missed the deadline, but there's no real way of
2949702785aSThomas Gleixner 	   knowing for sure.  If the event was in the past, then we'll
2959702785aSThomas Gleixner 	   get an immediate interrupt. */
2969702785aSThomas Gleixner 
2979702785aSThomas Gleixner 	return 0;
2989702785aSThomas Gleixner }
2999702785aSThomas Gleixner 
3009702785aSThomas Gleixner static const struct clock_event_device xen_timerop_clockevent = {
3019702785aSThomas Gleixner 	.name = "xen",
3029702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
3039702785aSThomas Gleixner 
3049702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
3059702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
3069702785aSThomas Gleixner 
3079702785aSThomas Gleixner 	.mult = 1,
3089702785aSThomas Gleixner 	.shift = 0,
3099702785aSThomas Gleixner 	.rating = 500,
3109702785aSThomas Gleixner 
3119702785aSThomas Gleixner 	.set_mode = xen_timerop_set_mode,
3129702785aSThomas Gleixner 	.set_next_event = xen_timerop_set_next_event,
3139702785aSThomas Gleixner };
3149702785aSThomas Gleixner 
3159702785aSThomas Gleixner 
3169702785aSThomas Gleixner 
3179702785aSThomas Gleixner static void xen_vcpuop_set_mode(enum clock_event_mode mode,
3189702785aSThomas Gleixner 				struct clock_event_device *evt)
3199702785aSThomas Gleixner {
3209702785aSThomas Gleixner 	int cpu = smp_processor_id();
3219702785aSThomas Gleixner 
3229702785aSThomas Gleixner 	switch (mode) {
3239702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
3249702785aSThomas Gleixner 		WARN_ON(1);	/* unsupported */
3259702785aSThomas Gleixner 		break;
3269702785aSThomas Gleixner 
3279702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
3289702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3299702785aSThomas Gleixner 			BUG();
3309702785aSThomas Gleixner 		break;
3319702785aSThomas Gleixner 
3329702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
3339702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
3349702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, cpu, NULL) ||
3359702785aSThomas Gleixner 		    HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3369702785aSThomas Gleixner 			BUG();
3379702785aSThomas Gleixner 		break;
3389702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
3399702785aSThomas Gleixner 		break;
3409702785aSThomas Gleixner 	}
3419702785aSThomas Gleixner }
3429702785aSThomas Gleixner 
3439702785aSThomas Gleixner static int xen_vcpuop_set_next_event(unsigned long delta,
3449702785aSThomas Gleixner 				     struct clock_event_device *evt)
3459702785aSThomas Gleixner {
3469702785aSThomas Gleixner 	int cpu = smp_processor_id();
3479702785aSThomas Gleixner 	struct vcpu_set_singleshot_timer single;
3489702785aSThomas Gleixner 	int ret;
3499702785aSThomas Gleixner 
3509702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
3519702785aSThomas Gleixner 
3529702785aSThomas Gleixner 	single.timeout_abs_ns = get_abs_timeout(delta);
3539702785aSThomas Gleixner 	single.flags = VCPU_SSHOTTMR_future;
3549702785aSThomas Gleixner 
3559702785aSThomas Gleixner 	ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
3569702785aSThomas Gleixner 
3579702785aSThomas Gleixner 	BUG_ON(ret != 0 && ret != -ETIME);
3589702785aSThomas Gleixner 
3599702785aSThomas Gleixner 	return ret;
3609702785aSThomas Gleixner }
3619702785aSThomas Gleixner 
3629702785aSThomas Gleixner static const struct clock_event_device xen_vcpuop_clockevent = {
3639702785aSThomas Gleixner 	.name = "xen",
3649702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
3659702785aSThomas Gleixner 
3669702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
3679702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
3689702785aSThomas Gleixner 
3699702785aSThomas Gleixner 	.mult = 1,
3709702785aSThomas Gleixner 	.shift = 0,
3719702785aSThomas Gleixner 	.rating = 500,
3729702785aSThomas Gleixner 
3739702785aSThomas Gleixner 	.set_mode = xen_vcpuop_set_mode,
3749702785aSThomas Gleixner 	.set_next_event = xen_vcpuop_set_next_event,
3759702785aSThomas Gleixner };
3769702785aSThomas Gleixner 
3779702785aSThomas Gleixner static const struct clock_event_device *xen_clockevent =
3789702785aSThomas Gleixner 	&xen_timerop_clockevent;
3799702785aSThomas Gleixner static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events);
3809702785aSThomas Gleixner 
3819702785aSThomas Gleixner static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
3829702785aSThomas Gleixner {
3839702785aSThomas Gleixner 	struct clock_event_device *evt = &__get_cpu_var(xen_clock_events);
3849702785aSThomas Gleixner 	irqreturn_t ret;
3859702785aSThomas Gleixner 
3869702785aSThomas Gleixner 	ret = IRQ_NONE;
3879702785aSThomas Gleixner 	if (evt->event_handler) {
3889702785aSThomas Gleixner 		evt->event_handler(evt);
3899702785aSThomas Gleixner 		ret = IRQ_HANDLED;
3909702785aSThomas Gleixner 	}
3919702785aSThomas Gleixner 
3929702785aSThomas Gleixner 	do_stolen_accounting();
3939702785aSThomas Gleixner 
3949702785aSThomas Gleixner 	return ret;
3959702785aSThomas Gleixner }
3969702785aSThomas Gleixner 
3979702785aSThomas Gleixner void xen_setup_timer(int cpu)
3989702785aSThomas Gleixner {
3999702785aSThomas Gleixner 	const char *name;
4009702785aSThomas Gleixner 	struct clock_event_device *evt;
4019702785aSThomas Gleixner 	int irq;
4029702785aSThomas Gleixner 
4039702785aSThomas Gleixner 	printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
4049702785aSThomas Gleixner 
4059702785aSThomas Gleixner 	name = kasprintf(GFP_KERNEL, "timer%d", cpu);
4069702785aSThomas Gleixner 	if (!name)
4079702785aSThomas Gleixner 		name = "<timer kasprintf failed>";
4089702785aSThomas Gleixner 
4099702785aSThomas Gleixner 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
410f611f2daSIan Campbell 				      IRQF_DISABLED|IRQF_PERCPU|
411f611f2daSIan Campbell 				      IRQF_NOBALANCING|IRQF_TIMER|
412f611f2daSIan Campbell 				      IRQF_FORCE_RESUME,
4139702785aSThomas Gleixner 				      name, NULL);
4149702785aSThomas Gleixner 
4159702785aSThomas Gleixner 	evt = &per_cpu(xen_clock_events, cpu);
4169702785aSThomas Gleixner 	memcpy(evt, xen_clockevent, sizeof(*evt));
4179702785aSThomas Gleixner 
418320ab2b0SRusty Russell 	evt->cpumask = cpumask_of(cpu);
4199702785aSThomas Gleixner 	evt->irq = irq;
4209702785aSThomas Gleixner }
4219702785aSThomas Gleixner 
422d68d82afSAlex Nixon void xen_teardown_timer(int cpu)
423d68d82afSAlex Nixon {
424d68d82afSAlex Nixon 	struct clock_event_device *evt;
425d68d82afSAlex Nixon 	BUG_ON(cpu == 0);
426d68d82afSAlex Nixon 	evt = &per_cpu(xen_clock_events, cpu);
427d68d82afSAlex Nixon 	unbind_from_irqhandler(evt->irq, NULL);
428d68d82afSAlex Nixon }
429d68d82afSAlex Nixon 
4309702785aSThomas Gleixner void xen_setup_cpu_clockevents(void)
4319702785aSThomas Gleixner {
4329702785aSThomas Gleixner 	BUG_ON(preemptible());
4339702785aSThomas Gleixner 
4349702785aSThomas Gleixner 	clockevents_register_device(&__get_cpu_var(xen_clock_events));
4359702785aSThomas Gleixner }
4369702785aSThomas Gleixner 
437d07af1f0SJeremy Fitzhardinge void xen_timer_resume(void)
438d07af1f0SJeremy Fitzhardinge {
439d07af1f0SJeremy Fitzhardinge 	int cpu;
440d07af1f0SJeremy Fitzhardinge 
441e7a3481cSJeremy Fitzhardinge 	pvclock_resume();
442e7a3481cSJeremy Fitzhardinge 
443d07af1f0SJeremy Fitzhardinge 	if (xen_clockevent != &xen_vcpuop_clockevent)
444d07af1f0SJeremy Fitzhardinge 		return;
445d07af1f0SJeremy Fitzhardinge 
446d07af1f0SJeremy Fitzhardinge 	for_each_online_cpu(cpu) {
447d07af1f0SJeremy Fitzhardinge 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
448d07af1f0SJeremy Fitzhardinge 			BUG();
449d07af1f0SJeremy Fitzhardinge 	}
450d07af1f0SJeremy Fitzhardinge }
451d07af1f0SJeremy Fitzhardinge 
452fb6ce5deSDaniel Kiper static const struct pv_time_ops xen_time_ops __initconst = {
453ca50a5f3SJeremy Fitzhardinge 	.sched_clock = xen_clocksource_read,
454409771d2SStefano Stabellini };
455409771d2SStefano Stabellini 
456fb6ce5deSDaniel Kiper static void __init xen_time_init(void)
4579702785aSThomas Gleixner {
4589702785aSThomas Gleixner 	int cpu = smp_processor_id();
459c4507257SJohn Stultz 	struct timespec tp;
4609702785aSThomas Gleixner 
461b01cc1b0SJohn Stultz 	clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
4629702785aSThomas Gleixner 
4639702785aSThomas Gleixner 	if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) {
4649702785aSThomas Gleixner 		/* Successfully turned off 100Hz tick, so we have the
4659702785aSThomas Gleixner 		   vcpuop-based timer interface */
4669702785aSThomas Gleixner 		printk(KERN_DEBUG "Xen: using vcpuop timer interface\n");
4679702785aSThomas Gleixner 		xen_clockevent = &xen_vcpuop_clockevent;
4689702785aSThomas Gleixner 	}
4699702785aSThomas Gleixner 
4709702785aSThomas Gleixner 	/* Set initial system time with full resolution */
471c4507257SJohn Stultz 	xen_read_wallclock(&tp);
472c4507257SJohn Stultz 	do_settimeofday(&tp);
4739702785aSThomas Gleixner 
474404ee5b1SAndi Kleen 	setup_force_cpu_cap(X86_FEATURE_TSC);
4759702785aSThomas Gleixner 
476be012920SIan Campbell 	xen_setup_runstate_info(cpu);
4779702785aSThomas Gleixner 	xen_setup_timer(cpu);
4789702785aSThomas Gleixner 	xen_setup_cpu_clockevents();
4799702785aSThomas Gleixner }
480409771d2SStefano Stabellini 
481fb6ce5deSDaniel Kiper void __init xen_init_time_ops(void)
482409771d2SStefano Stabellini {
483409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
484409771d2SStefano Stabellini 
485409771d2SStefano Stabellini 	x86_init.timers.timer_init = xen_time_init;
486409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = x86_init_noop;
487409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
488409771d2SStefano Stabellini 
489409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
490409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
491409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
492409771d2SStefano Stabellini }
493409771d2SStefano Stabellini 
494ca65f9fcSStefano Stabellini #ifdef CONFIG_XEN_PVHVM
495409771d2SStefano Stabellini static void xen_hvm_setup_cpu_clockevents(void)
496409771d2SStefano Stabellini {
497409771d2SStefano Stabellini 	int cpu = smp_processor_id();
498409771d2SStefano Stabellini 	xen_setup_runstate_info(cpu);
499409771d2SStefano Stabellini 	xen_setup_timer(cpu);
500409771d2SStefano Stabellini 	xen_setup_cpu_clockevents();
501409771d2SStefano Stabellini }
502409771d2SStefano Stabellini 
503fb6ce5deSDaniel Kiper void __init xen_hvm_init_time_ops(void)
504409771d2SStefano Stabellini {
505409771d2SStefano Stabellini 	/* vector callback is needed otherwise we cannot receive interrupts
50631e7e931SStefano Stabellini 	 * on cpu > 0 and at this point we don't know how many cpus are
50731e7e931SStefano Stabellini 	 * available */
50831e7e931SStefano Stabellini 	if (!xen_have_vector_callback)
509409771d2SStefano Stabellini 		return;
510409771d2SStefano Stabellini 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
511409771d2SStefano Stabellini 		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
512409771d2SStefano Stabellini 				"disable pv timer\n");
513409771d2SStefano Stabellini 		return;
514409771d2SStefano Stabellini 	}
515409771d2SStefano Stabellini 
516409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
517409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = xen_time_init;
518409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
519409771d2SStefano Stabellini 
520409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
521409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
522409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
523409771d2SStefano Stabellini }
524ca65f9fcSStefano Stabellini #endif
525