|
|
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.