|
|
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;
1.1.1.2 ! root 37: unsigned64_t delta_high, delta_low;
1.1 root 38: unsigned32_t mul;
39: signed8_t shift;
40: volatile struct vcpu_time_info *time = &hyp_shared_info.vcpu_info[0].time;
41:
42: do {
43: version = time->version;
44: rmb();
45: cpu_clock = hyp_cpu_clock();
46: last_cpu_clock = time->tsc_timestamp;
47: system_time = time->system_time;
48: mul = time->tsc_to_system_mul;
49: shift = time->tsc_shift;
50: rmb();
51: } while (version != time->version);
52:
53: delta = cpu_clock - last_cpu_clock;
54: if (shift < 0)
55: delta >>= -shift;
56: else
57: delta <<= shift;
1.1.1.2 ! root 58: delta_high = delta >> 32;
! 59: delta_low = (unsigned32_t) delta;
! 60: return system_time + ((delta_low * (unsigned64_t) mul) >> 32)
! 61: + (delta_high * (unsigned64_t) mul);
1.1 root 62: }
63:
64: unsigned64_t hyp_get_time(void) {
65: unsigned32_t version;
66: unsigned32_t sec, nsec;
67:
68: do {
69: version = hyp_shared_info.wc_version;
70: rmb();
71: sec = hyp_shared_info.wc_sec;
72: nsec = hyp_shared_info.wc_nsec;
73: rmb();
74: } while (version != hyp_shared_info.wc_version);
75:
76: return sec*1000000000ULL + nsec + hyp_get_stime();
77: }
78:
79: static void hypclock_intr(int unit, int old_ipl, void *ret_addr, struct i386_interrupt_state *regs) {
80: unsigned64_t nsec, delta;
81:
82: if (!lastnsec)
83: return;
84:
85: nsec = hyp_get_stime();
86: if (nsec < lastnsec) {
87: 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);
88: nsec = lastnsec;
89: }
90: delta = nsec-lastnsec;
91:
92: lastnsec += (delta/1000)*1000;
93: hypclock_machine_intr(old_ipl, ret_addr, regs, delta);
94: /* 10ms tick rest */
95: hyp_do_set_timer_op(hyp_get_stime()+10*1000*1000);
96:
97: #if 0
98: char *c = hyp_store_read(0, 1, "control/shutdown");
99: if (c) {
100: static int go_down = 0;
101: if (!go_down) {
102: printf("uh oh, shutdown: %s\n", c);
103: go_down = 1;
104: /* TODO: somehow send startup_reboot notification to init */
105: if (!strcmp(c, "reboot")) {
106: /* this is just a reboot */
107: }
108: }
109: }
110: #endif
111: }
112:
113: extern struct timeval time;
114:
115: int
116: readtodc(tp)
117: u_int *tp;
118: {
119: unsigned64_t t = hyp_get_time();
120: u_int n = t / 1000000000;
121:
122: *tp = n;
123:
124: return(0);
125: }
126:
127: int
128: writetodc()
129: {
130: /* Not allowed in Xen */
131: return(-1);
132: }
133:
134: void
135: clkstart()
136: {
137: evtchn_port_t port = hyp_event_channel_bind_virq(VIRQ_TIMER, 0);
138: hyp_evt_handler(port, hypclock_intr, 0, SPLHI);
139:
140: /* first clock tick */
141: clock_interrupt(0, 0, 0);
142: lastnsec = hyp_get_stime();
143:
144: /* 10ms tick rest */
145: hyp_do_set_timer_op(hyp_get_stime()+10*1000*1000);
146: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.