[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Sync PIT device model with latest qemu and move it to hypervisor.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 5765497cf75e7b519ccbc255b4657d854907e2db
# Parent  72f9c751d3ea1f17ff513cd7fc2cbe671a9af7c9
Sync PIT device model with latest qemu and move it to hypervisor.
Signed-off-by: Edwin Zhai <edwin.zhai@xxxxxxxxx>

diff -r 72f9c751d3ea -r 5765497cf75e tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Wed Apr 19 18:32:20 2006 +0100
+++ b/tools/ioemu/hw/pc.c       Wed Apr 19 18:38:14 2006 +0100
@@ -40,7 +40,6 @@ int dummy_refresh_clock;
 int dummy_refresh_clock;
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
-static PITState *pit;
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
@@ -243,17 +242,13 @@ static void cmos_init(uint64_t ram_size,
 
 static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    speaker_data_on = (val >> 1) & 1;
-    pit_set_gate(pit, 2, val & 1);
+    fprintf(stderr, "speaker port should not be handled in DM!\n");
 }
 
 static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
 {
-    int out;
-    out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
-    dummy_refresh_clock ^= 1;
-    return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
-      (dummy_refresh_clock << 4);
+    fprintf(stderr, "speaker port should not be handled in DM!\n");
+    return 0;
 }
 
 static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
@@ -529,7 +524,6 @@ void pc_init(uint64_t ram_size, int vga_
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
     pic_init();
-    pit = pit_init(0x40, 0);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff -r 72f9c751d3ea -r 5765497cf75e tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Wed Apr 19 18:32:20 2006 +0100
+++ b/tools/ioemu/target-i386-dm/Makefile       Wed Apr 19 18:38:14 2006 +0100
@@ -277,7 +277,7 @@ endif
 
 # Hardware support
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
-VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o
+VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o pc.o port-e9.o
 VL_OBJS+= cirrus_vga.o pcnet.o
 VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o
 
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/Makefile
--- a/xen/arch/x86/hvm/Makefile Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/Makefile Wed Apr 19 18:38:14 2006 +0100
@@ -2,6 +2,7 @@ subdir-y += vmx
 subdir-y += vmx
 
 obj-y += hvm.o
+obj-y += i8254.o
 obj-y += i8259.o
 obj-y += intercept.o
 obj-y += io.o
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Wed Apr 19 18:38:14 2006 +0100
@@ -203,6 +203,8 @@ void hvm_setup_platform(struct domain* d
         spin_lock_init(&d->arch.hvm_domain.round_robin_lock);
         hvm_vioapic_init(d);
     }
+
+    pit_init(&platform->vpit, current);
 }
 
 void pic_irq_request(void *data, int level)
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/intercept.c      Wed Apr 19 18:38:14 2006 +0100
@@ -206,139 +206,6 @@ int register_io_handler(unsigned long ad
     return 1;
 }
 
-static void pit_cal_count(struct hvm_virpit *vpit)
-{
-    u64 nsec_delta = (unsigned int)((NOW() - vpit->count_point));
-
-    nsec_delta += vpit->count_advance;
-    if (nsec_delta > vpit->period)
-        HVM_DBG_LOG(DBG_LEVEL_1,
-                   "HVM_PIT: long time has passed from last injection!");
-
-    if(vpit->init_val == 0)
-    {
-        printk("PIT init value == 0!\n");
-        domain_crash_synchronous();
-    }
-
-    vpit->count = vpit->init_val
-                  - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val);
-}
-
-static void pit_latch_io(struct hvm_virpit *vpit)
-{
-    pit_cal_count(vpit);
-
-    switch(vpit->read_state) {
-    case MSByte:
-        vpit->count_MSB_latched=1;
-        break;
-    case LSByte:
-        vpit->count_LSB_latched=1;
-        break;
-    case LSByte_multiple:
-        vpit->count_LSB_latched=1;
-        vpit->count_MSB_latched=1;
-        break;
-    case MSByte_multiple:
-        HVM_DBG_LOG(DBG_LEVEL_1,
-                   "HVM_PIT: latch PIT counter before MSB_multiple!");
-        vpit->read_state=LSByte_multiple;
-        vpit->count_LSB_latched=1;
-        vpit->count_MSB_latched=1;
-        break;
-    default:
-        domain_crash_synchronous();
-    }
-}
-
-static int pit_read_io(struct hvm_virpit *vpit)
-{
-    if(vpit->count_LSB_latched) {
-        /* Read Least Significant Byte */
-        if(vpit->read_state==LSByte_multiple) {
-            vpit->read_state=MSByte_multiple;
-        }
-        vpit->count_LSB_latched=0;
-        return (vpit->count & 0xFF);
-    } else if(vpit->count_MSB_latched) {
-        /* Read Most Significant Byte */
-        if(vpit->read_state==MSByte_multiple) {
-            vpit->read_state=LSByte_multiple;
-        }
-        vpit->count_MSB_latched=0;
-        return ((vpit->count>>8) & 0xFF);
-    } else {
-        /* Unlatched Count Read */
-        HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: unlatched read");
-        pit_cal_count(vpit);
-        if(!(vpit->read_state & 0x1)) {
-            /* Read Least Significant Byte */
-            if(vpit->read_state==LSByte_multiple) {
-                vpit->read_state=MSByte_multiple;
-            }
-            return (vpit->count & 0xFF);
-        } else {
-            /* Read Most Significant Byte */
-            if(vpit->read_state==MSByte_multiple) {
-                vpit->read_state=LSByte_multiple;
-            }
-            return ((vpit->count>>8) & 0xFF);
-        }
-    }
-}
-
-/* hvm_io_assist light-weight version, specific to PIT DM */ 
-static void resume_pit_io(ioreq_t *p)
-{
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
-    unsigned long old_eax = regs->eax;
-    p->state = STATE_INVALID;
-
-    switch(p->size) {
-    case 1:
-        regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
-        break;
-    case 2:
-        regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
-        break;
-    case 4:
-        regs->eax = (p->u.data & 0xffffffff);
-        break;
-    default:
-        BUG();
-    }
-}
-
-/* the intercept action for PIT DM retval:0--not handled; 1--handled */
-int intercept_pit_io(ioreq_t *p)
-{
-    struct vcpu *v = current;
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
-
-    if (p->size != 1 ||
-        p->pdata_valid ||
-        p->type != IOREQ_TYPE_PIO)
-        return 0;
-    
-    if (p->addr == PIT_MODE &&
-        p->dir == 0 &&    /* write */
-        ((p->u.data >> 4) & 0x3) == 0 && /* latch command */
-        ((p->u.data >> 6) & 0x3) == (vpit->channel)) {/* right channel */
-        pit_latch_io(vpit);
-        return 1;
-    }
-
-    if (p->addr == (PIT_CH0 + vpit->channel) &&
-        p->dir == 1) { /* read */
-        p->u.data = pit_read_io(vpit);
-        resume_pit_io(p);
-        return 1;
-    }
-
-    return 0;
-}
-
 /* hooks function for the HLT instruction emulation wakeup */
 void hlt_timer_fn(void *data)
 {
@@ -347,109 +214,6 @@ void hlt_timer_fn(void *data)
     evtchn_set_pending(v, iopacket_port(v));
 }
 
