direct-io.hg
changeset 11817:71e2a165aa7f
[HVM] Move RTC emulation into the hypervisor.
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
author | kfraser@localhost.localdomain |
---|---|
date | Wed Oct 18 18:35:21 2006 +0100 (2006-10-18) |
parents | da66691687df |
children | f247e0b52dda |
files | tools/ioemu/Makefile.target tools/ioemu/target-i386-dm/rtc-dm.c xen/arch/x86/hvm/Makefile xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/i8259.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/io.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/time.c xen/common/Makefile xen/common/time.c xen/include/asm-x86/hvm/vpic.h xen/include/asm-x86/hvm/vpit.h xen/include/xen/time.h |
line diff
1.1 --- a/tools/ioemu/Makefile.target Wed Oct 18 18:13:57 2006 +0100 1.2 +++ b/tools/ioemu/Makefile.target Wed Oct 18 18:35:21 2006 +0100 1.3 @@ -294,7 +294,11 @@ OBJS+=gdbstub.o 1.4 endif 1.5 1.6 # qemu-dm objects 1.7 +ifeq ($(ARCH),ia64) 1.8 LIBOBJS=helper2.o exec-dm.o i8259-dm.o 1.9 +else 1.10 +LIBOBJS=helper2.o exec-dm.o i8259-dm.o rtc-dm.o 1.11 +endif 1.12 1.13 all: $(PROGS) 1.14 1.15 @@ -354,7 +358,11 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o 1.16 ifeq ($(TARGET_BASE_ARCH), i386) 1.17 # Hardware support 1.18 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) 1.19 +ifeq ($(ARCH),ia64) 1.20 VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o 1.21 +else 1.22 +VL_OBJS+= fdc.o serial.o pc.o 1.23 +endif 1.24 VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o 1.25 VL_OBJS+= usb-uhci.o 1.26 VL_OBJS+= piix4acpi.o
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/ioemu/target-i386-dm/rtc-dm.c Wed Oct 18 18:35:21 2006 +0100 2.3 @@ -0,0 +1,107 @@ 2.4 +/* 2.5 + * QEMU MC146818 RTC emulation 2.6 + * 2.7 + * Copyright (c) 2003-2004 Fabrice Bellard 2.8 + * 2.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy 2.10 + * of this software and associated documentation files (the "Software"), to deal 2.11 + * in the Software without restriction, including without limitation the rights 2.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 2.13 + * copies of the Software, and to permit persons to whom the Software is 2.14 + * furnished to do so, subject to the following conditions: 2.15 + * 2.16 + * The above copyright notice and this permission notice shall be included in 2.17 + * all copies or substantial portions of the Software. 2.18 + * 2.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2.25 + * THE SOFTWARE. 2.26 + */ 2.27 + 2.28 +#include "vl.h" 2.29 + 2.30 +//#define DEBUG_CMOS 2.31 + 2.32 +struct RTCState { 2.33 + uint8_t cmos_data[128]; 2.34 + uint8_t cmos_index; 2.35 +}; 2.36 + 2.37 +void rtc_set_memory(RTCState *s, int addr, int val) 2.38 +{ 2.39 + if (addr >= 0 && addr <= 127) 2.40 + s->cmos_data[addr] = val; 2.41 +} 2.42 + 2.43 +static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) 2.44 +{ 2.45 + RTCState *s = opaque; 2.46 + 2.47 + if ((addr & 1) == 0) { 2.48 + s->cmos_index = data & 0x7f; 2.49 + } else { 2.50 +#ifdef DEBUG_CMOS 2.51 + printf("cmos: write index=0x%02x val=0x%02x\n", 2.52 + s->cmos_index, data); 2.53 +#endif 2.54 + s->cmos_data[s->cmos_index] = data; 2.55 + } 2.56 +} 2.57 + 2.58 +static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) 2.59 +{ 2.60 + RTCState *s = opaque; 2.61 + int ret; 2.62 + if ((addr & 1) == 0) { 2.63 + return 0xff; 2.64 + } else { 2.65 + ret = s->cmos_data[s->cmos_index]; 2.66 +#ifdef DEBUG_CMOS 2.67 + printf("cmos: read index=0x%02x val=0x%02x\n", 2.68 + s->cmos_index, ret); 2.69 +#endif 2.70 + return ret; 2.71 + } 2.72 +} 2.73 + 2.74 +static void rtc_save(QEMUFile *f, void *opaque) 2.75 +{ 2.76 + RTCState *s = opaque; 2.77 + 2.78 + qemu_put_buffer(f, s->cmos_data, 128); 2.79 + qemu_put_8s(f, &s->cmos_index); 2.80 +} 2.81 + 2.82 +static int rtc_load(QEMUFile *f, void *opaque, int version_id) 2.83 +{ 2.84 + RTCState *s = opaque; 2.85 + 2.86 + if (version_id != 1) 2.87 + return -EINVAL; 2.88 + 2.89 + qemu_get_buffer(f, s->cmos_data, 128); 2.90 + qemu_get_8s(f, &s->cmos_index); 2.91 + 2.92 + return 0; 2.93 +} 2.94 + 2.95 +RTCState *rtc_init(int base, int irq) 2.96 +{ 2.97 + RTCState *s; 2.98 + 2.99 + s = qemu_mallocz(sizeof(RTCState)); 2.100 + if (!s) 2.101 + return NULL; 2.102 + 2.103 + register_ioport_write(base, 2, 1, cmos_ioport_write, s); 2.104 + register_ioport_read(base, 2, 1, cmos_ioport_read, s); 2.105 + 2.106 + register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); 2.107 + return s; 2.108 +} 2.109 + 2.110 +void rtc_set_date(RTCState *s, const struct tm *tm) {}
3.1 --- a/xen/arch/x86/hvm/Makefile Wed Oct 18 18:13:57 2006 +0100 3.2 +++ b/xen/arch/x86/hvm/Makefile Wed Oct 18 18:35:21 2006 +0100 3.3 @@ -4,6 +4,7 @@ subdir-y += vmx 3.4 obj-y += hvm.o 3.5 obj-y += i8254.o 3.6 obj-y += i8259.o 3.7 +obj-y += rtc.o 3.8 obj-y += instrlen.o 3.9 obj-y += intercept.o 3.10 obj-y += io.o
4.1 --- a/xen/arch/x86/hvm/hvm.c Wed Oct 18 18:13:57 2006 +0100 4.2 +++ b/xen/arch/x86/hvm/hvm.c Wed Oct 18 18:35:21 2006 +0100 4.3 @@ -40,8 +40,10 @@ 4.4 #include <asm/processor.h> 4.5 #include <asm/types.h> 4.6 #include <asm/msr.h> 4.7 +#include <asm/mc146818rtc.h> 4.8 #include <asm/spinlock.h> 4.9 #include <asm/hvm/hvm.h> 4.10 +#include <asm/hvm/vpit.h> 4.11 #include <asm/hvm/support.h> 4.12 #include <public/sched.h> 4.13 #include <public/hvm/ioreq.h> 4.14 @@ -277,6 +279,7 @@ void hvm_setup_platform(struct domain* d 4.15 init_timer(&platform->pl_time.periodic_tm.timer, 4.16 pt_timer_fn, v, v->processor); 4.17 pit_init(v, cpu_khz); 4.18 + rtc_init(v, RTC_PORT(0), RTC_IRQ); 4.19 } 4.20 4.21 void pic_irq_request(void *data, int level) 4.22 @@ -368,7 +371,7 @@ void hvm_hlt(unsigned long rflags) 4.23 { 4.24 struct vcpu *v = current; 4.25 struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; 4.26 - s_time_t next_pit = -1, next_wakeup; 4.27 + s_time_t next_pt = -1, next_wakeup; 4.28 4.29 /* 4.30 * If we halt with interrupts disabled, that's a pretty sure sign that we 4.31 @@ -379,10 +382,10 @@ void hvm_hlt(unsigned long rflags) 4.32 return hvm_vcpu_down(); 4.33 4.34 if ( !v->vcpu_id ) 4.35 - next_pit = get_scheduled(v, pt->irq, pt); 4.36 + next_pt = get_scheduled(v, pt->irq, pt); 4.37 next_wakeup = get_apictime_scheduled(v); 4.38 - if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) 4.39 - next_wakeup = next_pit; 4.40 + if ( (next_pt != -1 && next_pt < next_wakeup) || next_wakeup == -1 ) 4.41 + next_wakeup = next_pt; 4.42 if ( next_wakeup != - 1 ) 4.43 set_timer(¤t->arch.hvm_vcpu.hlt_timer, next_wakeup); 4.44 do_sched_op_compat(SCHEDOP_block, 0);
5.1 --- a/xen/arch/x86/hvm/i8254.c Wed Oct 18 18:13:57 2006 +0100 5.2 +++ b/xen/arch/x86/hvm/i8254.c Wed Oct 18 18:35:21 2006 +0100 5.3 @@ -49,7 +49,6 @@ 5.4 #define RW_STATE_WORD0 3 5.5 #define RW_STATE_WORD1 4 5.6 5.7 -#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency) 5.8 static int handle_pit_io(ioreq_t *p); 5.9 static int handle_speaker_io(ioreq_t *p); 5.10 5.11 @@ -77,17 +76,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b 5.12 return res.ll; 5.13 } 5.14 5.15 -/* 5.16 - * get processor time. 5.17 - * unit: TSC 5.18 - */ 5.19 -int64_t hvm_get_clock(struct vcpu *v) 5.20 -{ 5.21 - uint64_t gtsc; 5.22 - gtsc = hvm_get_guest_time(v); 5.23 - return gtsc; 5.24 -} 5.25 - 5.26 static int pit_get_count(PITChannelState *s) 5.27 { 5.28 uint64_t d; 5.29 @@ -215,11 +203,11 @@ static inline void pit_load_count(PITCha 5.30 switch (s->mode) { 5.31 case 2: 5.32 /* create periodic time */ 5.33 - s->pt = create_periodic_time (s, period, 0, 0); 5.34 + s->pt = create_periodic_time (period, 0, 0, pit_time_fired, s); 5.35 break; 5.36 case 1: 5.37 /* create one shot time */ 5.38 - s->pt = create_periodic_time (s, period, 0, 1); 5.39 + s->pt = create_periodic_time (period, 0, 1, pit_time_fired, s); 5.40 #ifdef DEBUG_PIT 5.41 printk("HVM_PIT: create one shot time.\n"); 5.42 #endif
6.1 --- a/xen/arch/x86/hvm/i8259.c Wed Oct 18 18:13:57 2006 +0100 6.2 +++ b/xen/arch/x86/hvm/i8259.c Wed Oct 18 18:35:21 2006 +0100 6.3 @@ -598,23 +598,47 @@ int cpu_get_pic_interrupt(struct vcpu *v 6.4 return intno; 6.5 } 6.6 6.7 -int is_pit_irq(struct vcpu *v, int irq, int type) 6.8 +int is_periodic_irq(struct vcpu *v, int irq, int type) 6.9 { 6.10 - int pit_vec; 6.11 + int vec; 6.12 + struct periodic_time *pt = 6.13 + &(v->domain->arch.hvm_domain.pl_time.periodic_tm); 6.14 + struct RTCState *vrtc = 6.15 + &(v->domain->arch.hvm_domain.pl_time.vrtc); 6.16 + 6.17 + if (pt->irq == 0) { /* Is it pit irq? */ 6.18 + if (type == APIC_DM_EXTINT) 6.19 + vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base; 6.20 + else 6.21 + vec = 6.22 + v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector; 6.23 6.24 - if (type == APIC_DM_EXTINT) 6.25 - pit_vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base; 6.26 - else 6.27 - pit_vec = 6.28 - v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector; 6.29 + if (irq == vec) 6.30 + return 1; 6.31 + } 6.32 6.33 - return (irq == pit_vec); 6.34 + if (pt->irq == 8) { /* Or rtc irq? */ 6.35 + if (type == APIC_DM_EXTINT) 6.36 + vec = v->domain->arch.hvm_domain.vpic.pics[1].irq_base; 6.37 + else 6.38 + vec = 6.39 + v->domain->arch.hvm_domain.vioapic.redirtbl[8].RedirForm.vector; 6.40 + 6.41 + if (irq == vec) 6.42 + return is_rtc_periodic_irq(vrtc); 6.43 + } 6.44 + 6.45 + return 0; 6.46 } 6.47 6.48 int is_irq_enabled(struct vcpu *v, int irq) 6.49 { 6.50 + struct hvm_vioapic *vioapic = &v->domain->arch.hvm_domain.vioapic; 6.51 struct hvm_virpic *vpic=&v->domain->arch.hvm_domain.vpic; 6.52 - 6.53 + 6.54 + if (vioapic->redirtbl[irq].RedirForm.mask == 0) 6.55 + return 1; 6.56 + 6.57 if ( irq & 8 ) { 6.58 return !( (1 << (irq&7)) & vpic->pics[1].imr); 6.59 }
7.1 --- a/xen/arch/x86/hvm/intercept.c Wed Oct 18 18:13:57 2006 +0100 7.2 +++ b/xen/arch/x86/hvm/intercept.c Wed Oct 18 18:35:21 2006 +0100 7.3 @@ -315,17 +315,14 @@ void pickup_deactive_ticks(struct period 7.4 * period: fire frequency in ns. 7.5 */ 7.6 struct periodic_time * create_periodic_time( 7.7 - PITChannelState *s, 7.8 u32 period, 7.9 char irq, 7.10 - char one_shot) 7.11 + char one_shot, 7.12 + time_cb *cb, 7.13 + void *data) 7.14 { 7.15 - struct vcpu *v = s->vcpu; 7.16 - struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); 7.17 + struct periodic_time *pt = &(current->domain->arch.hvm_domain.pl_time.periodic_tm); 7.18 if ( pt->enabled ) { 7.19 - if ( v->vcpu_id != 0 ) { 7.20 - printk("HVM_PIT: start 2nd periodic time on non BSP!\n"); 7.21 - } 7.22 stop_timer (&pt->timer); 7.23 pt->enabled = 0; 7.24 } 7.25 @@ -345,7 +342,8 @@ struct periodic_time * create_periodic_t 7.26 pt->scheduled = NOW() + period; 7.27 set_timer (&pt->timer,pt->scheduled); 7.28 pt->enabled = 1; 7.29 - pt->priv = s; 7.30 + pt->cb = cb; 7.31 + pt->priv = data; 7.32 return pt; 7.33 } 7.34
8.1 --- a/xen/arch/x86/hvm/io.c Wed Oct 18 18:13:57 2006 +0100 8.2 +++ b/xen/arch/x86/hvm/io.c Wed Oct 18 18:35:21 2006 +0100 8.3 @@ -683,7 +683,7 @@ void hvm_interrupt_post(struct vcpu *v, 8.4 struct periodic_time *pt = 8.5 &(v->domain->arch.hvm_domain.pl_time.periodic_tm); 8.6 8.7 - if ( is_pit_irq(v, vector, type) ) { 8.8 + if ( pt->enabled && is_periodic_irq(v, vector, type) ) { 8.9 if ( !pt->first_injected ) { 8.10 pt->pending_intr_nr = 0; 8.11 pt->last_plt_gtime = hvm_get_guest_time(v); 8.12 @@ -694,8 +694,9 @@ void hvm_interrupt_post(struct vcpu *v, 8.13 pt->pending_intr_nr--; 8.14 pt->last_plt_gtime += pt->period_cycles; 8.15 hvm_set_guest_time(v, pt->last_plt_gtime); 8.16 - pit_time_fired(v, pt->priv); 8.17 } 8.18 + if (pt->cb) 8.19 + pt->cb(v, pt->priv); 8.20 } 8.21 8.22 switch(type) {
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/xen/arch/x86/hvm/rtc.c Wed Oct 18 18:35:21 2006 +0100 9.3 @@ -0,0 +1,393 @@ 9.4 +/* 9.5 + * QEMU MC146818 RTC emulation 9.6 + * 9.7 + * Copyright (c) 2003-2004 Fabrice Bellard 9.8 + * 9.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy 9.10 + * of this software and associated documentation files (the "Software"), to deal 9.11 + * in the Software without restriction, including without limitation the rights 9.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9.13 + * copies of the Software, and to permit persons to whom the Software is 9.14 + * furnished to do so, subject to the following conditions: 9.15 + * 9.16 + * The above copyright notice and this permission notice shall be included in 9.17 + * all copies or substantial portions of the Software. 9.18 + * 9.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 9.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 9.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 9.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 9.25 + * THE SOFTWARE. 9.26 + */ 9.27 + 9.28 +#include <asm/mc146818rtc.h> 9.29 +#include <asm/hvm/vpit.h> 9.30 +#include <asm/hvm/io.h> 9.31 +#include <asm/hvm/support.h> 9.32 +#include <asm/current.h> 9.33 + 9.34 +/* #define DEBUG_RTC */ 9.35 + 9.36 +void rtc_periodic_cb(struct vcpu *v, void *opaque) 9.37 +{ 9.38 + RTCState *s = opaque; 9.39 + s->cmos_data[RTC_REG_C] |= 0xc0; 9.40 +} 9.41 + 9.42 +int is_rtc_periodic_irq(void *opaque) 9.43 +{ 9.44 + RTCState *s = opaque; 9.45 + return !(s->cmos_data[RTC_REG_C] & RTC_AF || 9.46 + s->cmos_data[RTC_REG_C] & RTC_UF); 9.47 +} 9.48 + 9.49 +static void rtc_timer_update(RTCState *s, int64_t current_time) 9.50 +{ 9.51 + int period_code; 9.52 + int period; 9.53 + 9.54 + period_code = s->cmos_data[RTC_REG_A] & 0x0f; 9.55 + if (period_code != 0 && (s->cmos_data[RTC_REG_B] & RTC_PIE)) { 9.56 + if (period_code <= 2) 9.57 + period_code += 7; 9.58 + 9.59 + period = 1 << (period_code - 1); /* period in 32 Khz cycles */ 9.60 + period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */ 9.61 + 9.62 +#ifdef DEBUG_RTC 9.63 + printk("HVM_RTC: period = %uns\n", period); 9.64 +#endif 9.65 + 9.66 + s->pt = create_periodic_time(period, RTC_IRQ, 0, rtc_periodic_cb, s); 9.67 + } else if (s->pt) { 9.68 + destroy_periodic_time(s->pt); 9.69 + s->pt = NULL; 9.70 + } 9.71 +} 9.72 + 9.73 +static void rtc_set_time(RTCState *s); 9.74 + 9.75 +static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data) 9.76 +{ 9.77 + RTCState *s = opaque; 9.78 + 9.79 + if ((addr & 1) == 0) { 9.80 + s->cmos_index = data & 0x7f; 9.81 + if (s->cmos_index < RTC_SIZE) 9.82 + return 1; 9.83 + } else if (s->cmos_index < RTC_SIZE) { 9.84 +#ifdef DEBUG_RTC 9.85 + printk("HVM_RTC: write index=0x%02x val=0x%02x\n", 9.86 + s->cmos_index, data); 9.87 +#endif 9.88 + switch(s->cmos_index) { 9.89 + case RTC_SECONDS_ALARM: 9.90 + case RTC_MINUTES_ALARM: 9.91 + case RTC_HOURS_ALARM: 9.92 + s->cmos_data[s->cmos_index] = data; 9.93 + break; 9.94 + case RTC_SECONDS: 9.95 + case RTC_MINUTES: 9.96 + case RTC_HOURS: 9.97 + case RTC_DAY_OF_WEEK: 9.98 + case RTC_DAY_OF_MONTH: 9.99 + case RTC_MONTH: 9.100 + case RTC_YEAR: 9.101 + s->cmos_data[s->cmos_index] = data; 9.102 + /* if in set mode, do not update the time */ 9.103 + if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) { 9.104 + rtc_set_time(s); 9.105 + } 9.106 + break; 9.107 + case RTC_REG_A: 9.108 + /* UIP bit is read only */ 9.109 + s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | 9.110 + (s->cmos_data[RTC_REG_A] & RTC_UIP); 9.111 + rtc_timer_update(s, hvm_get_clock(s->vcpu)); 9.112 + break; 9.113 + case RTC_REG_B: 9.114 + if (data & RTC_SET) { 9.115 + /* set mode: reset UIP mode */ 9.116 + s->cmos_data[RTC_REG_A] &= ~RTC_UIP; 9.117 + data &= ~RTC_UIE; 9.118 + } else { 9.119 + /* if disabling set mode, update the time */ 9.120 + if (s->cmos_data[RTC_REG_B] & RTC_SET) { 9.121 + rtc_set_time(s); 9.122 + } 9.123 + } 9.124 + s->cmos_data[RTC_REG_B] = data; 9.125 + rtc_timer_update(s, hvm_get_clock(s->vcpu)); 9.126 + break; 9.127 + case RTC_REG_C: 9.128 + case RTC_REG_D: 9.129 + /* cannot write to them */ 9.130 + break; 9.131 + return 1; 9.132 + } 9.133 + } 9.134 + return 0; 9.135 +} 9.136 + 9.137 +static inline int to_bcd(RTCState *s, int a) 9.138 +{ 9.139 + if (s->cmos_data[RTC_REG_B] & 0x04) { 9.140 + return a; 9.141 + } else { 9.142 + return ((a / 10) << 4) | (a % 10); 9.143 + } 9.144 +} 9.145 + 9.146 +static inline int from_bcd(RTCState *s, int a) 9.147 +{ 9.148 + if (s->cmos_data[RTC_REG_B] & 0x04) { 9.149 + return a; 9.150 + } else { 9.151 + return ((a >> 4) * 10) + (a & 0x0f); 9.152 + } 9.153 +} 9.154 + 9.155 +static void rtc_set_time(RTCState *s) 9.156 +{ 9.157 + struct tm *tm = &s->current_tm; 9.158 + 9.159 + tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]); 9.160 + tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]); 9.161 + tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); 9.162 + if (!(s->cmos_data[RTC_REG_B] & 0x02) && 9.163 + (s->cmos_data[RTC_HOURS] & 0x80)) { 9.164 + tm->tm_hour += 12; 9.165 + } 9.166 + tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]); 9.167 + tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); 9.168 + tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; 9.169 + tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100; 9.170 +} 9.171 + 9.172 +static void rtc_copy_date(RTCState *s) 9.173 +{ 9.174 + const struct tm *tm = &s->current_tm; 9.175 + 9.176 + s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); 9.177 + s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); 9.178 + if (s->cmos_data[RTC_REG_B] & 0x02) { 9.179 + /* 24 hour format */ 9.180 + s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour); 9.181 + } else { 9.182 + /* 12 hour format */ 9.183 + s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12); 9.184 + if (tm->tm_hour >= 12) 9.185 + s->cmos_data[RTC_HOURS] |= 0x80; 9.186 + } 9.187 + s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday); 9.188 + s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday); 9.189 + s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1); 9.190 + s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100); 9.191 +} 9.192 + 9.193 +/* month is between 0 and 11. */ 9.194 +static int get_days_in_month(int month, int year) 9.195 +{ 9.196 + static const int days_tab[12] = { 9.197 + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 9.198 + }; 9.199 + int d; 9.200 + if ((unsigned )month >= 12) 9.201 + return 31; 9.202 + d = days_tab[month]; 9.203 + if (month == 1) { 9.204 + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) 9.205 + d++; 9.206 + } 9.207 + return d; 9.208 +} 9.209 + 9.210 +/* update 'tm' to the next second */ 9.211 +static void rtc_next_second(struct tm *tm) 9.212 +{ 9.213 + int days_in_month; 9.214 + 9.215 + tm->tm_sec++; 9.216 + if ((unsigned)tm->tm_sec >= 60) { 9.217 + tm->tm_sec = 0; 9.218 + tm->tm_min++; 9.219 + if ((unsigned)tm->tm_min >= 60) { 9.220 + tm->tm_min = 0; 9.221 + tm->tm_hour++; 9.222 + if ((unsigned)tm->tm_hour >= 24) { 9.223 + tm->tm_hour = 0; 9.224 + /* next day */ 9.225 + tm->tm_wday++; 9.226 + if ((unsigned)tm->tm_wday >= 7) 9.227 + tm->tm_wday = 0; 9.228 + days_in_month = get_days_in_month(tm->tm_mon, 9.229 + tm->tm_year + 1900); 9.230 + tm->tm_mday++; 9.231 + if (tm->tm_mday < 1) { 9.232 + tm->tm_mday = 1; 9.233 + } else if (tm->tm_mday > days_in_month) { 9.234 + tm->tm_mday = 1; 9.235 + tm->tm_mon++; 9.236 + if (tm->tm_mon >= 12) { 9.237 + tm->tm_mon = 0; 9.238 + tm->tm_year++; 9.239 + } 9.240 + } 9.241 + } 9.242 + } 9.243 + } 9.244 +} 9.245 + 9.246 +static void rtc_update_second(void *opaque) 9.247 +{ 9.248 + RTCState *s = opaque; 9.249 + 9.250 + /* if the oscillator is not in normal operation, we do not update */ 9.251 + if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { 9.252 + s->next_second_time += 1000000000ULL; 9.253 + set_timer(&s->second_timer, s->next_second_time); 9.254 + } else { 9.255 + rtc_next_second(&s->current_tm); 9.256 + 9.257 + if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) { 9.258 + /* update in progress bit */ 9.259 + s->cmos_data[RTC_REG_A] |= RTC_UIP; 9.260 + } 9.261 + /* Delay time before update cycle */ 9.262 + set_timer(&s->second_timer2, s->next_second_time + 244000); 9.263 + } 9.264 +} 9.265 + 9.266 +static void rtc_update_second2(void *opaque) 9.267 +{ 9.268 + RTCState *s = opaque; 9.269 + struct hvm_domain *plat=&s->vcpu->domain->arch.hvm_domain; 9.270 + struct hvm_virpic *pic= &plat->vpic; 9.271 + 9.272 + if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) { 9.273 + rtc_copy_date(s); 9.274 + } 9.275 + 9.276 + /* check alarm */ 9.277 + if (s->cmos_data[RTC_REG_B] & RTC_AIE) { 9.278 + if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || 9.279 + s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) && 9.280 + ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || 9.281 + s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) && 9.282 + ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || 9.283 + s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) { 9.284 + 9.285 + s->cmos_data[RTC_REG_C] |= 0xa0; 9.286 + pic_set_irq(pic, s->irq, 0); 9.287 + pic_set_irq(pic, s->irq, 1); 9.288 + } 9.289 + } 9.290 + 9.291 + /* update ended interrupt */ 9.292 + if (s->cmos_data[RTC_REG_B] & RTC_UIE) { 9.293 + s->cmos_data[RTC_REG_C] |= 0x90; 9.294 + pic_set_irq(pic, s->irq, 0); 9.295 + pic_set_irq(pic, s->irq, 1); 9.296 + } 9.297 + 9.298 + /* clear update in progress bit */ 9.299 + s->cmos_data[RTC_REG_A] &= ~RTC_UIP; 9.300 + 9.301 + s->next_second_time += 1000000000ULL; 9.302 + set_timer(&s->second_timer, s->next_second_time); 9.303 +} 9.304 + 9.305 +static uint32_t rtc_ioport_read(void *opaque, uint32_t addr) 9.306 +{ 9.307 + RTCState *s = opaque; 9.308 + struct hvm_domain *plat=&s->vcpu->domain->arch.hvm_domain; 9.309 + struct hvm_virpic *pic= &plat->vpic; 9.310 + int ret; 9.311 + 9.312 + if ((addr & 1) == 0) { 9.313 + return 0xff; 9.314 + } else { 9.315 + switch(s->cmos_index) { 9.316 + case RTC_SECONDS: 9.317 + case RTC_MINUTES: 9.318 + case RTC_HOURS: 9.319 + case RTC_DAY_OF_WEEK: 9.320 + case RTC_DAY_OF_MONTH: 9.321 + case RTC_MONTH: 9.322 + case RTC_YEAR: 9.323 + ret = s->cmos_data[s->cmos_index]; 9.324 + break; 9.325 + case RTC_REG_A: 9.326 + ret = s->cmos_data[s->cmos_index]; 9.327 + break; 9.328 + case RTC_REG_C: 9.329 + ret = s->cmos_data[s->cmos_index]; 9.330 + pic_set_irq(pic, s->irq, 0); 9.331 + s->cmos_data[RTC_REG_C] = 0x00; 9.332 + break; 9.333 + default: 9.334 + ret = s->cmos_data[s->cmos_index]; 9.335 + break; 9.336 + } 9.337 +#ifdef DEBUG_RTC 9.338 + printk("HVM_RTC: read index=0x%02x val=0x%02x\n", 9.339 + s->cmos_index, ret); 9.340 +#endif 9.341 + return ret; 9.342 + } 9.343 +} 9.344 + 9.345 +static int handle_rtc_io(ioreq_t *p) 9.346 +{ 9.347 + struct vcpu *v = current; 9.348 + struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; 9.349 + 9.350 + if (p->size != 1 || 9.351 + p->pdata_valid || 9.352 + p->type != IOREQ_TYPE_PIO){ 9.353 + printk("HVM_RTC: wrong RTC IO!\n"); 9.354 + return 1; 9.355 + } 9.356 + 9.357 + if (p->dir == 0) { /* write */ 9.358 + if (rtc_ioport_write(vrtc, p->addr, p->u.data & 0xFF)) 9.359 + return 1; 9.360 + } else if (p->dir == 1 && vrtc->cmos_index < RTC_SIZE) { /* read */ 9.361 + p->u.data = rtc_ioport_read(vrtc, p->addr); 9.362 + return 1; 9.363 + } 9.364 + return 0; 9.365 +} 9.366 + 9.367 +void rtc_init(struct vcpu *v, int base, int irq) 9.368 +{ 9.369 + RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; 9.370 + 9.371 + s->vcpu = v; 9.372 + s->irq = irq; 9.373 + s->cmos_data[RTC_REG_A] = 0x26; 9.374 + s->cmos_data[RTC_REG_B] = 0x02; 9.375 + s->cmos_data[RTC_REG_C] = 0x00; 9.376 + s->cmos_data[RTC_REG_D] = 0x80; 9.377 + 9.378 + s->current_tm = gmtime(get_localtime(v->domain)); 9.379 + rtc_copy_date(s); 9.380 + 9.381 + init_timer(&s->second_timer, rtc_update_second, s, v->processor); 9.382 + init_timer(&s->second_timer2, rtc_update_second2, s, v->processor); 9.383 + 9.384 + s->next_second_time = NOW() + 1000000000ULL; 9.385 + set_timer(&s->second_timer2, s->next_second_time); 9.386 + 9.387 + register_portio_handler(base, 2, handle_rtc_io); 9.388 +} 9.389 + 9.390 +void rtc_deinit(struct domain *d) 9.391 +{ 9.392 + RTCState *s = &d->arch.hvm_domain.pl_time.vrtc; 9.393 + 9.394 + kill_timer(&s->second_timer); 9.395 + kill_timer(&s->second_timer2); 9.396 +}
10.1 --- a/xen/arch/x86/hvm/svm/intr.c Wed Oct 18 18:13:57 2006 +0100 10.2 +++ b/xen/arch/x86/hvm/svm/intr.c Wed Oct 18 18:35:21 2006 +0100 10.3 @@ -140,8 +140,8 @@ asmlinkage void svm_intr_assist(void) 10.4 case APIC_DM_FIXED: 10.5 case APIC_DM_LOWEST: 10.6 /* Re-injecting a PIT interruptt? */ 10.7 - if (re_injecting && 10.8 - is_pit_irq(v, intr_vector, intr_type)) { 10.9 + if (re_injecting && pt->enabled && 10.10 + is_periodic_irq(v, intr_vector, intr_type)) { 10.11 ++pt->pending_intr_nr; 10.12 } 10.13 /* let's inject this interrupt */
11.1 --- a/xen/arch/x86/hvm/svm/svm.c Wed Oct 18 18:13:57 2006 +0100 11.2 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Oct 18 18:35:21 2006 +0100 11.3 @@ -921,6 +921,7 @@ static void svm_relinquish_guest_resourc 11.4 } 11.5 11.6 kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); 11.7 + rtc_deinit(d); 11.8 11.9 if ( d->arch.hvm_domain.shared_page_va ) 11.10 unmap_domain_page_global( 11.11 @@ -935,6 +936,7 @@ static void svm_migrate_timers(struct vc 11.12 { 11.13 struct periodic_time *pt = 11.14 &(v->domain->arch.hvm_domain.pl_time.periodic_tm); 11.15 + struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; 11.16 11.17 if ( pt->enabled ) 11.18 { 11.19 @@ -943,6 +945,8 @@ static void svm_migrate_timers(struct vc 11.20 } 11.21 if ( VLAPIC(v) != NULL ) 11.22 migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); 11.23 + migrate_timer(&vrtc->second_timer, v->processor); 11.24 + migrate_timer(&vrtc->second_timer2, v->processor); 11.25 } 11.26 11.27
12.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Oct 18 18:13:57 2006 +0100 12.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Oct 18 18:35:21 2006 +0100 12.3 @@ -146,6 +146,7 @@ static void vmx_relinquish_guest_resourc 12.4 } 12.5 12.6 kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); 12.7 + rtc_deinit(d); 12.8 12.9 if ( d->arch.hvm_domain.shared_page_va ) 12.10 unmap_domain_page_global( 12.11 @@ -487,6 +488,7 @@ static void stop_vmx(void) 12.12 void vmx_migrate_timers(struct vcpu *v) 12.13 { 12.14 struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); 12.15 + struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; 12.16 12.17 if ( pt->enabled ) 12.18 { 12.19 @@ -495,6 +497,8 @@ void vmx_migrate_timers(struct vcpu *v) 12.20 } 12.21 if ( VLAPIC(v) != NULL ) 12.22 migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); 12.23 + migrate_timer(&vrtc->second_timer, v->processor); 12.24 + migrate_timer(&vrtc->second_timer2, v->processor); 12.25 } 12.26 12.27 static void vmx_store_cpu_guest_regs(
13.1 --- a/xen/arch/x86/time.c Wed Oct 18 18:13:57 2006 +0100 13.2 +++ b/xen/arch/x86/time.c Wed Oct 18 18:35:21 2006 +0100 13.3 @@ -919,6 +919,13 @@ void send_timer_event(struct vcpu *v) 13.4 send_guest_vcpu_virq(v, VIRQ_TIMER); 13.5 } 13.6 13.7 +/* Return secs after 00:00:00 localtime, 1 January, 1970. */ 13.8 +unsigned long get_localtime(struct domain *d) 13.9 +{ 13.10 + return wc_sec + (wc_nsec + NOW()) / 1000000000ULL 13.11 + + d->time_offset_seconds; 13.12 +} 13.13 + 13.14 /* 13.15 * Local variables: 13.16 * mode: C
14.1 --- a/xen/common/Makefile Wed Oct 18 18:13:57 2006 +0100 14.2 +++ b/xen/common/Makefile Wed Oct 18 18:35:21 2006 +0100 14.3 @@ -20,8 +20,9 @@ obj-y += softirq.o 14.4 obj-y += string.o 14.5 obj-y += symbols.o 14.6 obj-y += sysctl.o 14.7 +obj-y += time.o 14.8 +obj-y += timer.o 14.9 obj-y += trace.o 14.10 -obj-y += timer.o 14.11 obj-y += version.o 14.12 obj-y += vsprintf.o 14.13 obj-y += xmalloc.o
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/xen/common/time.c Wed Oct 18 18:35:21 2006 +0100 15.3 @@ -0,0 +1,77 @@ 15.4 +/****************************************************************************** 15.5 + * time.c 15.6 + * 15.7 + * This program is free software; you can redistribute it and/or modify 15.8 + * it under the terms of the GNU General Public License as published by 15.9 + * the Free Software Foundation; either version 2 of the License, or 15.10 + * (at your option) any later version. 15.11 + * 15.12 + * This program is distributed in the hope that it will be useful, 15.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15.15 + * GNU General Public License for more details. 15.16 + * 15.17 + * You should have received a copy of the GNU General Public License 15.18 + * along with this program; if not, write to the Free Software 15.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15.20 + */ 15.21 + 15.22 +#include <xen/config.h> 15.23 +#include <xen/time.h> 15.24 + 15.25 +/* Nonzero if YEAR is a leap year (every 4 years, 15.26 + except every 100th isn't, and every 400th is). */ 15.27 +#define __isleap(year) \ 15.28 + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 15.29 + 15.30 +/* How many days are in each month. */ 15.31 +const unsigned short int __mon_lengths[2][12] = { 15.32 + /* Normal years. */ 15.33 + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 15.34 + /* Leap years. */ 15.35 + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 15.36 +}; 15.37 + 15.38 +#define SECS_PER_HOUR (60 * 60) 15.39 +#define SECS_PER_DAY (SECS_PER_HOUR * 24) 15.40 + 15.41 +struct tm gmtime(unsigned long t) 15.42 +{ 15.43 + struct tm tbuf; 15.44 + long days, rem; 15.45 + int y; 15.46 + unsigned short int *ip; 15.47 + 15.48 + days = t / SECS_PER_DAY; 15.49 + rem = t % SECS_PER_DAY; 15.50 + 15.51 + tbuf.tm_hour = rem / SECS_PER_HOUR; 15.52 + rem %= SECS_PER_HOUR; 15.53 + tbuf.tm_min = rem / 60; 15.54 + tbuf.tm_sec = rem % 60; 15.55 + /* January 1, 1970 was a Thursday. */ 15.56 + tbuf.tm_wday = (4 + days) % 7; 15.57 + if ( tbuf.tm_wday < 0 ) 15.58 + tbuf.tm_wday += 7; 15.59 + y = 1970; 15.60 + while ( days >= (rem = __isleap(y) ? 366 : 365) ) 15.61 + { 15.62 + ++y; 15.63 + days -= rem; 15.64 + } 15.65 + while ( days < 0 ) 15.66 + { 15.67 + --y; 15.68 + days += __isleap(y) ? 366 : 365; 15.69 + } 15.70 + tbuf.tm_year = y - 1900; 15.71 + tbuf.tm_yday = days; 15.72 + ip = (unsigned short int *)__mon_lengths[__isleap(y)]; 15.73 + for ( y = 0; days >= ip[y]; ++y ) 15.74 + days -= ip[y]; 15.75 + tbuf.tm_mon = y; 15.76 + tbuf.tm_mday = days + 1; 15.77 + tbuf.tm_isdst = -1; 15.78 + 15.79 + return tbuf; 15.80 +}
16.1 --- a/xen/include/asm-x86/hvm/vpic.h Wed Oct 18 18:13:57 2006 +0100 16.2 +++ b/xen/include/asm-x86/hvm/vpic.h Wed Oct 18 18:35:21 2006 +0100 16.3 @@ -75,7 +75,7 @@ void pic_update_irq(struct hvm_virpic *s 16.4 uint32_t pic_intack_read(struct hvm_virpic *s); 16.5 void register_pic_io_hook (void); 16.6 int cpu_get_pic_interrupt(struct vcpu *v, int *type); 16.7 -int is_pit_irq(struct vcpu *v, int irq, int type); 16.8 +int is_periodic_irq(struct vcpu *v, int irq, int type); 16.9 int is_irq_enabled(struct vcpu *v, int irq); 16.10 void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs); 16.11 void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs);
17.1 --- a/xen/include/asm-x86/hvm/vpit.h Wed Oct 18 18:13:57 2006 +0100 17.2 +++ b/xen/include/asm-x86/hvm/vpit.h Wed Oct 18 18:35:21 2006 +0100 17.3 @@ -25,11 +25,12 @@ 17.4 #include <xen/lib.h> 17.5 #include <xen/time.h> 17.6 #include <xen/errno.h> 17.7 +#include <xen/time.h> 17.8 #include <xen/timer.h> 17.9 #include <asm/hvm/vpic.h> 17.10 17.11 #define PIT_FREQ 1193181 17.12 -#define PIT_BASE 0x40 17.13 +#define PIT_BASE 0x40 17.14 17.15 typedef struct PITChannelState { 17.16 int count; /* can be 65536 */ 17.17 @@ -49,10 +50,32 @@ typedef struct PITChannelState { 17.18 struct vcpu *vcpu; 17.19 struct periodic_time *pt; 17.20 } PITChannelState; 17.21 + 17.22 +typedef struct PITState { 17.23 + PITChannelState channels[3]; 17.24 + int speaker_data_on; 17.25 + int dummy_refresh_clock; 17.26 +} PITState; 17.27 + 17.28 +#define RTC_SIZE 14 17.29 +typedef struct RTCState { 17.30 + uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */ 17.31 + uint8_t cmos_index; 17.32 + struct tm current_tm; 17.33 + int irq; 17.34 + /* second update */ 17.35 + int64_t next_second_time; 17.36 + struct timer second_timer; 17.37 + struct timer second_timer2; 17.38 + struct vcpu *vcpu; 17.39 + struct periodic_time *pt; 17.40 +} RTCState; 17.41 17.42 /* 17.43 * Abstract layer of periodic time, one short time. 17.44 */ 17.45 +typedef void time_cb(struct vcpu *v, void *opaque); 17.46 + 17.47 struct periodic_time { 17.48 char enabled; /* enabled */ 17.49 char one_shot; /* one shot time */ 17.50 @@ -64,19 +87,15 @@ struct periodic_time { 17.51 s_time_t scheduled; /* scheduled timer interrupt */ 17.52 u64 last_plt_gtime; /* platform time when last IRQ is injected */ 17.53 struct timer timer; /* ac_timer */ 17.54 + time_cb *cb; 17.55 void *priv; /* ponit back to platform time source */ 17.56 }; 17.57 17.58 -typedef struct PITState { 17.59 - PITChannelState channels[3]; 17.60 - int speaker_data_on; 17.61 - int dummy_refresh_clock; 17.62 -} PITState; 17.63 - 17.64 struct pl_time { /* platform time */ 17.65 struct periodic_time periodic_tm; 17.66 struct PITState vpit; 17.67 - /* TODO: RTC/ACPI time */ 17.68 + struct RTCState vrtc; 17.69 + /* TODO: ACPI time */ 17.70 }; 17.71 17.72 static __inline__ s_time_t get_scheduled( 17.73 @@ -90,13 +109,30 @@ static __inline__ s_time_t get_scheduled 17.74 return -1; 17.75 } 17.76 17.77 +extern u64 hvm_get_guest_time(struct vcpu *v); 17.78 +/* 17.79 + * get processor time. 17.80 + * unit: TSC 17.81 + */ 17.82 +static __inline__ int64_t hvm_get_clock(struct vcpu *v) 17.83 +{ 17.84 + uint64_t gtsc; 17.85 + 17.86 + gtsc = hvm_get_guest_time(v); 17.87 + return gtsc; 17.88 +} 17.89 + 17.90 +#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency) 17.91 + 17.92 /* to hook the ioreq packet to get the PIT initialization info */ 17.93 extern void hvm_hooks_assist(struct vcpu *v); 17.94 extern void pickup_deactive_ticks(struct periodic_time *vpit); 17.95 -extern u64 hvm_get_guest_time(struct vcpu *v); 17.96 -extern struct periodic_time *create_periodic_time(PITChannelState *v, u32 period, char irq, char one_shot); 17.97 +extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data); 17.98 extern void destroy_periodic_time(struct periodic_time *pt); 17.99 void pit_init(struct vcpu *v, unsigned long cpu_khz); 17.100 +void rtc_init(struct vcpu *v, int base, int irq); 17.101 +void rtc_deinit(struct domain *d); 17.102 +int is_rtc_periodic_irq(void *opaque); 17.103 void pt_timer_fn(void *data); 17.104 void pit_time_fired(struct vcpu *v, void *priv); 17.105
18.1 --- a/xen/include/xen/time.h Wed Oct 18 18:13:57 2006 +0100 18.2 +++ b/xen/include/xen/time.h Wed Oct 18 18:35:21 2006 +0100 18.3 @@ -49,6 +49,20 @@ struct domain; 18.4 typedef s64 s_time_t; 18.5 18.6 s_time_t get_s_time(void); 18.7 +unsigned long get_localtime(struct domain *d); 18.8 + 18.9 +struct tm { 18.10 + int tm_sec; /* seconds */ 18.11 + int tm_min; /* minutes */ 18.12 + int tm_hour; /* hours */ 18.13 + int tm_mday; /* day of the month */ 18.14 + int tm_mon; /* month */ 18.15 + int tm_year; /* year */ 18.16 + int tm_wday; /* day of the week */ 18.17 + int tm_yday; /* day in the year */ 18.18 + int tm_isdst; /* daylight saving time */ 18.19 +}; 18.20 +struct tm gmtime(unsigned long t); 18.21 18.22 #define NOW() ((s_time_t)get_s_time()) 18.23 #define SECONDS(_s) ((s_time_t)((_s) * 1000000000ULL))