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

[Xen-changelog] [xen-unstable] [HVM] Fix HPET timer to support 8-byte accesses, erroneous updates



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Date 1167401575 0
# Node ID a8b2738a6f7ff22022e0b49e14c3142409f8681a
# Parent  98271ea55d94cc9eebadafdac435794582b642df
[HVM] Fix HPET timer to support 8-byte accesses, erroneous updates
to read-only bits, etc.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c       |  472 +++++++++++++++---------------------------
 xen/include/asm-x86/hvm/vpt.h |   13 -
 2 files changed, 172 insertions(+), 313 deletions(-)

diff -r 98271ea55d94 -r a8b2738a6f7f xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Fri Dec 29 13:02:19 2006 +0000
+++ b/xen/arch/x86/hvm/hpet.c   Fri Dec 29 14:12:55 2006 +0000
@@ -1,6 +1,7 @@
 /*
- * hpet.c: emulating HPET in Xen
+ * hpet.c: HPET emulation for HVM guests.
  * Copyright (c) 2006, Intel Corporation.
+ * Copyright (c) 2006, Keir Fraser <keir@xxxxxxxxxxxxx>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -42,19 +43,7 @@
 #define HPET_T2_CFG     0x140
 #define HPET_T2_CMP     0x148
 #define HPET_T2_ROUTE   0x150
-#define HPET_T3_CFG     0x158 /* not supported now*/
-
-#define HPET_REV                0x01ULL
-#define HPET_NUMBER            0x200ULL /* 3 timers */
-#define HPET_COUNTER_SIZE_CAP 0x2000ULL
-#define HPET_LEG_RT_CAP       0x8000ULL
-#define HPET_VENDOR_8086  0x80860000ULL
-
-/* 64bit main counter; 3 timers supported now;
-   LegacyReplacemen Route supported.           */
-#define HPET_CAP_ID_REG \
-    (HPET_REV | HPET_NUMBER | HPET_COUNTER_SIZE_CAP | \
-     HPET_LEG_RT_CAP | HPET_VENDOR_8086)
+#define HPET_T3_CFG     0x160
 
 #define HPET_CFG_ENABLE          0x001
 #define HPET_CFG_LEGACY          0x002
@@ -65,6 +54,7 @@
 #define HPET_TN_PERIODIC_CAP     0x010
 #define HPET_TN_SETVAL           0x040
 #define HPET_TN_32BIT            0x100
+#define HPET_TN_SIZE_CAP         0x200
 #define HPET_TN_INT_ROUTE_MASK  0x3e00
 #define HPET_TN_INT_ROUTE_SHIFT      9
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
@@ -76,17 +66,12 @@
 
 #define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \
                     << HPET_TN_INT_ROUTE_CAP_SHIFT)
-
-#define HPET_TIMER_CMP32_DEFAULT 0xffffffffULL
-#define HPET_TIMER_CMP64_DEFAULT 0xffffffffffffffffULL
-#define HPET_TN_SIZE_CAP         (1 << 5)
 
 #define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)*S_TO_NS/h->tsc_freq)
 #define timer_config(h, n)       (h->hpet.timers[n].config)
 #define timer_enabled(h, n)      (timer_config(h, n) & HPET_TN_ENABLE)
 #define timer_is_periodic(h, n)  (timer_config(h, n) & HPET_TN_PERIODIC)
 #define timer_is_32bit(h, n)     (timer_config(h, n) & HPET_TN_32BIT)
-#define timer_period_cap(h, n)   (timer_config(h, n) & HPET_TN_PERIODIC_CAP)
 #define hpet_enabled(h)          (h->hpet.config & HPET_CFG_ENABLE)
 #define timer_level(h, n)        (timer_config(h, n) & HPET_TN_INT_TYPE_LEVEL)
 
