Annotation of Gnu-Mach/xen/time.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.