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

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

unix.superglobalmegacorp.com

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