@@ -97,72 +82,26 @@
     ((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
         >> HPET_TN_INT_ROUTE_CAP_SHIFT)
 
-#define hpet_time_after(a, b)   ((int32_t)(b) -(int32_t)(a) < 0)
-#define hpet_time_after64(a, b)   ((int64_t)(b) -(int64_t)(a) < 0)
-
-static inline uint32_t hpet_read32(HPETState *h, unsigned long addr)
-{
-    unsigned long p = ((unsigned long)&h->hpet) + addr;
-    return  *((uint32_t*)p);
-}
-
-static inline void hpet_write32(HPETState *h, unsigned long addr, uint32_t val)
-{
-    unsigned long p = ((unsigned long)&h->hpet) + addr;
-    *((uint32_t*)p) = val;
+#define hpet_time_after(a, b)   ((int32_t)(b) - (int32_t)(a) < 0)
+#define hpet_time_after64(a, b) ((int64_t)(b) - (int64_t)(a) < 0)
+
+static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
+{
+    uint64_t *p = (uint64_t *)(((unsigned long)&h->hpet) + addr);
+    return (addr >= HPET_T3_CFG) ? 0 : *p;
 }
 
 static int hpet_check_access_length(unsigned long addr, unsigned long len)
 {
-    if ( (len != 4) && (len != 8) )
-    {
-        gdprintk(XENLOG_ERR, "HPET: access with len=%lu\n", len);
-        goto fail;
-    }
-
-    if ( addr & (len-1) )
-    {
-        gdprintk(XENLOG_ERR, "HPET: access across register boundary\n");
-        goto fail;
+    if ( (addr & (len - 1)) || (len > 8) )
+    {
+        gdprintk(XENLOG_ERR, "HPET: access across register boundary: "
+                 "%lx %lx\n", addr, len);
+        domain_crash(current->domain);
+        return -EINVAL;
     }
 
     return 0;
-
- fail:
-    domain_crash(current->domain);
-    return -EINVAL;
-}
-
-static int hpet_check_access_offset(unsigned long addr)
-{
-    if ( addr >= HPET_T3_CFG )
-    {
-        gdprintk(XENLOG_ERR, "HPET: only 3 timers supported now\n");
-        goto fail;
-    }
-
-    if ( (addr == HPET_T0_ROUTE) || (addr == HPET_T0_ROUTE+4) ||
-         (addr == HPET_T1_ROUTE) || (addr == HPET_T1_ROUTE+4) ||
-         (addr == HPET_T2_ROUTE) || (addr == HPET_T2_ROUTE+4) )
-    {
-        gdprintk(XENLOG_ERR, "HPET: FSB interrupt route not supported now\n");
-        goto fail;
-    }
-
-    return 0;
-
- fail:
-    domain_crash(current->domain);
-    return -EINVAL;
-}
-
-static void hpet_level_triggered_interrupt_not_supported(void)
-{
-    /* It's hard to support level triggered interrupt in HPET. */
-    /* Now we haven't found any OS uses this kind of interrupt of HPET. */
-    gdprintk(XENLOG_ERR,
-             "HPET: level triggered interrupt not supported now\n");
-    domain_crash(current->domain);
 }
 
 static uint64_t hpet_update_maincounter(HPETState *h)
@@ -177,104 +116,68 @@ static unsigned long hpet_read(
     struct vcpu *v, unsigned long addr, unsigned long length)
 {
     HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
-    uint64_t mc, result;
+    unsigned long result;
+    uint64_t val;
 
     addr &= HPET_MMAP_SIZE-1;
 
     if ( hpet_check_access_length(addr, length) != 0 )
-        goto fail;
-
-    if ( length == 8 )
-    {
-        /* TODO: no OS is found to use length=8 now. 
-         * Windows 2000/XP/2003 doesn't use HPET; all of Linux 
-         * and 32bit/64bit Vista use 4-byte-length access.
-         * Besides, section 2.4.7 of HPET spec gives a note saying
-         * 64bit read may be inaccurate in some platforms. */
-        gdprintk(XENLOG_ERR, "HPET: hpet_read with len=8 not implementated\n");
-        domain_crash(v->domain);
-        goto fail;
-    }
-
-    switch ( addr )
-    {
-    case HPET_COUNTER:
-        mc = hpet_update_maincounter(h);
-        result = mc & 0xffffffffU;
-        break;
-    case HPET_COUNTER + 4:
-        mc = hpet_update_maincounter(h);
-        result = (mc >> 32);
-        break;
-    case HPET_T0_CMP:
-        result = hpet_read32(h, addr);
-        break;
-    case HPET_T0_CMP + 4:
-        result = timer_is_32bit(h, 0) ? 0 : hpet_read32(h, addr);
-        break;
-    default:
-        if ( hpet_check_access_offset(addr) != 0 )
-            goto fail;
-        result = hpet_read32(h, addr);
-        break;
-    }
+        return ~0UL;
+
+    val = hpet_read64(h, addr & ~7);
+    if ( (addr & ~7) == HPET_COUNTER )
+        val = hpet_update_maincounter(h);
+
+    result = val;
+    if ( length != 8 )
+        result = (val >> ((addr & 7) * 8)) & ((1UL << (length * 8)) - 1);
 
     return result;
-
- fail:
-    return ~0UL;
 }
 
 static void hpet_stop_timer(HPETState *h, unsigned int tn)
 {
-    ASSERT( tn < HPET_TIMER_NUM );
+    ASSERT(tn < HPET_TIMER_NUM);
     stop_timer(&h->timers[tn]);
 }
 
 static void hpet_set_timer(HPETState *h, unsigned int tn)
 {
-    uint64_t tn_cmp;
-    uint32_t cur_tick;
+    uint64_t tn_cmp, cur_tick;
 
     ASSERT(tn < HPET_TIMER_NUM);
     
     if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
         return;
 
-    switch ( tn )
-    {
-    case 0:
-        if ( !(h->hpet.config & HPET_CFG_LEGACY) )
-        {
-            gdprintk(XENLOG_INFO,
-                     "HPET: LegacyReplacementRoute not set for timer0\n");
-        }
-        else
-        {
-            /* HPET specification requires PIT shouldn't generate
-             * interrupts if LegacyReplacementRoute is set for timer0 */
-            PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit;
-            pit_stop_channel0_irq(pit);
-        }
-        if ( timer_is_32bit(h, 0) )
-            h->t0_period = hpet_tick_to_ns(h, (uint32_t)h->t0_initial_cnt);
-        else
-            h->t0_period = hpet_tick_to_ns(h, h->t0_initial_cnt);
-        h->t0_period = hpet_tick_to_ns(h, h->t0_initial_cnt);
-        set_timer(&h->timers[0], NOW() + h->t0_period);
-        break;
-    case 1:
-    case 2: /* only support 32bit timer1 & timer 2 now */
-        tn_cmp = h->hpet.timers[tn].c64 & 0xffffffffULL;
-        cur_tick = hpet_update_maincounter(h);
-        if ( tn_cmp > cur_tick )
-            set_timer(&h->timers[tn], NOW() +
-                      hpet_tick_to_ns(h, tn_cmp-cur_tick));
-        else /* handle the overflow case */
-            set_timer(&h->timers[tn], NOW() +
-                      hpet_tick_to_ns(h, 0xffffffff-cur_tick+tn_cmp));
-        break;
-    }
+    if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) )
+    {
+        /* HPET specification requires PIT shouldn't generate
+         * interrupts if LegacyReplacementRoute is set for timer0 */
+        PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit;
+        pit_stop_channel0_irq(pit);
+    }
+
+    tn_cmp   = h->hpet.timers[tn].cmp;
+    cur_tick = hpet_update_maincounter(h);
+    if ( timer_is_32bit(h, tn) )
+    {
+        tn_cmp   = (uint32_t)tn_cmp;
+        cur_tick = (uint32_t)cur_tick;
+    }
+
+    if ( (int64_t)(tn_cmp - cur_tick) > 0 )
+        set_timer(&h->timers[tn], NOW() +
+                  hpet_tick_to_ns(h, tn_cmp-cur_tick));
+    else
+        set_timer(&h->timers[tn], NOW());
+}
+
+static uint64_t hpet_fixup_reg(uint64_t new, uint64_t old, uint64_t mask)
+{
+    new &= mask;
+    new |= old & ~mask;
+    return new;
 }
 
 static void hpet_write(
@@ -282,7 +185,7 @@ static void hpet_write(
     unsigned long length, unsigned long val)
 {
     HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
-    unsigned long old_val;
+    uint64_t old_val, new_val;
     int tn, i;
 
     addr &= HPET_MMAP_SIZE-1;
@@ -290,106 +193,93 @@ static void hpet_write(
     if ( hpet_check_access_length(addr, length) != 0 )
         return;
 
-    if ( length == 8 )
-    {
-        gdprintk(XENLOG_ERR, "HPET: hpet_write with len=8 not implemented\n");
-        domain_crash(v->domain);
-        return;
-    }
-
-    switch ( addr )
-    {
-    case HPET_ID: 
-    case HPET_ID + 4: 
-        gdprintk(XENLOG_WARNING,
-                 "HPET: Capabilities and ID register is readonly\n");
-        break;
-    case HPET_CFG: 
-        old_val = h->hpet.config;
-        h->hpet.config = val;
-
-        if ( !(old_val & HPET_CFG_ENABLE) && (val & HPET_CFG_ENABLE) )
-        {
-            /* enable main counter & interrupt generating */
+    old_val = hpet_read64(h, addr & ~7);
+    if ( (addr & ~7) == HPET_COUNTER )
+        old_val = hpet_update_maincounter(h);
+
+    new_val = val;
+    if ( length != 8 )
+        new_val = hpet_fixup_reg(
+            new_val << (addr & 7) * 8, old_val,
+            ((1ULL << (length*8)) - 1) << ((addr & 7) * 8));
+
+    switch ( addr & ~7 )
+    {
+    case HPET_CFG:
+        h->hpet.config = hpet_fixup_reg(new_val, old_val, 0x3);
+
+        if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
+        {
+            /* Enable main counter and interrupt generation. */
             h->mc_offset = h->hpet.mc64 - hvm_get_guest_time(h->vcpu);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
                 hpet_set_timer(h, i); 
         }
-        else if ( (old_val & HPET_CFG_ENABLE) && !(val & HPET_CFG_ENABLE) )
-        {
-            /* halt main counter & disable interrupt generating */
+        else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
+        {
+            /* Halt main counter and disable interrupt generation. */
             h->hpet.mc64 = h->mc_offset + hvm_get_guest_time(h->vcpu);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
                 hpet_stop_timer(h, i);
         }
         break;
-    case HPET_STATUS:
-        hpet_level_triggered_interrupt_not_supported();
-        break;
+
     case HPET_COUNTER:
-    case HPET_COUNTER + 4:
         if ( hpet_enabled(h) )
             gdprintk(XENLOG_WARNING, 
                      "HPET: writing main counter but it's not halted!\n");
-        hpet_write32(h, addr, val);
-        break;
+        h->hpet.mc64 = new_val;
+        break;
+
+    case HPET_T0_CFG:
+    case HPET_T1_CFG:
+    case HPET_T2_CFG:
+        tn = (addr - HPET_T0_CFG) >> 5;
+
+        h->hpet.timers[tn].config = hpet_fixup_reg(new_val, old_val, 0x3f4e);
+
+        if ( timer_level(h, tn) )
+        {
+            gdprintk(XENLOG_ERR,
+                     "HPET: level triggered interrupt not supported now\n");
+            domain_crash(current->domain);
+            break;
+        }
+
+        if ( new_val & HPET_TN_32BIT )
+            h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp;
+
+        if ( !(old_val & HPET_TN_ENABLE) && (new_val & HPET_TN_ENABLE) )
+            hpet_set_timer(h, tn);
+        else if ( (old_val & HPET_TN_ENABLE) && !(new_val & HPET_TN_ENABLE) )
+            hpet_stop_timer(h, tn);
+        break;
+
+    case HPET_T0_CMP:
+    case HPET_T1_CMP:
+    case HPET_T2_CMP:
+        tn = (addr - HPET_T0_CMP) >> 5;
+        if ( timer_is_32bit(h, tn) )
+            new_val = (uint32_t)new_val;
+        if ( !timer_is_periodic(h, tn) ||
+             (h->hpet.timers[tn].config & HPET_TN_SETVAL) )
+            h->hpet.timers[tn].cmp = new_val;
+        else
+            h->period[tn] = new_val;
+        h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
+        if ( hpet_enabled(h) && timer_enabled(h, tn) )
+            hpet_set_timer(h, tn);
+        break;
+
+    case HPET_T0_ROUTE:
+    case HPET_T1_ROUTE:
+    case HPET_T2_ROUTE:
+        tn = (addr - HPET_T0_ROUTE) >> 5;
+        h->hpet.timers[tn].hpet_fsb[0] = new_val;
+        break;
+
     default:
-        if ( hpet_check_access_offset(addr) != 0 )
-            break;
-
-        if ( (addr < HPET_T0_CFG) || (addr >= HPET_T2_ROUTE) )
-        {
-            gdprintk(XENLOG_WARNING,
-                     "HPET: writing reserved addr=0x%lx, ignored\n", addr);
-            break;
-        }
-
-        tn = (addr - HPET_T0_CFG) / 0x20;
-        if ( (addr == HPET_T0_CMP + 0x20*tn) || 
-             (addr == HPET_T0_CMP + 0x20*tn+4) )
-        {
-            hpet_write32(h, addr, val);
-            if ( addr == HPET_T0_CMP )
-                *((uint32_t*)&(h->t0_initial_cnt)) = val;
-            else if ( addr == HPET_T0_CMP + 4 )
-                *(((uint32_t*)&(h->t0_initial_cnt))+1) = val;
-            if( hpet_enabled(h) && timer_enabled(h, tn) )
-                hpet_set_timer(h, tn);
-        }
-        else /* HPET_Tn_CFG or HPET_Tn_CFG+4 */
-        {
-            if ( addr == (HPET_T0_CFG + 0x20*tn + 4) )
-            {
-                gdprintk(XENLOG_WARNING,
-                         "HPET:  Timer%d_CFG[63..32] is readonly\n", tn);
-            }
-            else
-            {
-                old_val = timer_config(h, tn);
-                if( (old_val & HPET_TN_CFG_BITS_READONLY_OR_RESERVED) !=
-                    (val & HPET_TN_CFG_BITS_READONLY_OR_RESERVED) )
-                {
-                    gdprintk(XENLOG_ERR,
-                             "HPET: TN_CFG writing incorrect value\n");
-                    domain_crash(v->domain);
-                    break;
-                }
-                hpet_write32(h, addr, val);
-
-                if ( timer_level(h, tn) )
-                {
-                    hpet_level_triggered_interrupt_not_supported();
-                    break;
-                }
-
-                if ( !(old_val & HPET_TN_ENABLE) &&
-                     (val & HPET_TN_ENABLE) )
-                    hpet_set_timer(h, tn);
-                else if ( (old_val & HPET_TN_ENABLE) &&
-                          !(val & HPET_TN_ENABLE) )
-                    hpet_stop_timer(h, tn); 
-            }
-        }
+        /* Ignore writes to unsupported and reserved registers. */
         break;
     }
 }
@@ -402,25 +292,26 @@ static int hpet_range(struct vcpu *v, un
 
 struct hvm_mmio_handler hpet_mmio_handler = {
     .check_handler = hpet_range,
-    .read_handler = hpet_read,
+    .read_handler  = hpet_read,
     .write_handler = hpet_write
 };
-
-static void hpet_set_irq(struct domain *d, int hpet_tn)
-{
-    /* if LegacyReplacementRoute bit is set, HPET specification requires
-       timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
-       timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. */
-    int isa_irq = (hpet_tn == 0) ? 0 : 8;
-    hvm_isa_irq_deassert(d, isa_irq);
-    hvm_isa_irq_assert(d, isa_irq);
-}
 
 static void hpet_route_interrupt(HPETState *h, unsigned int tn)
 {
     unsigned int tn_int_route = timer_int_route(h, tn);
     struct domain *d = h->vcpu->domain;
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) )
+    {
+        /* if LegacyReplacementRoute bit is set, HPET specification requires
+           timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
+           timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. */
+        int isa_irq = (tn == 0) ? 0 : 8;
+        hvm_isa_irq_deassert(d, isa_irq);
+        hvm_isa_irq_assert(d, isa_irq);
+        return;
+    }
 
     if ( !(timer_int_route_cap(h, tn) & (1U << tn_int_route)) )
     {
@@ -444,45 +335,24 @@ static void hpet_timer_fn(void *opaque)
 
     if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
         return;
-    
-    if ( timer_level(h, tn) )
-    {
-        hpet_level_triggered_interrupt_not_supported();
-        return;
-    }
-
-    switch ( tn )
-    {
-        case 0:
-        case 1:
-            if ( h->hpet.config & HPET_CFG_LEGACY )
-                hpet_set_irq(h->vcpu->domain, tn);
-            else
-                hpet_route_interrupt(h, tn);
-
-            if ( (tn == 0) && timer_is_periodic(h, tn) )
-            {
-                uint64_t mc = hpet_update_maincounter(h);
-                if ( timer_is_32bit(h, 0) )
-                {
-                    while ( hpet_time_after(mc, h->hpet.timers[0].c32) )
-                        h->hpet.timers[0].c32 += h->t0_initial_cnt;
-                }
-                else
-                {
-                    while ( hpet_time_after64(mc, h->hpet.timers[0].c64) )
-                        h->hpet.timers[0].c64 += h->t0_initial_cnt;
-                }
-                set_timer(&h->timers[tn], NOW() + h->t0_period);
-            }
-            break;
-        case 2:
-            hpet_route_interrupt(h, tn);
-            break;
-        default:
-            gdprintk(XENLOG_WARNING,
-                     "HPET: timer%u is not supported now\n", tn);
-            break;
+
+    hpet_route_interrupt(h, tn);
+
+    if ( timer_is_periodic(h, tn) && (h->period[tn] != 0) )
+    {
+        uint64_t mc = hpet_update_maincounter(h);
+        if ( timer_is_32bit(h, tn) )
+        {
+            while ( hpet_time_after(mc, h->hpet.timers[tn].cmp) )
+                h->hpet.timers[tn].cmp = (uint32_t)(
+                    h->hpet.timers[tn].cmp + h->period[tn]);
+        }
+        else
+        {
+            while ( hpet_time_after64(mc, h->hpet.timers[tn].cmp) )
+                h->hpet.timers[tn].cmp += h->period[tn];
+        }
+        set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->period[tn]));
     }
 
     vcpu_kick(h->vcpu);    
@@ -506,23 +376,19 @@ void hpet_init(struct vcpu *v)
 
     h->vcpu = v;
     h->tsc_freq = ticks_per_sec(v);
-    h->hpet.capability = HPET_CAP_ID_REG;
+
+    /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
+    h->hpet.capability = 0x8086A201ULL;
 
     /* This is the number of femptoseconds per HPET tick. */
-    /* Here we define HPET's frequency as tsc's. */
+    /* Here we define HPET's frequency to be the same as the TSC's. */
     h->hpet.capability |= ((S_TO_FS/h->tsc_freq) << 32);
 
-    h->hpet.timers[0].config = HPET_TN_INT_ROUTE_CAP | 
-                        HPET_TN_SIZE_CAP | HPET_TN_PERIODIC_CAP;
-    h->hpet.timers[0].c64 = HPET_TIMER_CMP64_DEFAULT;
-
-    h->hpet.timers[1].config = HPET_TN_INT_ROUTE_CAP;
-    h->hpet.timers[1].c32 = HPET_TIMER_CMP32_DEFAULT;
-    h->hpet.timers[2].config = HPET_TN_INT_ROUTE_CAP;
-    h->hpet.timers[2].c32 = HPET_TIMER_CMP32_DEFAULT;
-
     for ( i = 0; i < HPET_TIMER_NUM; i++ )
     {
+        h->hpet.timers[i].config = 
+            HPET_TN_INT_ROUTE_CAP | HPET_TN_SIZE_CAP | HPET_TN_PERIODIC_CAP;
+        h->hpet.timers[i].cmp = ~0ULL;
         h->timer_fn_info[i].hs = h;
         h->timer_fn_info[i].tn = i;
         init_timer(&h->timers[i], hpet_timer_fn, &h->timer_fn_info[i],
diff -r 98271ea55d94 -r a8b2738a6f7f xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Fri Dec 29 13:02:19 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h     Fri Dec 29 14:12:55 2006 +0000
@@ -39,17 +39,11 @@ struct HPET {
     uint64_t res1;              /* reserved */
     uint64_t isr;               /* interrupt status reg */
     uint64_t res2[25];          /* reserved */
-    union {                     /* main counter */
-        uint64_t mc64;
-        uint32_t mc32;
-    };
+    uint64_t mc64;              /* main counter */
     uint64_t res3;              /* reserved */
     struct {                    /* timers */
         uint64_t config;        /* configuration/cap */
-        union {                 /* timer compare register */
-            uint64_t c64;
-            uint32_t c32;
-        };
+        uint64_t cmp;           /* comparator */
         uint64_t hpet_fsb[2];   /* FSB route, not supported now */
     } timers[HPET_TIMER_NUM];
 };
@@ -65,8 +59,7 @@ typedef struct HPETState {
     struct vcpu     *vcpu;
     uint64_t        tsc_freq;
     uint64_t        mc_offset;
-    uint64_t        t0_initial_cnt;
-    uint64_t        t0_period;
+    uint64_t        period[HPET_TIMER_NUM];
     struct timer timers[HPET_TIMER_NUM];
     struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM]; 
 } HPETState;

_______________________________________________
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®.