]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/xen/xentimer.c
bcm: flush out early boot messages on uart and screen initialization
[plan9front.git] / sys / src / 9 / xen / xentimer.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7
8 static vcpu_time_info_t shadow[MAX_VIRT_CPUS];          // XXX should be in Mach
9 static ulong wallclock;
10 static ulong wallclocksystime;
11
12 /*
13  * Return a consistent set of time parameters.
14  */
15 static vcpu_time_info_t *
16 getshadow(void)
17 {
18         vcpu_time_info_t *s, *t;
19
20         t = &HYPERVISOR_shared_info->vcpu_info[m->machno].time;
21         s = &shadow[m->machno];         // XXX place in mach struct
22         while(t->version != s->version) {
23                 if (t->version&1)
24                         continue;
25                 s->version = t->version;
26                 s->tsc_timestamp = t->tsc_timestamp;
27                 s->system_time = t->system_time;
28                 s->tsc_to_system_mul = t->tsc_to_system_mul;
29                 s->tsc_shift = t->tsc_shift;
30         }
31         return s;
32 }
33
34
35 /* just get it from the shared info */
36 void
37 guesscpuhz(int) // XXX no arg!
38 {
39         vcpu_time_info_t *t;
40
41         t = getshadow();
42         m->cpuhz = (1000000000LL << 32) / t->tsc_to_system_mul;
43         if(t->tsc_shift < 0)
44                 m->cpuhz <<= -t->tsc_shift;
45         else
46                 m->cpuhz >>= t->tsc_shift;
47         m->cpumhz = m->cpuhz / 1000000L;
48 }
49
50 void
51 xentimerset(uvlong next)
52 {
53         uvlong soon;
54
55         soon = fastticks(0) + 100000;
56         if (next < soon)
57                 next = soon;
58         HYPERVISOR_set_timer_op(next);
59 }
60
61 void
62 xentimerclock(Ureg* ureg, void*)
63 {
64
65         timerintr(ureg, 0);
66 }
67
68 void
69 xentimerenable(void)
70 {
71         intrenable(VIRQ_TIMER, xentimerclock, nil, 0, "Xen Timer");
72 }
73
74 uvlong
75 xentimerread(uvlong *hz)
76 {
77         uvlong x;
78         uvlong delta, sdelta;
79         vcpu_time_info_t *t;
80
81         t = getshadow();
82         cycles(&x);
83         delta = x - t->tsc_timestamp;
84         if (t->tsc_shift < 0)
85                 delta >>= -t->tsc_shift;
86         else
87                 delta <<= t->tsc_shift;
88         mul64fract(&sdelta, delta, t->tsc_to_system_mul);
89         x = t->system_time + sdelta;
90         if (HYPERVISOR_shared_info->wc_sec != wallclock) {
91                 wallclock = HYPERVISOR_shared_info->wc_sec;
92                 wallclocksystime = x;
93         }
94         if (hz)
95                 *hz = 1000000000;
96         return x;
97 }
98
99 ulong
100 xenwallclock()
101 {
102         ulong elapsed;
103
104         elapsed = (ulong)((xentimerread(0) - wallclocksystime)/1000000000);
105         return wallclock + elapsed;
106 }
107
108 void
109 microdelay(int microsecs)
110 {
111         uvlong targ, hz;
112
113         targ = xentimerread(&hz);
114         targ += microsecs * hz / 1000000;
115         while(xentimerread(0) < targ)
116                 continue;
117 }
118
119 void
120 delay(int millisecs)
121 {
122         microdelay(millisecs * 1000);
123 }
124
125 /*  
126  *  performance measurement ticks.  must be low overhead.
127  *  doesn't have to count over a second.
128  */
129 ulong
130 perfticks(void)
131 {
132         uvlong x;
133
134         cycles(&x);
135         return x;
136 }