ia64/xen-unstable

changeset 11890:71e2a165aa7f

[HVM] Move RTC emulation into the hypervisor.
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(&current->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))