static int xen_timerop_shutdown(struct clock_event_device *evt) { /* cancel timeout */ HYPERVISOR_set_timer_op(0); return 0; }
/* * This function will reprogram the timer. * * When in oneshot mode the argument is the absolute time in future at which to * generate the interrupt. * * When in periodic mode, the argument is the interval at which the * interrupts should be generated. There is no need to support the periodic * mode timer change at this time. * * Note that we must be careful to convert from hrtime to Xen system time (see * xpv_timestamp.c). */ static void xen_uppc_timer_reprogram(hrtime_t timer_req) { hrtime_t now, timer_new, time_delta, xen_time; ulong_t flags; flags = intr_clear(); /* * We should be called from high PIL context (CBE_HIGH_PIL), * so kpreempt is disabled. */ now = xpv_gethrtime(); xen_time = xpv_getsystime(); if (timer_req <= now) { /* * requested to generate an interrupt in the past * generate an interrupt as soon as possible */ time_delta = XEN_NSEC_PER_TICK; } else time_delta = timer_req - now; timer_new = xen_time + time_delta; if (HYPERVISOR_set_timer_op(timer_new) != 0) panic("can't set hypervisor timer?"); intr_restore(flags); }
void block_domain(u32 millisecs) { struct timeval tv; gettimeofday(&tv); HYPERVISOR_set_timer_op(monotonic_clock() + 1000000LL * (s64) millisecs); HYPERVISOR_sched_op(SCHEDOP_block, 0); }
static int xen_timerop_set_next_event(unsigned long delta, struct clock_event_device *evt) { WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT); if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0) BUG(); return 0; }
static int xen_timerop_set_next_event(unsigned long delta, struct clock_event_device *evt) { WARN_ON(!clockevent_state_oneshot(evt)); if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0) BUG(); /* We may have missed the deadline, but there's no real way of knowing for sure. If the event was in the past, then we'll get an immediate interrupt. */ return 0; }
CAMLprim value caml_block_domain(value v_timeout) { CAMLparam1(v_timeout); s_time_t block_nsecs = (s_time_t)(Double_val(v_timeout) * 1000000000); HYPERVISOR_set_timer_op(NOW() + block_nsecs); /* xen/common/schedule.c:do_block clears evtchn_upcall_mask to re-enable interrupts. It blocks the domain and immediately checks for pending events which otherwise may be missed. */ HYPERVISOR_sched_op(SCHEDOP_block, 0); /* set evtchn_upcall_mask: there's no need to be interrupted when we know we have outstanding work to do. When we next call this function, the call to SCHEDOP_block will check for pending events. */ local_irq_disable(); CAMLreturn(Val_unit); }
static void xen_timerop_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: /* unsupported */ WARN_ON(1); break; case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_RESUME: break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: HYPERVISOR_set_timer_op(0); /* cancel timeout */ break; } }