Annotation of Gnu-Mach/xen/time.c, revision 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.