-static __inline__ void missed_ticks(struct hvm_virpit*vpit)
-{
-    int missed_ticks;
-
-    missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
-    if ( missed_ticks++ >= 0 ) {
-        vpit->pending_intr_nr += missed_ticks;
-        vpit->scheduled += missed_ticks * vpit->period;
-    }
-}
-
-/* hooks function for the PIT when the guest is active */
-static void pit_timer_fn(void *data)
-{
-    struct vcpu *v = data;
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
-
-    /* pick up missed timer tick */
-    missed_ticks(vpit);
-    if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) {
-        set_timer(&vpit->pit_timer, vpit->scheduled);
-    }
-}
-
-/* pick up missed timer ticks at deactive time */
-void pickup_deactive_ticks(struct hvm_virpit *vpit)
-{
-    if ( !active_timer(&(vpit->pit_timer)) ) {
-        missed_ticks(vpit);
-        set_timer(&vpit->pit_timer, vpit->scheduled);
-    }
-}
-
-/* Only some PIT operations such as load init counter need a hypervisor hook.
- * leave all other operations in user space DM
- */
-void hvm_hooks_assist(struct vcpu *v)
-{
-    vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
-    ioreq_t *p = &vio->vp_ioreq;
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
-    int rw_mode, reinit = 0;
-
-    /* load init count*/
-    if (p->state == STATE_IORESP_HOOK) {
-        /* set up actimer, handle re-init */
-        if ( active_timer(&(vpit->pit_timer)) ) {
-            HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: guest reset PIT with channel 
%lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
-            stop_timer(&(vpit->pit_timer));
-            reinit = 1;
- 
-        }
-        else {
-            init_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor);
-        }
-
-        /* init count for this channel */
-        vpit->init_val = (p->u.data & 0xFFFF) ;
-        /* frequency(ns) of pit */
-        vpit->period = DIV_ROUND(((vpit->init_val) * 1000000000ULL), PIT_FREQ);
-        HVM_DBG_LOG(DBG_LEVEL_1,"HVM_PIT: guest set init pit freq:%u ns, 
initval:0x%x\n", vpit->period, vpit->init_val);
-        if (vpit->period < 900000) { /* < 0.9 ms */
-            printk("HVM_PIT: guest programmed too small an init_val: %x\n",
-                   vpit->init_val);
-            vpit->period = 1000000;
-        }
-         vpit->period_cycles = (u64)vpit->period * cpu_khz / 1000000L;
-         printk("HVM_PIT: guest freq in cycles=%lld\n",(long 
long)vpit->period_cycles);
-
-        vpit->channel = ((p->u.data >> 24) & 0x3);
-        vpit->first_injected = 0;
-
-        vpit->count_LSB_latched = 0;
-        vpit->count_MSB_latched = 0;
-
-        rw_mode = ((p->u.data >> 26) & 0x3);
-        switch(rw_mode) {
-        case 0x1:
-            vpit->read_state=LSByte;
-            break;
-        case 0x2:
-            vpit->read_state=MSByte;
-            break;
-        case 0x3:
-            vpit->read_state=LSByte_multiple;
-            break;
-        default:
-            printk("HVM_PIT:wrong PIT rw_mode!\n");
-            break;
-        }
-
-        vpit->scheduled = NOW() + vpit->period;
-        set_timer(&vpit->pit_timer, vpit->scheduled);
-
-        /*restore the state*/
-        p->state = STATE_IORESP_READY;
-
-        /* register handler to intercept the PIT io when vm_exit */
-        if (!reinit) {
-            register_portio_handler(0x40, 4, intercept_pit_io); 
-        }
-    }
-}
 
 /*
  * Local variables:
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/io.c     Wed Apr 19 18:38:14 2006 +0100
@@ -674,8 +674,6 @@ void hvm_io_assist(struct vcpu *v)
     }
 
     p = &vio->vp_ioreq;
-    if (p->state == STATE_IORESP_HOOK)
-        hvm_hooks_assist(v);
 
     /* clear IO wait HVM flag */
     if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c       Wed Apr 19 18:38:14 2006 +0100
