xref: /linux/arch/x86/xen/time.c (revision fb6ce5dea4bb704bfcd9fda7e6b1354da66f4d2f)
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 #define XEN_SHIFT 22
309702785aSThomas Gleixner 
319702785aSThomas Gleixner /* Xen may fire a timer up to this many ns early */
329702785aSThomas Gleixner #define TIMER_SLOP	100000
339702785aSThomas Gleixner #define NS_PER_TICK	(1000000000LL / HZ)
349702785aSThomas Gleixner 
359702785aSThomas Gleixner /* runstate info updated by Xen */
36c6e22f9eSTejun Heo static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
379702785aSThomas Gleixner 
389702785aSThomas Gleixner /* snapshots of runstate info */
39c6e22f9eSTejun Heo static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot);
409702785aSThomas Gleixner 
419702785aSThomas Gleixner /* unused ns of stolen and blocked time */
42c6e22f9eSTejun Heo static DEFINE_PER_CPU(u64, xen_residual_stolen);
43c6e22f9eSTejun Heo static DEFINE_PER_CPU(u64, xen_residual_blocked);
449702785aSThomas Gleixner 
459702785aSThomas Gleixner /* return an consistent snapshot of 64-bit time/counter value */
469702785aSThomas Gleixner static u64 get64(const u64 *p)
479702785aSThomas Gleixner {
489702785aSThomas Gleixner 	u64 ret;
499702785aSThomas Gleixner 
509702785aSThomas Gleixner 	if (BITS_PER_LONG < 64) {
519702785aSThomas Gleixner 		u32 *p32 = (u32 *)p;
529702785aSThomas Gleixner 		u32 h, l;
539702785aSThomas Gleixner 
549702785aSThomas Gleixner 		/*
559702785aSThomas Gleixner 		 * Read high then low, and then make sure high is
569702785aSThomas Gleixner 		 * still the same; this will only loop if low wraps
579702785aSThomas Gleixner 		 * and carries into high.
589702785aSThomas Gleixner 		 * XXX some clean way to make this endian-proof?
599702785aSThomas Gleixner 		 */
609702785aSThomas Gleixner 		do {
619702785aSThomas Gleixner 			h = p32[1];
629702785aSThomas Gleixner 			barrier();
639702785aSThomas Gleixner 			l = p32[0];
649702785aSThomas Gleixner 			barrier();
659702785aSThomas Gleixner 		} while (p32[1] != h);
669702785aSThomas Gleixner 
679702785aSThomas Gleixner 		ret = (((u64)h) << 32) | l;
689702785aSThomas Gleixner 	} else
699702785aSThomas Gleixner 		ret = *p;
709702785aSThomas Gleixner 
719702785aSThomas Gleixner 	return ret;
729702785aSThomas Gleixner }
739702785aSThomas Gleixner 
749702785aSThomas Gleixner /*
759702785aSThomas Gleixner  * Runstate accounting
769702785aSThomas Gleixner  */
779702785aSThomas Gleixner static void get_runstate_snapshot(struct vcpu_runstate_info *res)
789702785aSThomas Gleixner {
799702785aSThomas Gleixner 	u64 state_time;
809702785aSThomas Gleixner 	struct vcpu_runstate_info *state;
819702785aSThomas Gleixner 
829702785aSThomas Gleixner 	BUG_ON(preemptible());
839702785aSThomas Gleixner 
84c6e22f9eSTejun Heo 	state = &__get_cpu_var(xen_runstate);
859702785aSThomas Gleixner 
869702785aSThomas Gleixner 	/*
879702785aSThomas Gleixner 	 * The runstate info is always updated by the hypervisor on
889702785aSThomas Gleixner 	 * the current CPU, so there's no need to use anything
899702785aSThomas Gleixner 	 * stronger than a compiler barrier when fetching it.
909702785aSThomas Gleixner 	 */
919702785aSThomas Gleixner 	do {
929702785aSThomas Gleixner 		state_time = get64(&state->state_entry_time);
939702785aSThomas Gleixner 		barrier();
949702785aSThomas Gleixner 		*res = *state;
959702785aSThomas Gleixner 		barrier();
969702785aSThomas Gleixner 	} while (get64(&state->state_entry_time) != state_time);
979702785aSThomas Gleixner }
989702785aSThomas Gleixner 
99f0d73394SJeremy Fitzhardinge /* return true when a vcpu could run but has no real cpu to run on */
100f0d73394SJeremy Fitzhardinge bool xen_vcpu_stolen(int vcpu)
101f0d73394SJeremy Fitzhardinge {
102c6e22f9eSTejun Heo 	return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable;
103f0d73394SJeremy Fitzhardinge }
104f0d73394SJeremy Fitzhardinge 
105be012920SIan Campbell void xen_setup_runstate_info(int cpu)
1069702785aSThomas Gleixner {
1079702785aSThomas Gleixner 	struct vcpu_register_runstate_memory_area area;
1089702785aSThomas Gleixner 
109c6e22f9eSTejun Heo 	area.addr.v = &per_cpu(xen_runstate, cpu);
1109702785aSThomas Gleixner 
1119702785aSThomas Gleixner 	if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area,
1129702785aSThomas Gleixner 			       cpu, &area))
1139702785aSThomas Gleixner 		BUG();
1149702785aSThomas Gleixner }
1159702785aSThomas Gleixner 
1169702785aSThomas Gleixner static void do_stolen_accounting(void)
1179702785aSThomas Gleixner {
1189702785aSThomas Gleixner 	struct vcpu_runstate_info state;
1199702785aSThomas Gleixner 	struct vcpu_runstate_info *snap;
1209702785aSThomas Gleixner 	s64 blocked, runnable, offline, stolen;
1219702785aSThomas Gleixner 	cputime_t ticks;
1229702785aSThomas Gleixner 
1239702785aSThomas Gleixner 	get_runstate_snapshot(&state);
1249702785aSThomas Gleixner 
1259702785aSThomas Gleixner 	WARN_ON(state.state != RUNSTATE_running);
1269702785aSThomas Gleixner 
127c6e22f9eSTejun Heo 	snap = &__get_cpu_var(xen_runstate_snapshot);
1289702785aSThomas Gleixner 
1299702785aSThomas Gleixner 	/* work out how much time the VCPU has not been runn*ing*  */
1309702785aSThomas Gleixner 	blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked];
1319702785aSThomas Gleixner 	runnable = state.time[RUNSTATE_runnable] - snap->time[RUNSTATE_runnable];
1329702785aSThomas Gleixner 	offline = state.time[RUNSTATE_offline] - snap->time[RUNSTATE_offline];
1339702785aSThomas Gleixner 
1349702785aSThomas Gleixner 	*snap = state;
1359702785aSThomas Gleixner 
1369702785aSThomas Gleixner 	/* Add the appropriate number of ticks of stolen time,
13779741dd3SMartin Schwidefsky 	   including any left-overs from last time. */
138780f36d8SChristoph Lameter 	stolen = runnable + offline + __this_cpu_read(xen_residual_stolen);
1399702785aSThomas Gleixner 
1409702785aSThomas Gleixner 	if (stolen < 0)
1419702785aSThomas Gleixner 		stolen = 0;
1429702785aSThomas Gleixner 
143f595ec96SJeremy Fitzhardinge 	ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
144780f36d8SChristoph Lameter 	__this_cpu_write(xen_residual_stolen, stolen);
14579741dd3SMartin Schwidefsky 	account_steal_ticks(ticks);
1469702785aSThomas Gleixner 
1479702785aSThomas Gleixner 	/* Add the appropriate number of ticks of blocked time,
14879741dd3SMartin Schwidefsky 	   including any left-overs from last time. */
149780f36d8SChristoph Lameter 	blocked += __this_cpu_read(xen_residual_blocked);
1509702785aSThomas Gleixner 
1519702785aSThomas Gleixner 	if (blocked < 0)
1529702785aSThomas Gleixner 		blocked = 0;
1539702785aSThomas Gleixner 
154f595ec96SJeremy Fitzhardinge 	ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
155780f36d8SChristoph Lameter 	__this_cpu_write(xen_residual_blocked, blocked);
15679741dd3SMartin Schwidefsky 	account_idle_ticks(ticks);
1579702785aSThomas Gleixner }
1589702785aSThomas Gleixner 
159e93ef949SAlok Kataria /* Get the TSC speed from Xen */
160409771d2SStefano Stabellini static unsigned long xen_tsc_khz(void)
1619702785aSThomas Gleixner {
1623807f345SGlauber Costa 	struct pvclock_vcpu_time_info *info =
1639702785aSThomas Gleixner 		&HYPERVISOR_shared_info->vcpu_info[0].time;
1649702785aSThomas Gleixner 
1653807f345SGlauber Costa 	return pvclock_tsc_khz(info);
1669702785aSThomas Gleixner }
1679702785aSThomas Gleixner 
168ee7686bcSJeremy Fitzhardinge cycle_t xen_clocksource_read(void)
1699702785aSThomas Gleixner {
1701c7b67f7SGerd Hoffmann         struct pvclock_vcpu_time_info *src;
1719702785aSThomas Gleixner 	cycle_t ret;
1729702785aSThomas Gleixner 
1731c7b67f7SGerd Hoffmann 	src = &get_cpu_var(xen_vcpu)->time;
1741c7b67f7SGerd Hoffmann 	ret = pvclock_clocksource_read(src);
1751c7b67f7SGerd Hoffmann 	put_cpu_var(xen_vcpu);
1769702785aSThomas Gleixner 	return ret;
1779702785aSThomas Gleixner }
1789702785aSThomas Gleixner 
1798e19608eSMagnus Damm static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
1808e19608eSMagnus Damm {
1818e19608eSMagnus Damm 	return xen_clocksource_read();
1828e19608eSMagnus Damm }
1838e19608eSMagnus Damm 
1849702785aSThomas Gleixner static void xen_read_wallclock(struct timespec *ts)
1859702785aSThomas Gleixner {
1861c7b67f7SGerd Hoffmann 	struct shared_info *s = HYPERVISOR_shared_info;
1871c7b67f7SGerd Hoffmann 	struct pvclock_wall_clock *wall_clock = &(s->wc);
1881c7b67f7SGerd Hoffmann         struct pvclock_vcpu_time_info *vcpu_time;
1899702785aSThomas Gleixner 
1901c7b67f7SGerd Hoffmann 	vcpu_time = &get_cpu_var(xen_vcpu)->time;
1911c7b67f7SGerd Hoffmann 	pvclock_read_wallclock(wall_clock, vcpu_time, ts);
1921c7b67f7SGerd Hoffmann 	put_cpu_var(xen_vcpu);
1939702785aSThomas Gleixner }
1949702785aSThomas Gleixner 
195409771d2SStefano Stabellini static unsigned long xen_get_wallclock(void)
1969702785aSThomas Gleixner {
1979702785aSThomas Gleixner 	struct timespec ts;
1989702785aSThomas Gleixner 
1999702785aSThomas Gleixner 	xen_read_wallclock(&ts);
2009702785aSThomas Gleixner 	return ts.tv_sec;
2019702785aSThomas Gleixner }
2029702785aSThomas Gleixner 
203409771d2SStefano Stabellini static int xen_set_wallclock(unsigned long now)
2049702785aSThomas Gleixner {
2059702785aSThomas Gleixner 	/* do nothing for domU */
2069702785aSThomas Gleixner 	return -1;
2079702785aSThomas Gleixner }
2089702785aSThomas Gleixner 
2099702785aSThomas Gleixner static struct clocksource xen_clocksource __read_mostly = {
2109702785aSThomas Gleixner 	.name = "xen",
2119702785aSThomas Gleixner 	.rating = 400,
2128e19608eSMagnus Damm 	.read = xen_clocksource_get_cycles,
2139702785aSThomas Gleixner 	.mask = ~0,
2149702785aSThomas Gleixner 	.mult = 1<<XEN_SHIFT,		/* time directly in nanoseconds */
2159702785aSThomas Gleixner 	.shift = XEN_SHIFT,
2169702785aSThomas Gleixner 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
2179702785aSThomas Gleixner };
2189702785aSThomas Gleixner 
2199702785aSThomas Gleixner /*
2209702785aSThomas Gleixner    Xen clockevent implementation
2219702785aSThomas Gleixner 
2229702785aSThomas Gleixner    Xen has two clockevent implementations:
2239702785aSThomas Gleixner 
2249702785aSThomas Gleixner    The old timer_op one works with all released versions of Xen prior
2259702785aSThomas Gleixner    to version 3.0.4.  This version of the hypervisor provides a
2269702785aSThomas Gleixner    single-shot timer with nanosecond resolution.  However, sharing the
2279702785aSThomas Gleixner    same event channel is a 100Hz tick which is delivered while the
2289702785aSThomas Gleixner    vcpu is running.  We don't care about or use this tick, but it will
2299702785aSThomas Gleixner    cause the core time code to think the timer fired too soon, and
2309702785aSThomas Gleixner    will end up resetting it each time.  It could be filtered, but
2319702785aSThomas Gleixner    doing so has complications when the ktime clocksource is not yet
2329702785aSThomas Gleixner    the xen clocksource (ie, at boot time).
2339702785aSThomas Gleixner 
2349702785aSThomas Gleixner    The new vcpu_op-based timer interface allows the tick timer period
2359702785aSThomas Gleixner    to be changed or turned off.  The tick timer is not useful as a
2369702785aSThomas Gleixner    periodic timer because events are only delivered to running vcpus.
2379702785aSThomas Gleixner    The one-shot timer can report when a timeout is in the past, so
2389702785aSThomas Gleixner    set_next_event is capable of returning -ETIME when appropriate.
2399702785aSThomas Gleixner    This interface is used when available.
2409702785aSThomas Gleixner */
2419702785aSThomas Gleixner 
2429702785aSThomas Gleixner 
2439702785aSThomas Gleixner /*
2449702785aSThomas Gleixner   Get a hypervisor absolute time.  In theory we could maintain an
2459702785aSThomas Gleixner   offset between the kernel's time and the hypervisor's time, and
2469702785aSThomas Gleixner   apply that to a kernel's absolute timeout.  Unfortunately the
2479702785aSThomas Gleixner   hypervisor and kernel times can drift even if the kernel is using
2489702785aSThomas Gleixner   the Xen clocksource, because ntp can warp the kernel's clocksource.
2499702785aSThomas Gleixner */
2509702785aSThomas Gleixner static s64 get_abs_timeout(unsigned long delta)
2519702785aSThomas Gleixner {
2529702785aSThomas Gleixner 	return xen_clocksource_read() + delta;
2539702785aSThomas Gleixner }
2549702785aSThomas Gleixner 
2559702785aSThomas Gleixner static void xen_timerop_set_mode(enum clock_event_mode mode,
2569702785aSThomas Gleixner 				 struct clock_event_device *evt)
2579702785aSThomas Gleixner {
2589702785aSThomas Gleixner 	switch (mode) {
2599702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
2609702785aSThomas Gleixner 		/* unsupported */
2619702785aSThomas Gleixner 		WARN_ON(1);
2629702785aSThomas Gleixner 		break;
2639702785aSThomas Gleixner 
2649702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
2659702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
2669702785aSThomas Gleixner 		break;
2679702785aSThomas Gleixner 
2689702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
2699702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
2709702785aSThomas Gleixner 		HYPERVISOR_set_timer_op(0);  /* cancel timeout */
2719702785aSThomas Gleixner 		break;
2729702785aSThomas Gleixner 	}
2739702785aSThomas Gleixner }
2749702785aSThomas Gleixner 
2759702785aSThomas Gleixner static int xen_timerop_set_next_event(unsigned long delta,
2769702785aSThomas Gleixner 				      struct clock_event_device *evt)
2779702785aSThomas Gleixner {
2789702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
2799702785aSThomas Gleixner 
2809702785aSThomas Gleixner 	if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0)
2819702785aSThomas Gleixner 		BUG();
2829702785aSThomas Gleixner 
2839702785aSThomas Gleixner 	/* We may have missed the deadline, but there's no real way of
2849702785aSThomas Gleixner 	   knowing for sure.  If the event was in the past, then we'll
2859702785aSThomas Gleixner 	   get an immediate interrupt. */
2869702785aSThomas Gleixner 
2879702785aSThomas Gleixner 	return 0;
2889702785aSThomas Gleixner }
2899702785aSThomas Gleixner 
2909702785aSThomas Gleixner static const struct clock_event_device xen_timerop_clockevent = {
2919702785aSThomas Gleixner 	.name = "xen",
2929702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
2939702785aSThomas Gleixner 
2949702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
2959702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
2969702785aSThomas Gleixner 
2979702785aSThomas Gleixner 	.mult = 1,
2989702785aSThomas Gleixner 	.shift = 0,
2999702785aSThomas Gleixner 	.rating = 500,
3009702785aSThomas Gleixner 
3019702785aSThomas Gleixner 	.set_mode = xen_timerop_set_mode,
3029702785aSThomas Gleixner 	.set_next_event = xen_timerop_set_next_event,
3039702785aSThomas Gleixner };
3049702785aSThomas Gleixner 
3059702785aSThomas Gleixner 
3069702785aSThomas Gleixner 
3079702785aSThomas Gleixner static void xen_vcpuop_set_mode(enum clock_event_mode mode,
3089702785aSThomas Gleixner 				struct clock_event_device *evt)
3099702785aSThomas Gleixner {
3109702785aSThomas Gleixner 	int cpu = smp_processor_id();
3119702785aSThomas Gleixner 
3129702785aSThomas Gleixner 	switch (mode) {
3139702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
3149702785aSThomas Gleixner 		WARN_ON(1);	/* unsupported */
3159702785aSThomas Gleixner 		break;
3169702785aSThomas Gleixner 
3179702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
3189702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3199702785aSThomas Gleixner 			BUG();
3209702785aSThomas Gleixner 		break;
3219702785aSThomas Gleixner 
3229702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
3239702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
3249702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, cpu, NULL) ||
3259702785aSThomas Gleixner 		    HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3269702785aSThomas Gleixner 			BUG();
3279702785aSThomas Gleixner 		break;
3289702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
3299702785aSThomas Gleixner 		break;
3309702785aSThomas Gleixner 	}
3319702785aSThomas Gleixner }
3329702785aSThomas Gleixner 
3339702785aSThomas Gleixner static int xen_vcpuop_set_next_event(unsigned long delta,
3349702785aSThomas Gleixner 				     struct clock_event_device *evt)
3359702785aSThomas Gleixner {
3369702785aSThomas Gleixner 	int cpu = smp_processor_id();
3379702785aSThomas Gleixner 	struct vcpu_set_singleshot_timer single;
3389702785aSThomas Gleixner 	int ret;
3399702785aSThomas Gleixner 
3409702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
3419702785aSThomas Gleixner 
3429702785aSThomas Gleixner 	single.timeout_abs_ns = get_abs_timeout(delta);
3439702785aSThomas Gleixner 	single.flags = VCPU_SSHOTTMR_future;
3449702785aSThomas Gleixner 
3459702785aSThomas Gleixner 	ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
3469702785aSThomas Gleixner 
3479702785aSThomas Gleixner 	BUG_ON(ret != 0 && ret != -ETIME);
3489702785aSThomas Gleixner 
3499702785aSThomas Gleixner 	return ret;
3509702785aSThomas Gleixner }
3519702785aSThomas Gleixner 
3529702785aSThomas Gleixner static const struct clock_event_device xen_vcpuop_clockevent = {
3539702785aSThomas Gleixner 	.name = "xen",
3549702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
3559702785aSThomas Gleixner 
3569702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
3579702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
3589702785aSThomas Gleixner 
3599702785aSThomas Gleixner 	.mult = 1,
3609702785aSThomas Gleixner 	.shift = 0,
3619702785aSThomas Gleixner 	.rating = 500,
3629702785aSThomas Gleixner 
3639702785aSThomas Gleixner 	.set_mode = xen_vcpuop_set_mode,
3649702785aSThomas Gleixner 	.set_next_event = xen_vcpuop_set_next_event,
3659702785aSThomas Gleixner };
3669702785aSThomas Gleixner 
3679702785aSThomas Gleixner static const struct clock_event_device *xen_clockevent =
3689702785aSThomas Gleixner 	&xen_timerop_clockevent;
3699702785aSThomas Gleixner static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events);
3709702785aSThomas Gleixner 
3719702785aSThomas Gleixner static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
3729702785aSThomas Gleixner {
3739702785aSThomas Gleixner 	struct clock_event_device *evt = &__get_cpu_var(xen_clock_events);
3749702785aSThomas Gleixner 	irqreturn_t ret;
3759702785aSThomas Gleixner 
3769702785aSThomas Gleixner 	ret = IRQ_NONE;
3779702785aSThomas Gleixner 	if (evt->event_handler) {
3789702785aSThomas Gleixner 		evt->event_handler(evt);
3799702785aSThomas Gleixner 		ret = IRQ_HANDLED;
3809702785aSThomas Gleixner 	}
3819702785aSThomas Gleixner 
3829702785aSThomas Gleixner 	do_stolen_accounting();
3839702785aSThomas Gleixner 
3849702785aSThomas Gleixner 	return ret;
3859702785aSThomas Gleixner }
3869702785aSThomas Gleixner 
3879702785aSThomas Gleixner void xen_setup_timer(int cpu)
3889702785aSThomas Gleixner {
3899702785aSThomas Gleixner 	const char *name;
3909702785aSThomas Gleixner 	struct clock_event_device *evt;
3919702785aSThomas Gleixner 	int irq;
3929702785aSThomas Gleixner 
3939702785aSThomas Gleixner 	printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
3949702785aSThomas Gleixner 
3959702785aSThomas Gleixner 	name = kasprintf(GFP_KERNEL, "timer%d", cpu);
3969702785aSThomas Gleixner 	if (!name)
3979702785aSThomas Gleixner 		name = "<timer kasprintf failed>";
3989702785aSThomas Gleixner 
3999702785aSThomas Gleixner 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
400f611f2daSIan Campbell 				      IRQF_DISABLED|IRQF_PERCPU|
401f611f2daSIan Campbell 				      IRQF_NOBALANCING|IRQF_TIMER|
402f611f2daSIan Campbell 				      IRQF_FORCE_RESUME,
4039702785aSThomas Gleixner 				      name, NULL);
4049702785aSThomas Gleixner 
4059702785aSThomas Gleixner 	evt = &per_cpu(xen_clock_events, cpu);
4069702785aSThomas Gleixner 	memcpy(evt, xen_clockevent, sizeof(*evt));
4079702785aSThomas Gleixner 
408320ab2b0SRusty Russell 	evt->cpumask = cpumask_of(cpu);
4099702785aSThomas Gleixner 	evt->irq = irq;
4109702785aSThomas Gleixner }
4119702785aSThomas Gleixner 
412d68d82afSAlex Nixon void xen_teardown_timer(int cpu)
413d68d82afSAlex Nixon {
414d68d82afSAlex Nixon 	struct clock_event_device *evt;
415d68d82afSAlex Nixon 	BUG_ON(cpu == 0);
416d68d82afSAlex Nixon 	evt = &per_cpu(xen_clock_events, cpu);
417d68d82afSAlex Nixon 	unbind_from_irqhandler(evt->irq, NULL);
418d68d82afSAlex Nixon }
419d68d82afSAlex Nixon 
4209702785aSThomas Gleixner void xen_setup_cpu_clockevents(void)
4219702785aSThomas Gleixner {
4229702785aSThomas Gleixner 	BUG_ON(preemptible());
4239702785aSThomas Gleixner 
4249702785aSThomas Gleixner 	clockevents_register_device(&__get_cpu_var(xen_clock_events));
4259702785aSThomas Gleixner }
4269702785aSThomas Gleixner 
427d07af1f0SJeremy Fitzhardinge void xen_timer_resume(void)
428d07af1f0SJeremy Fitzhardinge {
429d07af1f0SJeremy Fitzhardinge 	int cpu;
430d07af1f0SJeremy Fitzhardinge 
431e7a3481cSJeremy Fitzhardinge 	pvclock_resume();
432e7a3481cSJeremy Fitzhardinge 
433d07af1f0SJeremy Fitzhardinge 	if (xen_clockevent != &xen_vcpuop_clockevent)
434d07af1f0SJeremy Fitzhardinge 		return;
435d07af1f0SJeremy Fitzhardinge 
436d07af1f0SJeremy Fitzhardinge 	for_each_online_cpu(cpu) {
437d07af1f0SJeremy Fitzhardinge 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
438d07af1f0SJeremy Fitzhardinge 			BUG();
439d07af1f0SJeremy Fitzhardinge 	}
440d07af1f0SJeremy Fitzhardinge }
441d07af1f0SJeremy Fitzhardinge 
442*fb6ce5deSDaniel Kiper static const struct pv_time_ops xen_time_ops __initconst = {
443ca50a5f3SJeremy Fitzhardinge 	.sched_clock = xen_clocksource_read,
444409771d2SStefano Stabellini };
445409771d2SStefano Stabellini 
446*fb6ce5deSDaniel Kiper static void __init xen_time_init(void)
4479702785aSThomas Gleixner {
4489702785aSThomas Gleixner 	int cpu = smp_processor_id();
449c4507257SJohn Stultz 	struct timespec tp;
4509702785aSThomas Gleixner 
4519702785aSThomas Gleixner 	clocksource_register(&xen_clocksource);
4529702785aSThomas Gleixner 
4539702785aSThomas Gleixner 	if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) {
4549702785aSThomas Gleixner 		/* Successfully turned off 100Hz tick, so we have the
4559702785aSThomas Gleixner 		   vcpuop-based timer interface */
4569702785aSThomas Gleixner 		printk(KERN_DEBUG "Xen: using vcpuop timer interface\n");
4579702785aSThomas Gleixner 		xen_clockevent = &xen_vcpuop_clockevent;
4589702785aSThomas Gleixner 	}
4599702785aSThomas Gleixner 
4609702785aSThomas Gleixner 	/* Set initial system time with full resolution */
461c4507257SJohn Stultz 	xen_read_wallclock(&tp);
462c4507257SJohn Stultz 	do_settimeofday(&tp);
4639702785aSThomas Gleixner 
464404ee5b1SAndi Kleen 	setup_force_cpu_cap(X86_FEATURE_TSC);
4659702785aSThomas Gleixner 
466be012920SIan Campbell 	xen_setup_runstate_info(cpu);
4679702785aSThomas Gleixner 	xen_setup_timer(cpu);
4689702785aSThomas Gleixner 	xen_setup_cpu_clockevents();
4699702785aSThomas Gleixner }
470409771d2SStefano Stabellini 
471*fb6ce5deSDaniel Kiper void __init xen_init_time_ops(void)
472409771d2SStefano Stabellini {
473409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
474409771d2SStefano Stabellini 
475409771d2SStefano Stabellini 	x86_init.timers.timer_init = xen_time_init;
476409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = x86_init_noop;
477409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
478409771d2SStefano Stabellini 
479409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
480409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
481409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
482409771d2SStefano Stabellini }
483409771d2SStefano Stabellini 
484ca65f9fcSStefano Stabellini #ifdef CONFIG_XEN_PVHVM
485409771d2SStefano Stabellini static void xen_hvm_setup_cpu_clockevents(void)
486409771d2SStefano Stabellini {
487409771d2SStefano Stabellini 	int cpu = smp_processor_id();
488409771d2SStefano Stabellini 	xen_setup_runstate_info(cpu);
489409771d2SStefano Stabellini 	xen_setup_timer(cpu);
490409771d2SStefano Stabellini 	xen_setup_cpu_clockevents();
491409771d2SStefano Stabellini }
492409771d2SStefano Stabellini 
493*fb6ce5deSDaniel Kiper void __init xen_hvm_init_time_ops(void)
494409771d2SStefano Stabellini {
495409771d2SStefano Stabellini 	/* vector callback is needed otherwise we cannot receive interrupts
49631e7e931SStefano Stabellini 	 * on cpu > 0 and at this point we don't know how many cpus are
49731e7e931SStefano Stabellini 	 * available */
49831e7e931SStefano Stabellini 	if (!xen_have_vector_callback)
499409771d2SStefano Stabellini 		return;
500409771d2SStefano Stabellini 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
501409771d2SStefano Stabellini 		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
502409771d2SStefano Stabellini 				"disable pv timer\n");
503409771d2SStefano Stabellini 		return;
504409771d2SStefano Stabellini 	}
505409771d2SStefano Stabellini 
506409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
507409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = xen_time_init;
508409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
509409771d2SStefano Stabellini 
510409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
511409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
512409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
513409771d2SStefano Stabellini }
514ca65f9fcSStefano Stabellini #endif
515