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