diff options
author | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
---|---|---|
committer | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
commit | 5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch) | |
tree | c1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/xentimer.c | |
parent | fa03455b5057675b18d1c87aef2d1071b2088de0 (diff) |
import xen 32 bit paravirtual kernel from /n/sources/xen.
Diffstat (limited to 'sys/src/9/xen/xentimer.c')
-rw-r--r-- | sys/src/9/xen/xentimer.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/sys/src/9/xen/xentimer.c b/sys/src/9/xen/xentimer.c new file mode 100644 index 000000000..2a57cc5b9 --- /dev/null +++ b/sys/src/9/xen/xentimer.c @@ -0,0 +1,136 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static vcpu_time_info_t shadow[MAX_VIRT_CPUS]; // XXX should be in Mach +static ulong wallclock; +static ulong wallclocksystime; + +/* + * Return a consistent set of time parameters. + */ +static vcpu_time_info_t * +getshadow(void) +{ + vcpu_time_info_t *s, *t; + + t = &HYPERVISOR_shared_info->vcpu_info[m->machno].time; + s = &shadow[m->machno]; // XXX place in mach struct + while(t->version != s->version) { + if (t->version&1) + continue; + s->version = t->version; + s->tsc_timestamp = t->tsc_timestamp; + s->system_time = t->system_time; + s->tsc_to_system_mul = t->tsc_to_system_mul; + s->tsc_shift = t->tsc_shift; + } + return s; +} + + +/* just get it from the shared info */ +void +guesscpuhz(int) // XXX no arg! +{ + vcpu_time_info_t *t; + + t = getshadow(); + m->cpuhz = (1000000000LL << 32) / t->tsc_to_system_mul; + if(t->tsc_shift < 0) + m->cpuhz <<= -t->tsc_shift; + else + m->cpuhz >>= t->tsc_shift; + m->cpumhz = m->cpuhz / 1000000L; +} + +void +xentimerset(uvlong next) +{ + uvlong soon; + + soon = fastticks(0) + 100000; + if (next < soon) + next = soon; + HYPERVISOR_set_timer_op(next); +} + +void +xentimerclock(Ureg* ureg, void*) +{ + + timerintr(ureg, 0); +} + +void +xentimerenable(void) +{ + intrenable(VIRQ_TIMER, xentimerclock, nil, 0, "Xen Timer"); +} + +uvlong +xentimerread(uvlong *hz) +{ + uvlong x; + uvlong delta, sdelta; + vcpu_time_info_t *t; + + t = getshadow(); + cycles(&x); + delta = x - t->tsc_timestamp; + if (t->tsc_shift < 0) + delta >>= -t->tsc_shift; + else + delta <<= t->tsc_shift; + mul64fract(&sdelta, delta, t->tsc_to_system_mul); + x = t->system_time + sdelta; + if (HYPERVISOR_shared_info->wc_sec != wallclock) { + wallclock = HYPERVISOR_shared_info->wc_sec; + wallclocksystime = x; + } + if (hz) + *hz = 1000000000; + return x; +} + +ulong +xenwallclock() +{ + ulong elapsed; + + elapsed = (ulong)((xentimerread(0) - wallclocksystime)/1000000000); + return wallclock + elapsed; +} + +void +microdelay(int microsecs) +{ + uvlong targ, hz; + + targ = xentimerread(&hz); + targ += microsecs * hz / 1000000; + while(xentimerread(0) < targ) + continue; +} + +void +delay(int millisecs) +{ + microdelay(millisecs * 1000); +} + +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + uvlong x; + + cycles(&x); + return x; +} |