|
|
1.1 root 1: /*
2: * Copyright (C) 2006-2009 Free Software Foundation
3: *
4: * This program is free software ; you can redistribute it and/or modify
5: * it under the terms of the GNU General Public License as published by
6: * the Free Software Foundation ; either version 2 of the License, or
7: * (at your option) any later version.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY ; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with the program ; if not, write to the Free Software
16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include <sys/types.h>
20: #include <mach/mach_types.h>
21: #include <kern/mach_clock.h>
22: #include <mach/xen.h>
23: #include <machine/xen.h>
24: #include <machine/spl.h>
25: #include <machine/ipl.h>
26: #include <mach/machine/eflags.h>
27: #include <xen/evt.h>
28: #include "time.h"
29: #include "store.h"
30:
31: static unsigned64_t lastnsec;
32:
33: /* 2^64 nanoseconds ~= 500 years */
34: static unsigned64_t hyp_get_stime(void) {
35: unsigned32_t version;
36: unsigned64_t cpu_clock, last_cpu_clock, delta, system_time;
37: unsigned32_t mul;
38: signed8_t shift;
39: volatile struct vcpu_time_info *time = &hyp_shared_info.vcpu_info[0].time;
40:
41: do {
42: version = time->version;
43: rmb();
44: cpu_clock = hyp_cpu_clock();
45: last_cpu_clock = time->tsc_timestamp;
46: system_time = time->system_time;
47: mul = time->tsc_to_system_mul;
48: shift = time->tsc_shift;
49: rmb();
50: } while (version != time->version);
51:
52: delta = cpu_clock - last_cpu_clock;
53: if (shift < 0)
54: delta >>= -shift;
55: else
56: delta <<= shift;
57: return system_time + ((delta * (unsigned64_t) mul) >> 32);
58: }
59:
60: unsigned64_t hyp_get_time(void) {
61: unsigned32_t version;
62: unsigned32_t sec, nsec;
63:
64: do {
65: version = hyp_shared_info.wc_version;
66: rmb();
67: sec = hyp_shared_info.wc_sec;
68: nsec = hyp_shared_info.wc_nsec;
69: rmb();
70: } while (version != hyp_shared_info.wc_version);
71:
72: return sec*1000000000ULL + nsec + hyp_get_stime();
73: }
74:
75: static void hypclock_intr(int unit, int old_ipl, void *ret_addr, struct i386_interrupt_state *regs) {
76: unsigned64_t nsec, delta;
77:
78: if (!lastnsec)
79: return;
80:
81: nsec = hyp_get_stime();
82: if (nsec < lastnsec) {
83: printf("warning: nsec 0x%08lx%08lx < lastnsec 0x%08lx%08lx\n",(unsigned long)(nsec>>32), (unsigned long)nsec, (unsigned long)(lastnsec>>32), (unsigned long)lastnsec);
84: nsec = lastnsec;
85: }
86: delta = nsec-lastnsec;
87:
88: lastnsec += (delta/1000)*1000;
89: hypclock_machine_intr(old_ipl, ret_addr, regs, delta);
90: /* 10ms tick rest */
91: hyp_do_set_timer_op(hyp_get_stime()+10*1000*1000);
92:
93: #if 0
94: char *c = hyp_store_read(0, 1, "control/shutdown");
95: if (c) {
96: static int go_down = 0;
97: if (!go_down) {
98: printf("uh oh, shutdown: %s\n", c);
99: go_down = 1;
100: /* TODO: somehow send startup_reboot notification to init */
101: if (!strcmp(c, "reboot")) {
102: /* this is just a reboot */
103: }
104: }
105: }
106: #endif
107: }
108:
109: extern struct timeval time;
110: extern struct timezone tz;
111:
112: int
113: readtodc(tp)
114: u_int *tp;
115: {
116: unsigned64_t t = hyp_get_time();
117: u_int n = t / 1000000000;
118:
119: *tp = n;
120:
121: return(0);
122: }
123:
124: int
125: writetodc()
126: {
127: /* Not allowed in Xen */
128: return(-1);
129: }
130:
131: void
132: clkstart()
133: {
134: evtchn_port_t port = hyp_event_channel_bind_virq(VIRQ_TIMER, 0);
135: hyp_evt_handler(port, hypclock_intr, 0, SPLHI);
136:
137: /* first clock tick */
138: clock_interrupt(0, 0, 0);
139: lastnsec = hyp_get_stime();
140:
141: /* 10ms tick rest */
142: hyp_do_set_timer_op(hyp_get_stime()+10*1000*1000);
143: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.