xref: /linux/arch/x86/xen/time.c (revision 3565184ed0c1ea46bea5b792da5f72a83c43e49b)
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 
171f1c39625SJeremy Fitzhardinge 	preempt_disable_notrace();
172f1c39625SJeremy Fitzhardinge 	src = &__get_cpu_var(xen_vcpu)->time;
1731c7b67f7SGerd Hoffmann 	ret = pvclock_clocksource_read(src);
174f1c39625SJeremy Fitzhardinge 	preempt_enable_notrace();
1759702785aSThomas Gleixner 	return ret;
1769702785aSThomas Gleixner }
1779702785aSThomas Gleixner 
1788e19608eSMagnus Damm static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
1798e19608eSMagnus Damm {
1808e19608eSMagnus Damm 	return xen_clocksource_read();
1818e19608eSMagnus Damm }
1828e19608eSMagnus Damm 
1839702785aSThomas Gleixner static void xen_read_wallclock(struct timespec *ts)
1849702785aSThomas Gleixner {
1851c7b67f7SGerd Hoffmann 	struct shared_info *s = HYPERVISOR_shared_info;
1861c7b67f7SGerd Hoffmann 	struct pvclock_wall_clock *wall_clock = &(s->wc);
1871c7b67f7SGerd Hoffmann         struct pvclock_vcpu_time_info *vcpu_time;
1889702785aSThomas Gleixner 
1891c7b67f7SGerd Hoffmann 	vcpu_time = &get_cpu_var(xen_vcpu)->time;
1901c7b67f7SGerd Hoffmann 	pvclock_read_wallclock(wall_clock, vcpu_time, ts);
1911c7b67f7SGerd Hoffmann 	put_cpu_var(xen_vcpu);
1929702785aSThomas Gleixner }
1939702785aSThomas Gleixner 
194*3565184eSDavid Vrabel static void xen_get_wallclock(struct timespec *now)
1959702785aSThomas Gleixner {
196*3565184eSDavid Vrabel 	xen_read_wallclock(now);
1979702785aSThomas Gleixner }
1989702785aSThomas Gleixner 
199*3565184eSDavid Vrabel static int xen_set_wallclock(const struct timespec *now)
2009702785aSThomas Gleixner {
201fdb9eb9fSJeremy Fitzhardinge 	struct xen_platform_op op;
202fdb9eb9fSJeremy Fitzhardinge 
2039702785aSThomas Gleixner 	/* do nothing for domU */
204fdb9eb9fSJeremy Fitzhardinge 	if (!xen_initial_domain())
2059702785aSThomas Gleixner 		return -1;
206fdb9eb9fSJeremy Fitzhardinge 
207fdb9eb9fSJeremy Fitzhardinge 	op.cmd = XENPF_settime;
208*3565184eSDavid Vrabel 	op.u.settime.secs = now->tv_sec;
209*3565184eSDavid Vrabel 	op.u.settime.nsecs = now->tv_nsec;
210fdb9eb9fSJeremy Fitzhardinge 	op.u.settime.system_time = xen_clocksource_read();
211fdb9eb9fSJeremy Fitzhardinge 
212*3565184eSDavid Vrabel 	return HYPERVISOR_dom0_op(&op);
2139702785aSThomas Gleixner }
2149702785aSThomas Gleixner 
2159702785aSThomas Gleixner static struct clocksource xen_clocksource __read_mostly = {
2169702785aSThomas Gleixner 	.name = "xen",
2179702785aSThomas Gleixner 	.rating = 400,
2188e19608eSMagnus Damm 	.read = xen_clocksource_get_cycles,
2199702785aSThomas Gleixner 	.mask = ~0,
2209702785aSThomas Gleixner 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
2219702785aSThomas Gleixner };
2229702785aSThomas Gleixner 
2239702785aSThomas Gleixner /*
2249702785aSThomas Gleixner    Xen clockevent implementation
2259702785aSThomas Gleixner 
2269702785aSThomas Gleixner    Xen has two clockevent implementations:
2279702785aSThomas Gleixner 
2289702785aSThomas Gleixner    The old timer_op one works with all released versions of Xen prior
2299702785aSThomas Gleixner    to version 3.0.4.  This version of the hypervisor provides a
2309702785aSThomas Gleixner    single-shot timer with nanosecond resolution.  However, sharing the
2319702785aSThomas Gleixner    same event channel is a 100Hz tick which is delivered while the
2329702785aSThomas Gleixner    vcpu is running.  We don't care about or use this tick, but it will
2339702785aSThomas Gleixner    cause the core time code to think the timer fired too soon, and
2349702785aSThomas Gleixner    will end up resetting it each time.  It could be filtered, but
2359702785aSThomas Gleixner    doing so has complications when the ktime clocksource is not yet
2369702785aSThomas Gleixner    the xen clocksource (ie, at boot time).
2379702785aSThomas Gleixner 
2389702785aSThomas Gleixner    The new vcpu_op-based timer interface allows the tick timer period
2399702785aSThomas Gleixner    to be changed or turned off.  The tick timer is not useful as a
2409702785aSThomas Gleixner    periodic timer because events are only delivered to running vcpus.
2419702785aSThomas Gleixner    The one-shot timer can report when a timeout is in the past, so
2429702785aSThomas Gleixner    set_next_event is capable of returning -ETIME when appropriate.
2439702785aSThomas Gleixner    This interface is used when available.
2449702785aSThomas Gleixner */
2459702785aSThomas Gleixner 
2469702785aSThomas Gleixner 
2479702785aSThomas Gleixner /*
2489702785aSThomas Gleixner   Get a hypervisor absolute time.  In theory we could maintain an
2499702785aSThomas Gleixner   offset between the kernel's time and the hypervisor's time, and
2509702785aSThomas Gleixner   apply that to a kernel's absolute timeout.  Unfortunately the
2519702785aSThomas Gleixner   hypervisor and kernel times can drift even if the kernel is using
2529702785aSThomas Gleixner   the Xen clocksource, because ntp can warp the kernel's clocksource.
2539702785aSThomas Gleixner */
2549702785aSThomas Gleixner static s64 get_abs_timeout(unsigned long delta)
2559702785aSThomas Gleixner {
2569702785aSThomas Gleixner 	return xen_clocksource_read() + delta;
2579702785aSThomas Gleixner }
2589702785aSThomas Gleixner 
2599702785aSThomas Gleixner static void xen_timerop_set_mode(enum clock_event_mode mode,
2609702785aSThomas Gleixner 				 struct clock_event_device *evt)
2619702785aSThomas Gleixner {
2629702785aSThomas Gleixner 	switch (mode) {
2639702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
2649702785aSThomas Gleixner 		/* unsupported */
2659702785aSThomas Gleixner 		WARN_ON(1);
2669702785aSThomas Gleixner 		break;
2679702785aSThomas Gleixner 
2689702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
2699702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
2709702785aSThomas Gleixner 		break;
2719702785aSThomas Gleixner 
2729702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
2739702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
2749702785aSThomas Gleixner 		HYPERVISOR_set_timer_op(0);  /* cancel timeout */
2759702785aSThomas Gleixner 		break;
2769702785aSThomas Gleixner 	}
2779702785aSThomas Gleixner }
2789702785aSThomas Gleixner 
2799702785aSThomas Gleixner static int xen_timerop_set_next_event(unsigned long delta,
2809702785aSThomas Gleixner 				      struct clock_event_device *evt)
2819702785aSThomas Gleixner {
2829702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
2839702785aSThomas Gleixner 
2849702785aSThomas Gleixner 	if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0)
2859702785aSThomas Gleixner 		BUG();
2869702785aSThomas Gleixner 
2879702785aSThomas Gleixner 	/* We may have missed the deadline, but there's no real way of
2889702785aSThomas Gleixner 	   knowing for sure.  If the event was in the past, then we'll
2899702785aSThomas Gleixner 	   get an immediate interrupt. */
2909702785aSThomas Gleixner 
2919702785aSThomas Gleixner 	return 0;
2929702785aSThomas Gleixner }
2939702785aSThomas Gleixner 
2949702785aSThomas Gleixner static const struct clock_event_device xen_timerop_clockevent = {
2959702785aSThomas Gleixner 	.name = "xen",
2969702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
2979702785aSThomas Gleixner 
2989702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
2999702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
3009702785aSThomas Gleixner 
3019702785aSThomas Gleixner 	.mult = 1,
3029702785aSThomas Gleixner 	.shift = 0,
3039702785aSThomas Gleixner 	.rating = 500,
3049702785aSThomas Gleixner 
3059702785aSThomas Gleixner 	.set_mode = xen_timerop_set_mode,
3069702785aSThomas Gleixner 	.set_next_event = xen_timerop_set_next_event,
3079702785aSThomas Gleixner };
3089702785aSThomas Gleixner 
3099702785aSThomas Gleixner 
3109702785aSThomas Gleixner 
3119702785aSThomas Gleixner static void xen_vcpuop_set_mode(enum clock_event_mode mode,
3129702785aSThomas Gleixner 				struct clock_event_device *evt)
3139702785aSThomas Gleixner {
3149702785aSThomas Gleixner 	int cpu = smp_processor_id();
3159702785aSThomas Gleixner 
3169702785aSThomas Gleixner 	switch (mode) {
3179702785aSThomas Gleixner 	case CLOCK_EVT_MODE_PERIODIC:
3189702785aSThomas Gleixner 		WARN_ON(1);	/* unsupported */
3199702785aSThomas Gleixner 		break;
3209702785aSThomas Gleixner 
3219702785aSThomas Gleixner 	case CLOCK_EVT_MODE_ONESHOT:
3229702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3239702785aSThomas Gleixner 			BUG();
3249702785aSThomas Gleixner 		break;
3259702785aSThomas Gleixner 
3269702785aSThomas Gleixner 	case CLOCK_EVT_MODE_UNUSED:
3279702785aSThomas Gleixner 	case CLOCK_EVT_MODE_SHUTDOWN:
3289702785aSThomas Gleixner 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, cpu, NULL) ||
3299702785aSThomas Gleixner 		    HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
3309702785aSThomas Gleixner 			BUG();
3319702785aSThomas Gleixner 		break;
3329702785aSThomas Gleixner 	case CLOCK_EVT_MODE_RESUME:
3339702785aSThomas Gleixner 		break;
3349702785aSThomas Gleixner 	}
3359702785aSThomas Gleixner }
3369702785aSThomas Gleixner 
3379702785aSThomas Gleixner static int xen_vcpuop_set_next_event(unsigned long delta,
3389702785aSThomas Gleixner 				     struct clock_event_device *evt)
3399702785aSThomas Gleixner {
3409702785aSThomas Gleixner 	int cpu = smp_processor_id();
3419702785aSThomas Gleixner 	struct vcpu_set_singleshot_timer single;
3429702785aSThomas Gleixner 	int ret;
3439702785aSThomas Gleixner 
3449702785aSThomas Gleixner 	WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
3459702785aSThomas Gleixner 
3469702785aSThomas Gleixner 	single.timeout_abs_ns = get_abs_timeout(delta);
3479702785aSThomas Gleixner 	single.flags = VCPU_SSHOTTMR_future;
3489702785aSThomas Gleixner 
3499702785aSThomas Gleixner 	ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
3509702785aSThomas Gleixner 
3519702785aSThomas Gleixner 	BUG_ON(ret != 0 && ret != -ETIME);
3529702785aSThomas Gleixner 
3539702785aSThomas Gleixner 	return ret;
3549702785aSThomas Gleixner }
3559702785aSThomas Gleixner 
3569702785aSThomas Gleixner static const struct clock_event_device xen_vcpuop_clockevent = {
3579702785aSThomas Gleixner 	.name = "xen",
3589702785aSThomas Gleixner 	.features = CLOCK_EVT_FEAT_ONESHOT,
3599702785aSThomas Gleixner 
3609702785aSThomas Gleixner 	.max_delta_ns = 0xffffffff,
3619702785aSThomas Gleixner 	.min_delta_ns = TIMER_SLOP,
3629702785aSThomas Gleixner 
3639702785aSThomas Gleixner 	.mult = 1,
3649702785aSThomas Gleixner 	.shift = 0,
3659702785aSThomas Gleixner 	.rating = 500,
3669702785aSThomas Gleixner 
3679702785aSThomas Gleixner 	.set_mode = xen_vcpuop_set_mode,
3689702785aSThomas Gleixner 	.set_next_event = xen_vcpuop_set_next_event,
3699702785aSThomas Gleixner };
3709702785aSThomas Gleixner 
3719702785aSThomas Gleixner static const struct clock_event_device *xen_clockevent =
3729702785aSThomas Gleixner 	&xen_timerop_clockevent;
373ef35a4e6SKonrad Rzeszutek Wilk static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events) = { .irq = -1 };
3749702785aSThomas Gleixner 
3759702785aSThomas Gleixner static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
3769702785aSThomas Gleixner {
3779702785aSThomas Gleixner 	struct clock_event_device *evt = &__get_cpu_var(xen_clock_events);
3789702785aSThomas Gleixner 	irqreturn_t ret;
3799702785aSThomas Gleixner 
3809702785aSThomas Gleixner 	ret = IRQ_NONE;
3819702785aSThomas Gleixner 	if (evt->event_handler) {
3829702785aSThomas Gleixner 		evt->event_handler(evt);
3839702785aSThomas Gleixner 		ret = IRQ_HANDLED;
3849702785aSThomas Gleixner 	}
3859702785aSThomas Gleixner 
3869702785aSThomas Gleixner 	do_stolen_accounting();
3879702785aSThomas Gleixner 
3889702785aSThomas Gleixner 	return ret;
3899702785aSThomas Gleixner }
3909702785aSThomas Gleixner 
3919702785aSThomas Gleixner void xen_setup_timer(int cpu)
3929702785aSThomas Gleixner {
3939702785aSThomas Gleixner 	const char *name;
3949702785aSThomas Gleixner 	struct clock_event_device *evt;
3959702785aSThomas Gleixner 	int irq;
3969702785aSThomas Gleixner 
397ef35a4e6SKonrad Rzeszutek Wilk 	evt = &per_cpu(xen_clock_events, cpu);
398ef35a4e6SKonrad Rzeszutek Wilk 	WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu);
399ef35a4e6SKonrad Rzeszutek Wilk 
4009702785aSThomas Gleixner 	printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
4019702785aSThomas Gleixner 
4029702785aSThomas Gleixner 	name = kasprintf(GFP_KERNEL, "timer%d", cpu);
4039702785aSThomas Gleixner 	if (!name)
4049702785aSThomas Gleixner 		name = "<timer kasprintf failed>";
4059702785aSThomas Gleixner 
4069702785aSThomas Gleixner 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
407f611f2daSIan Campbell 				      IRQF_DISABLED|IRQF_PERCPU|
408f611f2daSIan Campbell 				      IRQF_NOBALANCING|IRQF_TIMER|
409f611f2daSIan Campbell 				      IRQF_FORCE_RESUME,
4109702785aSThomas Gleixner 				      name, NULL);
4119702785aSThomas Gleixner 
4129702785aSThomas Gleixner 	memcpy(evt, xen_clockevent, sizeof(*evt));
4139702785aSThomas Gleixner 
414320ab2b0SRusty Russell 	evt->cpumask = cpumask_of(cpu);
4159702785aSThomas Gleixner 	evt->irq = irq;
4169702785aSThomas Gleixner }
4179702785aSThomas Gleixner 
418d68d82afSAlex Nixon void xen_teardown_timer(int cpu)
419d68d82afSAlex Nixon {
420d68d82afSAlex Nixon 	struct clock_event_device *evt;
421d68d82afSAlex Nixon 	BUG_ON(cpu == 0);
422d68d82afSAlex Nixon 	evt = &per_cpu(xen_clock_events, cpu);
423d68d82afSAlex Nixon 	unbind_from_irqhandler(evt->irq, NULL);
424ef35a4e6SKonrad Rzeszutek Wilk 	evt->irq = -1;
425d68d82afSAlex Nixon }
426d68d82afSAlex Nixon 
4279702785aSThomas Gleixner void xen_setup_cpu_clockevents(void)
4289702785aSThomas Gleixner {
4299702785aSThomas Gleixner 	BUG_ON(preemptible());
4309702785aSThomas Gleixner 
4319702785aSThomas Gleixner 	clockevents_register_device(&__get_cpu_var(xen_clock_events));
4329702785aSThomas Gleixner }
4339702785aSThomas Gleixner 
434d07af1f0SJeremy Fitzhardinge void xen_timer_resume(void)
435d07af1f0SJeremy Fitzhardinge {
436d07af1f0SJeremy Fitzhardinge 	int cpu;
437d07af1f0SJeremy Fitzhardinge 
438e7a3481cSJeremy Fitzhardinge 	pvclock_resume();
439e7a3481cSJeremy Fitzhardinge 
440d07af1f0SJeremy Fitzhardinge 	if (xen_clockevent != &xen_vcpuop_clockevent)
441d07af1f0SJeremy Fitzhardinge 		return;
442d07af1f0SJeremy Fitzhardinge 
443d07af1f0SJeremy Fitzhardinge 	for_each_online_cpu(cpu) {
444d07af1f0SJeremy Fitzhardinge 		if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
445d07af1f0SJeremy Fitzhardinge 			BUG();
446d07af1f0SJeremy Fitzhardinge 	}
447d07af1f0SJeremy Fitzhardinge }
448d07af1f0SJeremy Fitzhardinge 
449fb6ce5deSDaniel Kiper static const struct pv_time_ops xen_time_ops __initconst = {
450ca50a5f3SJeremy Fitzhardinge 	.sched_clock = xen_clocksource_read,
451409771d2SStefano Stabellini };
452409771d2SStefano Stabellini 
453fb6ce5deSDaniel Kiper static void __init xen_time_init(void)
4549702785aSThomas Gleixner {
4559702785aSThomas Gleixner 	int cpu = smp_processor_id();
456c4507257SJohn Stultz 	struct timespec tp;
4579702785aSThomas Gleixner 
458b01cc1b0SJohn Stultz 	clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
4599702785aSThomas Gleixner 
4609702785aSThomas Gleixner 	if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) {
4619702785aSThomas Gleixner 		/* Successfully turned off 100Hz tick, so we have the
4629702785aSThomas Gleixner 		   vcpuop-based timer interface */
4639702785aSThomas Gleixner 		printk(KERN_DEBUG "Xen: using vcpuop timer interface\n");
4649702785aSThomas Gleixner 		xen_clockevent = &xen_vcpuop_clockevent;
4659702785aSThomas Gleixner 	}
4669702785aSThomas Gleixner 
4679702785aSThomas Gleixner 	/* Set initial system time with full resolution */
468c4507257SJohn Stultz 	xen_read_wallclock(&tp);
469c4507257SJohn Stultz 	do_settimeofday(&tp);
4709702785aSThomas Gleixner 
471404ee5b1SAndi Kleen 	setup_force_cpu_cap(X86_FEATURE_TSC);
4729702785aSThomas Gleixner 
473be012920SIan Campbell 	xen_setup_runstate_info(cpu);
4749702785aSThomas Gleixner 	xen_setup_timer(cpu);
4759702785aSThomas Gleixner 	xen_setup_cpu_clockevents();
4769702785aSThomas Gleixner }
477409771d2SStefano Stabellini 
478fb6ce5deSDaniel Kiper void __init xen_init_time_ops(void)
479409771d2SStefano Stabellini {
480409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
481409771d2SStefano Stabellini 
482409771d2SStefano Stabellini 	x86_init.timers.timer_init = xen_time_init;
483409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = x86_init_noop;
484409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
485409771d2SStefano Stabellini 
486409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
487409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
488409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
489409771d2SStefano Stabellini }
490409771d2SStefano Stabellini 
491ca65f9fcSStefano Stabellini #ifdef CONFIG_XEN_PVHVM
492409771d2SStefano Stabellini static void xen_hvm_setup_cpu_clockevents(void)
493409771d2SStefano Stabellini {
494409771d2SStefano Stabellini 	int cpu = smp_processor_id();
495409771d2SStefano Stabellini 	xen_setup_runstate_info(cpu);
4967918c92aSKonrad Rzeszutek Wilk 	/*
4977918c92aSKonrad Rzeszutek Wilk 	 * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence
4987918c92aSKonrad Rzeszutek Wilk 	 * doing it xen_hvm_cpu_notify (which gets called by smp_init during
4997918c92aSKonrad Rzeszutek Wilk 	 * early bootup and also during CPU hotplug events).
5007918c92aSKonrad Rzeszutek Wilk 	 */
501409771d2SStefano Stabellini 	xen_setup_cpu_clockevents();
502409771d2SStefano Stabellini }
503409771d2SStefano Stabellini 
504fb6ce5deSDaniel Kiper void __init xen_hvm_init_time_ops(void)
505409771d2SStefano Stabellini {
506409771d2SStefano Stabellini 	/* vector callback is needed otherwise we cannot receive interrupts
50731e7e931SStefano Stabellini 	 * on cpu > 0 and at this point we don't know how many cpus are
50831e7e931SStefano Stabellini 	 * available */
50931e7e931SStefano Stabellini 	if (!xen_have_vector_callback)
510409771d2SStefano Stabellini 		return;
511409771d2SStefano Stabellini 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
512409771d2SStefano Stabellini 		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
513409771d2SStefano Stabellini 				"disable pv timer\n");
514409771d2SStefano Stabellini 		return;
515409771d2SStefano Stabellini 	}
516409771d2SStefano Stabellini 
517409771d2SStefano Stabellini 	pv_time_ops = xen_time_ops;
518409771d2SStefano Stabellini 	x86_init.timers.setup_percpu_clockev = xen_time_init;
519409771d2SStefano Stabellini 	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
520409771d2SStefano Stabellini 
521409771d2SStefano Stabellini 	x86_platform.calibrate_tsc = xen_tsc_khz;
522409771d2SStefano Stabellini 	x86_platform.get_wallclock = xen_get_wallclock;
523409771d2SStefano Stabellini 	x86_platform.set_wallclock = xen_set_wallclock;
524409771d2SStefano Stabellini }
525ca65f9fcSStefano Stabellini #endif
526