@@ -46,44 +46,43 @@
 
 u64 svm_get_guest_time(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = 
&(v->domain->arch.hvm_domain.vpit.time_info);
     u64    host_tsc;
     
     rdtscll(host_tsc);
-    return host_tsc + vpit->cache_tsc_offset;
+    return host_tsc + time_info->cache_tsc_offset;
 }
 
 void svm_set_guest_time(struct vcpu *v, u64 gtime)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = 
&(v->domain->arch.hvm_domain.vpit.time_info);
     u64    host_tsc;
    
     rdtscll(host_tsc);
     
-    vpit->cache_tsc_offset = gtime - host_tsc;
-    v->arch.hvm_svm.vmcb->tsc_offset = vpit->cache_tsc_offset;
+    time_info->cache_tsc_offset = gtime - host_tsc;
+    v->arch.hvm_svm.vmcb->tsc_offset = time_info->cache_tsc_offset;
 }
 
 static inline void
 interrupt_post_injection(struct vcpu * v, int vector, int type)
 {
     struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = &vpit->time_info;
 
     if ( is_pit_irq(v, vector, type) ) {
-        if ( !vpit->first_injected ) {
-            vpit->pending_intr_nr = 0;
-            vpit->last_pit_gtime = svm_get_guest_time(v);
-            vpit->scheduled = NOW() + vpit->period;
-            set_timer(&vpit->pit_timer, vpit->scheduled);
-            vpit->first_injected = 1;
+        if ( !time_info->first_injected ) {
+            time_info->pending_intr_nr = 0;
+            time_info->last_pit_gtime = svm_get_guest_time(v);
+            time_info->first_injected = 1;
         } else {
-            vpit->pending_intr_nr--;
+            time_info->pending_intr_nr--;
         }
-        vpit->count_advance = 0;
-        vpit->count_point = NOW();
-
-        vpit->last_pit_gtime += vpit->period_cycles;
-        svm_set_guest_time(v, vpit->last_pit_gtime);
+        time_info->count_advance = 0;
+        time_info->count_point = NOW();
+
+        time_info->last_pit_gtime += time_info->period_cycles;
+        svm_set_guest_time(v, time_info->last_pit_gtime);
     }
 
     switch(type)
@@ -123,6 +122,7 @@ asmlinkage void svm_intr_assist(void)
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     struct hvm_domain *plat=&v->domain->arch.hvm_domain; 
     struct hvm_virpit *vpit = &plat->vpit;
+    struct hvm_time_info *time_info = &vpit->time_info;
     struct hvm_virpic *pic= &plat->vpic;
     int intr_type = VLAPIC_DELIV_MODE_EXT;
     int intr_vector = -1;
@@ -185,7 +185,7 @@ asmlinkage void svm_intr_assist(void)
       if ( cpu_has_pending_irq(v) ) {
            intr_vector = cpu_get_interrupt(v, &intr_type);
       }
-      else  if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) {
+      else  if ( (v->vcpu_id == 0) && time_info->pending_intr_nr ) {
           pic_set_irq(pic, 0, 0);
           pic_set_irq(pic, 0, 1);
           intr_vector = cpu_get_interrupt(v, &intr_type);
@@ -201,7 +201,7 @@ asmlinkage void svm_intr_assist(void)
             /* Re-injecting a PIT interruptt? */
             if (re_injecting && 
                 is_pit_irq(v, intr_vector, intr_type)) {
-                    ++vpit->pending_intr_nr;
+                    ++time_info->pending_intr_nr;
             }
             /* let's inject this interrupt */
             TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Wed Apr 19 18:38:14 2006 +0100
@@ -675,12 +675,12 @@ static void arch_svm_do_launch(struct vc
 
 static void svm_freeze_time(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+    struct hvm_time_info *time_info = 
&v->domain->arch.hvm_domain.vpit.time_info;
     
-    if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
+    if ( time_info->first_injected && !v->domain->arch.hvm_domain.guest_time ) 
{
         v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v);
-        vpit->count_advance += (NOW() - vpit->count_point);
-        stop_timer(&(vpit->pit_timer));
+        time_info->count_advance += (NOW() - time_info->count_point);
+        stop_timer(&(time_info->pit_timer));
     }
 }
 
@@ -750,7 +750,7 @@ static void svm_relinquish_guest_resourc
         }
     }
 
-    kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
+    kill_timer(&d->arch.hvm_domain.vpit.time_info.pit_timer);
 
     if ( d->arch.hvm_domain.shared_page_va )
         unmap_domain_page_global(
@@ -780,10 +780,10 @@ void arch_svm_do_resume(struct vcpu *v)
 
 void svm_migrate_timers(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
-
-    migrate_timer( &vpit->pit_timer, v->processor );
-    migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
+    struct hvm_time_info *time_info = 
&v->domain->arch.hvm_domain.vpit.time_info;
+
+    migrate_timer(&time_info->pit_timer, v->processor);
+    migrate_timer(&v->arch.hvm_svm.hlt_timer, v->processor);
     if ( hvm_apic_support(v->domain) && VLAPIC( v ))
         migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
 }
@@ -1843,11 +1843,11 @@ static inline void svm_do_msr_access(str
         switch (regs->ecx) {
         case MSR_IA32_TIME_STAMP_COUNTER:
         {
-            struct hvm_virpit *vpit;
+            struct hvm_time_info *time_info;
 
             rdtscll(msr_content);
-            vpit = &(v->domain->arch.hvm_domain.vpit);
-            msr_content += vpit->cache_tsc_offset;
+            time_info = &v->domain->arch.hvm_domain.vpit.time_info;
+            msr_content += time_info->cache_tsc_offset;
             break;
         }
         case MSR_IA32_SYSENTER_CS:
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Wed Apr 19 18:38:14 2006 +0100
@@ -478,14 +478,15 @@ void svm_do_resume(struct vcpu *v)
 {
     struct domain *d = v->domain;
     struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit;
+    struct hvm_time_info *time_info = &vpit->time_info;
 
     svm_stts(v);
     
     /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( vpit->first_injected ) {
+    if ( time_info->first_injected ) {
         if ( v->domain->arch.hvm_domain.guest_time ) {
             svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
-            vpit->count_point = NOW();
+            time_info->count_point = NOW();
             v->domain->arch.hvm_domain.guest_time = 0;
         }
         pickup_deactive_ticks(vpit);
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/io.c Wed Apr 19 18:38:14 2006 +0100
@@ -51,44 +51,43 @@ void __set_tsc_offset(u64  offset)
 
 u64 get_guest_time(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = 
&(v->domain->arch.hvm_domain.vpit.time_info);
     u64    host_tsc;
     
     rdtscll(host_tsc);
-    return host_tsc + vpit->cache_tsc_offset;
+    return host_tsc + time_info->cache_tsc_offset;
 }
 
 void set_guest_time(struct vcpu *v, u64 gtime)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = 
&(v->domain->arch.hvm_domain.vpit.time_info);
     u64    host_tsc;
    
     rdtscll(host_tsc);
     
-    vpit->cache_tsc_offset = gtime - host_tsc;
-    __set_tsc_offset(vpit->cache_tsc_offset);
+    time_info->cache_tsc_offset = gtime - host_tsc;
+    __set_tsc_offset(time_info->cache_tsc_offset);
 }
 
 static inline void
 interrupt_post_injection(struct vcpu * v, int vector, int type)
 {
     struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct hvm_time_info *time_info = &vpit->time_info;
 
     if ( is_pit_irq(v, vector, type) ) {
-        if ( !vpit->first_injected ) {
-            vpit->pending_intr_nr = 0;
-            vpit->last_pit_gtime = get_guest_time(v);
-            vpit->scheduled = NOW() + vpit->period;
-            set_timer(&vpit->pit_timer, vpit->scheduled);
-            vpit->first_injected = 1;
+        if ( !time_info->first_injected ) {
+            time_info->pending_intr_nr = 0;
+            time_info->last_pit_gtime = get_guest_time(v);
+            time_info->first_injected = 1;
         } else {
-            vpit->pending_intr_nr--;
+            time_info->pending_intr_nr--;
         }
-        vpit->count_advance = 0;
-        vpit->count_point = NOW();
-
-        vpit->last_pit_gtime += vpit->period_cycles;
-        set_guest_time(v, vpit->last_pit_gtime);
+        time_info->count_advance = 0;
+        time_info->count_point = NOW();
+
+        time_info->last_pit_gtime += time_info->period_cycles;
+        set_guest_time(v, time_info->last_pit_gtime);
     }
 
     switch(type)
@@ -152,13 +151,13 @@ asmlinkage void vmx_intr_assist(void)
     unsigned long eflags;
     struct vcpu *v = current;
     struct hvm_domain *plat=&v->domain->arch.hvm_domain;
-    struct hvm_virpit *vpit = &plat->vpit;
+    struct hvm_time_info *time_info = &plat->vpit.time_info;
     struct hvm_virpic *pic= &plat->vpic;
 
     if ( v->vcpu_id == 0 )
         hvm_pic_assist(v);
 
-    if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) {
+    if ( (v->vcpu_id == 0) && time_info->pending_intr_nr ) {
         pic_set_irq(pic, 0, 0);
         pic_set_irq(pic, 0, 1);
     }
@@ -203,13 +202,14 @@ void vmx_do_resume(struct vcpu *v)
 {
     struct domain *d = v->domain;
     struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+    struct hvm_time_info *time_info = &vpit->time_info;
 
     vmx_stts();
 
     /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( vpit->first_injected ) {
+    if ( time_info->first_injected ) {
         if ( v->domain->arch.hvm_domain.guest_time ) {
-            vpit->count_point = NOW();
+            time_info->count_point = NOW();
             set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
             v->domain->arch.hvm_domain.guest_time = 0;
         }
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Apr 19 18:38:14 2006 +0100
@@ -102,7 +102,7 @@ static void vmx_relinquish_guest_resourc
         }
     }
 
-    kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
+    kill_timer(&d->arch.hvm_domain.vpit.time_info.pit_timer);
 
     if ( d->arch.hvm_domain.shared_page_va )
         unmap_domain_page_global(
@@ -358,12 +358,12 @@ static inline int long_mode_do_msr_write
 
 static void vmx_freeze_time(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+    struct hvm_time_info *time_info = 
&(v->domain->arch.hvm_domain.vpit.time_info);
     
-    if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
+    if ( time_info->first_injected && !v->domain->arch.hvm_domain.guest_time ) 
{
         v->domain->arch.hvm_domain.guest_time = get_guest_time(v);
-        vpit->count_advance += (NOW() - vpit->count_point);
-        stop_timer(&(vpit->pit_timer));
+        time_info->count_advance += (NOW() - time_info->count_point);
+        stop_timer(&(time_info->pit_timer));
     }
 }
 
@@ -393,9 +393,9 @@ int vmx_initialize_guest_resources(struc
 
 void vmx_migrate_timers(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
-
-    migrate_timer(&vpit->pit_timer, v->processor);
+    struct hvm_time_info *time_info = 
&v->domain->arch.hvm_domain.vpit.time_info;
+
+    migrate_timer(&time_info->pit_timer, v->processor);
     migrate_timer(&v->arch.hvm_vmx.hlt_timer, v->processor);
     if ( hvm_apic_support(v->domain) && VLAPIC(v))
         migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor);
@@ -1836,11 +1836,11 @@ static inline void vmx_do_msr_read(struc
     switch (regs->ecx) {
     case MSR_IA32_TIME_STAMP_COUNTER:
     {
-        struct hvm_virpit *vpit;
+        struct hvm_time_info *time_info;
 
         rdtscll(msr_content);
-        vpit = &(v->domain->arch.hvm_domain.vpit);
-        msr_content += vpit->cache_tsc_offset;
+        time_info = &(v->domain->arch.hvm_domain.vpit.time_info);
+        msr_content += time_info->cache_tsc_offset;
         break;
     }
     case MSR_IA32_SYSENTER_CS:
diff -r 72f9c751d3ea -r 5765497cf75e xen/include/asm-x86/hvm/vpit.h
--- a/xen/include/asm-x86/hvm/vpit.h    Wed Apr 19 18:32:20 2006 +0100
+++ b/xen/include/asm-x86/hvm/vpit.h    Wed Apr 19 18:38:14 2006 +0100
@@ -30,47 +30,65 @@
 
 #define PIT_FREQ 1193181
 
-#define LSByte          0
-#define MSByte          1
-#define LSByte_multiple 2
-#define MSByte_multiple 3
+#define PIT_BASE 0x40
+#define HVM_PIT_ACCEL_MODE 2
 
-struct hvm_virpit {
-    /* for simulation of counter 0 in mode 2 */
+typedef struct PITChannelState {
+    int count; /* can be 65536 */
+    u16 latched_count;
+    u8 count_latched;
+    u8 status_latched;
+    u8 status;
+    u8 read_state;
+    u8 write_state;
+    u8 write_latch;
+    u8 rw_mode;
+    u8 mode;
+    u8 bcd; /* not supported */
+    u8 gate; /* timer start */
+    s64 count_load_time;
+    /* irq handling */
+    s64 next_transition_time;
+    int irq;
+    struct hvm_time_info *hvm_time;
+    u32 period; /* period(ns) based on count */
+} PITChannelState;
+
+struct hvm_time_info {
+    /* extra info for the mode 2 channel */
+    struct timer pit_timer;
+    struct vcpu *vcpu;          /* which vcpu the ac_timer bound to */
     u64 period_cycles;          /* pit frequency in cpu cycles */
     s_time_t count_advance;     /* accumulated count advance since last fire */
     s_time_t count_point;        /* last point accumulating count advance */
-    s_time_t scheduled;         /* scheduled timer interrupt */
-    struct timer pit_timer;     /* periodic timer for mode 2*/
-    unsigned int channel;       /* the pit channel, counter 0~2 */
     unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
-    u32 period;                 /* pit frequency in ns */
     int first_injected;         /* flag to prevent shadow window */
     s64 cache_tsc_offset;       /* cache of VMCS TSC_OFFSET offset */
     u64 last_pit_gtime;         /* guest time when last pit is injected */
+};
 
-    /* virtual PIT state for handle related I/O */
-    int read_state;
-    int count_LSB_latched;
-    int count_MSB_latched;
+typedef struct hvm_virpit {
+    PITChannelState channels[3];
+    struct hvm_time_info time_info;
+    int speaker_data_on;
+    int dummy_refresh_clock;
+}hvm_virpit;
 
-    unsigned int count;  /* the 16 bit channel count */
-    unsigned int init_val; /* the init value for the counter */
-};
 
 static __inline__ s_time_t get_pit_scheduled(
     struct vcpu *v,
     struct hvm_virpit *vpit)
 {
+    struct PITChannelState *s = &(vpit->channels[0]);
     if ( is_irq_enabled(v, 0) ) {
-        return vpit->scheduled;
+        return s->next_transition_time;
     }
     else
         return -1;
 }
 
 /* to hook the ioreq packet to get the PIT initialization info */
-extern void hvm_hooks_assist(struct vcpu *v);
-void pickup_deactive_ticks(struct hvm_virpit *vpit);
+extern void pit_init(struct hvm_virpit *pit, struct vcpu *v);
+extern void pickup_deactive_ticks(struct hvm_virpit *vpit);
 
 #endif /* __ASM_X86_HVM_VPIT_H__ */
diff -r 72f9c751d3ea -r 5765497cf75e xen/arch/x86/hvm/i8254.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Wed Apr 19 18:38:14 2006 +0100
@@ -0,0 +1,594 @@
+/*
+ * QEMU 8253/8254 interval timer emulation
+ * 
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2006 Intel Corperation
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/* Edwin Zhai <edwin.zhai@xxxxxxxxx>
+ * Ported to xen:
+ * use actimer for intr generation;
+ * move speaker io access to hypervisor;
+ * use new method for counter/intrs calculation
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/xmalloc.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vpit.h>
+#include <asm/current.h>
+
+/*#define DEBUG_PIT*/
+
+#define RW_STATE_LSB 1
+#define RW_STATE_MSB 2
+#define RW_STATE_WORD0 3
+#define RW_STATE_WORD1 4
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC (1000000000ULL)
+#endif
+
+#ifndef TIMER_SLOP 
+#define TIMER_SLOP (50*1000) /* ns */
+#endif
+
+static void pit_irq_timer_update(PITChannelState *s, s64 current_time);
+
+s_time_t hvm_get_clock(void)
+{
+    /* TODO: add pause/unpause support */
+    return NOW();
+}
+
+static int pit_get_count(PITChannelState *s)
+{
+    u64 d;
+    u64 counter;
+
+    d = hvm_get_clock() - s->count_load_time;
+    switch(s->mode) {
+    case 0:
+    case 1:
+    case 4:
+    case 5:
+        counter = (s->period - d) & 0xffff;
+        break;
+    case 3:
+        /* XXX: may be incorrect for odd counts */
+        counter = s->period - ((2 * d) % s->period);
+        break;
+    default:
+        /* mod 2 counter handle */
+        d = hvm_get_clock() - s->hvm_time->count_point;
+        d += s->hvm_time->count_advance;
+        counter = s->period - (d % s->period);
+        break;
+    }
+    /* change from ns to pit counter */
+    counter = DIV_ROUND( (counter * PIT_FREQ), NSEC_PER_SEC);
+    return counter;
+}
+
+/* get pit output bit */
+static int pit_get_out1(PITChannelState *s, s64 current_time)
+{
+    u64 d;
+    int out;
+
+    d = current_time - s->count_load_time;
+    switch(s->mode) {
+    default:
+    case 0:
+        out = (d >= s->period);
+        break;
+    case 1:
+        out = (d < s->period);
+        break;
+    case 2:
+        /* mod2 out is no meaning, since intr are generated in background */
+        if ((d % s->period) == 0 && d != 0)
+            out = 1;
+        else
+            out = 0;
+        break;
+    case 3:
+        out = (d % s->period) < ((s->period + 1) >> 1);
+        break;
+    case 4:
+    case 5:
+        out = (d == s->period);
+        break;
+    }
+    return out;
+}
+
+int pit_get_out(hvm_virpit *pit, int channel, s64 current_time)
+{
+    PITChannelState *s = &pit->channels[channel];
+    return pit_get_out1(s, current_time);
+}
+
+static __inline__ s64 missed_ticks(PITChannelState *s, s64 current_time)
+{
+    struct hvm_time_info *hvm_time = s->hvm_time;
+    /* ticks from current time(expected time) to NOW */ 
+    int missed_ticks;
+    /* current_time is expected time for next intr, check if it's true
+     * (actimer has a TIMER_SLOP in advance)
+     */
+    s64 missed_time = hvm_get_clock() + TIMER_SLOP - current_time;
+
+    if (missed_time >= 0) {
+        missed_ticks = missed_time/(s_time_t)s->period + 1;
+        hvm_time->pending_intr_nr += missed_ticks;
+        s->next_transition_time = current_time + (missed_ticks ) * s->period;
+    } else
+        printk("HVM_PIT:missed ticks < 0 \n");
+
+    return s->next_transition_time;
+}
+
+/* only rearm the actimer when return value > 0
+ *  -2: init state
+ *  -1: the mode has expired
+ *   0: current VCPU is not running
+ *  >0: the next fired time
+ */
+s64 pit_get_next_transition_time(PITChannelState *s, 
+                                            s64 current_time)
+{
+    s64 d, next_time, base;
+    int period2;
+    struct hvm_time_info *hvm_time = s->hvm_time;
+
+    d = current_time - s->count_load_time;
+    switch(s->mode) {
+    default:
+    case 0:
+    case 1:
+        if (d < s->period)
+            next_time = s->period;
+        else
+            return -1;
+        break;
+    case 2:
+        if (test_bit(_VCPUF_running, &(hvm_time->vcpu->vcpu_flags)) )
+            next_time = missed_ticks(s, current_time);
+        else
+            return 0;
+        break;
+    case 3:
+        base = (d / s->period) * s->period;
+        period2 = ((s->period + 1) >> 1);
+        if ((d - base) < period2) 
+            next_time = base + period2;
+        else
+            next_time = base + s->period;
+        break;
+    case 4:
+    case 5:
+        if (d < s->period)
+            next_time = s->period;
+        else if (d == s->period)
+            next_time = s->period + 1;
+        else
+            return -1;
+        break;
+    case 0xff:
+        return -2;      /* for init state */ 
+        break;
+    }
+    /* XXX: better solution: use a clock at PIT_FREQ Hz */
+    if (next_time <= current_time){
+#ifdef DEBUG_PIT
+        printk("HVM_PIT:next_time <= current_time. next=0x%llx, 
current=0x%llx!\n",next_time, current_time);
+#endif
+        next_time = current_time + 1;
+    }
+    return next_time;
+}
+
+/* val must be 0 or 1 */
+void pit_set_gate(hvm_virpit *pit, int channel, int val)
+{
+    PITChannelState *s = &pit->channels[channel];
+
+    switch(s->mode) {
+    default:
+    case 0:
+    case 4:
+        /* XXX: just disable/enable counting */
+        break;
+    case 1:
+    case 5:
+        if (s->gate < val) {
+            /* restart counting on rising edge */
+            s->count_load_time = hvm_get_clock();
+            pit_irq_timer_update(s, s->count_load_time);
+        }
+        break;
+    case 2:
+    case 3:
+        if (s->gate < val) {
+            /* restart counting on rising edge */
+            s->count_load_time = hvm_get_clock();
+            pit_irq_timer_update(s, s->count_load_time);
+        }
+        /* XXX: disable/enable counting */
+        break;
+    }
+    s->gate = val;
+}
+
+int pit_get_gate(hvm_virpit *pit, int channel)
+{
+    PITChannelState *s = &pit->channels[channel];
+    return s->gate;
+}
+
+static inline void pit_load_count(PITChannelState *s, int val)
+{
+    if (val == 0)
+        val = 0x10000;
+
+    s->count_load_time = hvm_get_clock();
+    s->count = val;
+    s->period = DIV_ROUND(((s->count) * NSEC_PER_SEC), PIT_FREQ);
+
+#ifdef DEBUG_PIT
+    printk("HVM_PIT: pit-load-counter, count=0x%x,period=0x%u us,mode=%d, 
load_time=%lld\n",
+            val,
+            s->period / 1000,
+            s->mode,
+            s->count_load_time);
+#endif
+
+    if (s->mode == HVM_PIT_ACCEL_MODE) {
+        if (!s->hvm_time) {
+            printk("HVM_PIT:guest should only set mod 2 on channel 0!\n");
+            return;
+        }
+        s->hvm_time->period_cycles = (u64)s->period * cpu_khz / 1000000L;
+        s->hvm_time->first_injected = 0;
+
+        if (s->period < 900000) { /* < 0.9 ms */
+            printk("HVM_PIT: guest programmed too small an count: %x\n",
+                    s->count);
+            s->period = 1000000;
+        }
+    }
+        
+    pit_irq_timer_update(s, s->count_load_time);
+}
+
+/* if already latched, do not latch again */
+static void pit_latch_count(PITChannelState *s)
+{
+    if (!s->count_latched) {
+        s->latched_count = pit_get_count(s);
+        s->count_latched = s->rw_mode;
+    }
+}
+
+static void pit_ioport_write(void *opaque, u32 addr, u32 val)
+{
+    hvm_virpit *pit = opaque;
+    int channel, access;
+    PITChannelState *s;
+    val &= 0xff;
+
+    addr &= 3;
+    if (addr == 3) {
+        channel = val >> 6;
+        if (channel == 3) {
+            /* read back command */
+            for(channel = 0; channel < 3; channel++) {
+                s = &pit->channels[channel];
+                if (val & (2 << channel)) {
+                    if (!(val & 0x20)) {
+                        pit_latch_count(s);
+                    }
+                    if (!(val & 0x10) && !s->status_latched) {
+                        /* status latch */
+                        /* XXX: add BCD and null count */
+                        s->status =  (pit_get_out1(s, hvm_get_clock()) << 7) |
+                            (s->rw_mode << 4) |
+                            (s->mode << 1) |
+                            s->bcd;
+                        s->status_latched = 1;
+                    }
+                }
+            }
+        } else {
+            s = &pit->channels[channel];
+            access = (val >> 4) & 3;
+            if (access == 0) {
+                pit_latch_count(s);
+            } else {
+                s->rw_mode = access;
+                s->read_state = access;
+                s->write_state = access;
+
+                s->mode = (val >> 1) & 7;
+                s->bcd = val & 1;
+                /* XXX: update irq timer ? */
+            }
+        }
+    } else {
+        s = &pit->channels[addr];
+        switch(s->write_state) {
+        default:
+        case RW_STATE_LSB:
+            pit_load_count(s, val);
+            break;
+        case RW_STATE_MSB:
+            pit_load_count(s, val << 8);
+            break;
+        case RW_STATE_WORD0:
+            s->write_latch = val;
+            s->write_state = RW_STATE_WORD1;
+            break;
+        case RW_STATE_WORD1:
+            pit_load_count(s, s->write_latch | (val << 8));
+            s->write_state = RW_STATE_WORD0;
+            break;
+        }
+    }
+}
+
+static u32 pit_ioport_read(void *opaque, u32 addr)
+{
+    hvm_virpit *pit = opaque;
+    int ret, count;
+    PITChannelState *s;
+    
+    addr &= 3;
+    s = &pit->channels[addr];
+    if (s->status_latched) {
+        s->status_latched = 0;
+        ret = s->status;
+    } else if (s->count_latched) {
+        switch(s->count_latched) {
+        default:
+        case RW_STATE_LSB:
+            ret = s->latched_count & 0xff;
+            s->count_latched = 0;
+            break;
+        case RW_STATE_MSB:
+            ret = s->latched_count >> 8;
+            s->count_latched = 0;
+            break;
+        case RW_STATE_WORD0:
+            ret = s->latched_count & 0xff;
+            s->count_latched = RW_STATE_MSB;
+            break;
+        }
+    } else {
+        switch(s->read_state) {
+        default:
+        case RW_STATE_LSB:
+            count = pit_get_count(s);
+            ret = count & 0xff;
+            break;
+        case RW_STATE_MSB:
+            count = pit_get_count(s);
+            ret = (count >> 8) & 0xff;
+            break;
+        case RW_STATE_WORD0:
+            count = pit_get_count(s);
+            ret = count & 0xff;
+            s->read_state = RW_STATE_WORD1;
+            break;
+        case RW_STATE_WORD1:
+            count = pit_get_count(s);
+            ret = (count >> 8) & 0xff;
+            s->read_state = RW_STATE_WORD0;
+            break;
+        }
+    }
+    return ret;
+}
+
+static void pit_irq_timer_update(PITChannelState *s, s64 current_time)
+{
+    s64 expire_time;
+    int irq_level;
+    struct vcpu *v = current;
+    struct hvm_virpic *pic= &v->domain->arch.hvm_domain.vpic;
+
+    if (!s->hvm_time || s->mode == 0xff)
+        return;
+
+    expire_time = pit_get_next_transition_time(s, current_time);
+    /* not generate intr by direct pic_set_irq in mod 2
+     * XXX:mod 3 should be same as mod 2
+     */
+    if (s->mode != HVM_PIT_ACCEL_MODE) {
+        irq_level = pit_get_out1(s, current_time);
+        pic_set_irq(pic, s->irq, irq_level);
+        s->next_transition_time = expire_time;
+#ifdef DEBUG_PIT
+        printk("HVM_PIT:irq_level=%d next_delay=%l ns\n",
+                irq_level, 
+                (expire_time - current_time));
+#endif
+    }
+
+    if (expire_time > 0)
+        set_timer(&(s->hvm_time->pit_timer), s->next_transition_time);
+
+}
+
+static void pit_irq_timer(void *data)
+{
+    PITChannelState *s = data;
+
+    pit_irq_timer_update(s, s->next_transition_time);
+}
+
+static void pit_reset(void *opaque)
+{
+    hvm_virpit *pit = opaque;
+    PITChannelState *s;
+    int i;
+
+    for(i = 0;i < 3; i++) {
+        s = &pit->channels[i];
+        s->mode = 0xff; /* the init mode */
+        s->gate = (i != 2);
+        pit_load_count(s, 0);
+    }
+}
+
+/* hvm_io_assist light-weight version, specific to PIT DM */ 
+static void resume_pit_io(ioreq_t *p)
+{
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    unsigned long old_eax = regs->eax;
+    p->state = STATE_INVALID;
+
+    switch(p->size) {
+    case 1:
+        regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
+        break;
+    case 2:
+        regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
+        break;
+    case 4:
+        regs->eax = (p->u.data & 0xffffffff);
+        break;
+    default:
+        BUG();
+    }
+}
+
+/* the intercept action for PIT DM retval:0--not handled; 1--handled */  
+int handle_pit_io(ioreq_t *p)
+{
+    struct vcpu *v = current;
+    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+    if (p->size != 1 ||
+        p->pdata_valid ||
+        p->type != IOREQ_TYPE_PIO){
+        printk("HVM_PIT:wrong PIT IO!\n");
+        return 1;
+    }
+    
+    if (p->dir == 0) {/* write */
+        pit_ioport_write(vpit, p->addr, p->u.data);
+    } else if (p->dir == 1) { /* read */
+        p->u.data = pit_ioport_read(vpit, p->addr);
+        resume_pit_io(p);
+    }
+
+    /* always return 1, since PIT sit in HV now */
+    return 1;
+}
+
+static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    hvm_virpit *pit = opaque;
+    val &= 0xff;
+    pit->speaker_data_on = (val >> 1) & 1;
+    pit_set_gate(pit, 2, val & 1);
+}
+
+static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
+{
+    int out;
+    hvm_virpit *pit = opaque;
+    out = pit_get_out(pit, 2, hvm_get_clock());
+    pit->dummy_refresh_clock ^= 1;
+
+    return (pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
+      (pit->dummy_refresh_clock << 4);
+}
+
+int handle_speaker_io(ioreq_t *p)
+{
+    struct vcpu *v = current;
+    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+    if (p->size != 1 ||
+        p->pdata_valid ||
+        p->type != IOREQ_TYPE_PIO){
+        printk("HVM_SPEAKER:wrong SPEAKER IO!\n");
+        return 1;
+    }
+    
+    if (p->dir == 0) {/* write */
+        speaker_ioport_write(vpit, p->addr, p->u.data);
+    } else if (p->dir == 1) {/* read */
+        p->u.data = speaker_ioport_read(vpit, p->addr);
+        resume_pit_io(p);
+    }
+
+    return 1;
+}
+
+/* pick up missed timer ticks at deactive time */
+void pickup_deactive_ticks(struct hvm_virpit *vpit)
+{
+    s64 next_time;
+    PITChannelState *s = &(vpit->channels[0]);
+    if ( !active_timer(&(vpit->time_info.pit_timer)) ) {
+        next_time = pit_get_next_transition_time(s, s->next_transition_time); 
+        if (next_time > 0)
+            set_timer(&(s->hvm_time->pit_timer), s->next_transition_time);
+        else {
+            printk("HVM_PIT:not set_timer before resume next_time=%lld!\n", 
next_time);
+            next_time = s->next_transition_time;
+        }
+    }
+}
+
+void pit_init(struct hvm_virpit *pit, struct vcpu *v)
+{
+    PITChannelState *s;
+    struct hvm_time_info *hvm_time;
+
+    s = &pit->channels[0];
+    /* the timer 0 is connected to an IRQ */
+    s->irq = 0;
+    /* channel 0 need access the related time info for intr injection */
+    hvm_time = s->hvm_time = &pit->time_info;
+    hvm_time->vcpu = v;
+
+    init_timer(&(hvm_time->pit_timer), pit_irq_timer, s, v->processor);
+
+    register_portio_handler(PIT_BASE, 4, handle_pit_io);
+
+    /* register the speaker port */
+    register_portio_handler(0x61, 1, handle_speaker_io);
+
+    pit_reset(pit);
+
+    return;
+
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.