WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [XEN] HVM: Clean up and simplify vlapic d

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] HVM: Clean up and simplify vlapic device-model code.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 30 Oct 2006 22:10:13 +0000
Delivery-date: Thu, 02 Nov 2006 13:37:12 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 7e52933a46b183fccd47bc3ac1f1e38c4f699596
# Parent  2b99c99f96e67572d33dc1117a6f402ab90d2d3d
[XEN] HVM: Clean up and simplify vlapic device-model code.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/vlapic.c        |  485 ++++++++++++++++++---------------------
 xen/include/asm-x86/hvm/vlapic.h |  119 +--------
 2 files changed, 249 insertions(+), 355 deletions(-)

diff -r 2b99c99f96e6 -r 7e52933a46b1 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Mon Oct 30 10:42:27 2006 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Mon Oct 30 13:53:09 2006 +0000
@@ -29,19 +29,28 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/io.h>
 #include <asm/hvm/support.h>
-
 #include <xen/lib.h>
 #include <xen/sched.h>
 #include <asm/current.h>
 #include <public/hvm/ioreq.h>
 #include <public/hvm/params.h>
 
+#define VLAPIC_VERSION                  0x00050014
+#define VLAPIC_LVT_NUM                  6
+
 /* XXX remove this definition after GFW enabled */
 #define VLAPIC_NO_BIOS
 
 extern u32 get_apic_bus_cycle(void);
 
 #define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
+
+#define LVT_MASK \
+    APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
+
+#define LINT_MASK   \
+    LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
+    APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
 
 static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
 {
@@ -57,9 +66,70 @@ static unsigned int vlapic_lvt_mask[VLAP
      LVT_MASK
 };
 
-int hvm_apic_support(struct domain *d)
-{
-    return d->arch.hvm_domain.params[HVM_PARAM_APIC_ENABLED];
+/* Following could belong in apicdef.h */
+#define APIC_SHORT_MASK                  0xc0000
+#define APIC_DEST_NOSHORT                0x0
+#define APIC_DEST_MASK                   0x800
+
+#define vlapic_lvt_enabled(vlapic, lvt_type)    \
+    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
+
+#define vlapic_lvt_vector(vlapic, lvt_type)     \
+    (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
+
+#define vlapic_lvt_dm(vlapic, lvt_type)           \
+    (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
+
+#define vlapic_lvtt_period(vlapic)     \
+    (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
+
+/*
+ * Generic APIC bitmap vector update & search routines.
+ */
+
+#define VEC_POS(v) ((v)%32)
+#define REG_POS(v) (((v)/32)* 0x10)
+#define vlapic_test_and_set_vector(vec, bitmap)                 \
+    test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
+#define vlapic_test_and_clear_vector(vec, bitmap)               \
+    test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
+#define vlapic_set_vector(vec, bitmap)                          \
+    set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
+#define vlapic_clear_vector(vec, bitmap)                        \
+    clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
+
+static int vlapic_find_highest_vector(u32 *bitmap)
+{
+    int word_offset = MAX_VECTOR / 32;
+
+    /* Work backwards through the bitmap (first 32-bit word in every four). */
+    while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) )
+        continue;
+
+    return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32);
+}
+
+
+/*
+ * IRR-specific bitmap update & search routines.
+ */
+
+static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
+{
+    vlapic->flush_tpr_threshold = 1;
+    return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
+}
+
+static void vlapic_set_irr(int vector, struct vlapic *vlapic)
+{
+    vlapic->flush_tpr_threshold = 1;
+    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
+}
+
+static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
+{
+    vlapic->flush_tpr_threshold = 1;
+    vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
 }
 
 int vlapic_find_highest_irr(struct vlapic *vlapic)
@@ -70,6 +140,24 @@ int vlapic_find_highest_irr(struct vlapi
     ASSERT((result == -1) || (result >= 16));
 
     return result;
+}
+
+
+int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
+{
+    int ret;
+
+    ret = vlapic_test_and_set_irr(vec, vlapic);
+    if ( trig )
+        vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
+
+    /* We may need to wake up target vcpu, besides set pending bit here */
+    return ret;
+}
+
+int hvm_apic_support(struct domain *d)
+{
+    return d->arch.hvm_domain.params[HVM_PARAM_APIC_ENABLED];
 }
 
 s_time_t get_apictime_scheduled(struct vcpu *v)
@@ -139,11 +227,13 @@ static int vlapic_match_dest(struct vcpu
           (delivery_mode != APIC_DM_NMI)) )
     {
         HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "uninitialized target vcpu %p, "
-                    "delivery_mode 0x%x, dest 0x%x.\n", v, delivery_mode, 
dest);
+                    "delivery_mode 0x%x, dest 0x%x.\n",
+                    v, delivery_mode, dest);
         return result;
     }
 
-    switch ( short_hand ) {
+    switch ( short_hand )
+    {
     case APIC_DEST_NOSHORT:             /* no shorthand */
         if ( !dest_mode )   /* Physical */
         {
@@ -159,7 +249,7 @@ static int vlapic_match_dest(struct vcpu
             ldr = vlapic_get_reg(target, APIC_LDR);
             
             /* Flat mode */
-            if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT)
+            if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT )
             {
                 result = GET_APIC_LOGICAL_ID(ldr) & dest;
             }
@@ -173,8 +263,8 @@ static int vlapic_match_dest(struct vcpu
                            "delivery mode\n");
                     domain_crash_synchronous();
                 }
-                result = (GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
-                         (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0;
+                result = ((GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
+                          (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0);
             }
         }
         break;
@@ -220,14 +310,14 @@ static int vlapic_accept_irq(struct vcpu
         if ( vlapic_test_and_set_irr(vector, vlapic) && trig_mode )
         {
             HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                  "level trig mode repeatedly for vector %d\n", vector);
+                        "level trig mode repeatedly for vector %d\n", vector);
             break;
         }
 
         if ( trig_mode )
         {
             HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-              "level trig mode for vector %d\n", vector);
+                        "level trig mode for vector %d\n", vector);
             vlapic_set_vector(vector, vlapic->regs + APIC_TMR);
         }
 
@@ -247,29 +337,27 @@ static int vlapic_accept_irq(struct vcpu
         break;
 
     case APIC_DM_INIT:
-        if ( trig_mode && !(level & APIC_INT_ASSERT) )     //Deassert
-            printk("This hvm_vlapic is for P4, no work for De-assert init\n");
-        else
-        {
-            /* FIXME How to check the situation after vcpu reset? */
-            if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) )
-            {
-                printk("Reset hvm vcpu not supported yet\n");
-                domain_crash_synchronous();
-            }
-            v->arch.hvm_vcpu.init_sipi_sipi_state =
-                HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
-            result = 1;
-        }
+        /* No work on INIT de-assert for P4-type APIC. */
+        if ( trig_mode && !(level & APIC_INT_ASSERT) )
+            break;
+        /* FIXME How to check the situation after vcpu reset? */
+        if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) )
+        {
+            gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n");
+            domain_crash_synchronous();
+        }
+        v->arch.hvm_vcpu.init_sipi_sipi_state =
+            HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
+        result = 1;
         break;
 
     case APIC_DM_STARTUP:
         if ( v->arch.hvm_vcpu.init_sipi_sipi_state ==
-                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
+             HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
             break;
 
         v->arch.hvm_vcpu.init_sipi_sipi_state =
-                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM;
+            HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM;
 
         if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
         {
@@ -302,7 +390,7 @@ struct vlapic *apic_round_robin(struct d
     int next, old;
     struct vlapic* target = NULL;
 
-    if ( dest_mode == 0 )   //Physical mode
+    if ( dest_mode == 0 ) /* Physical mode */
     {
         printk("<apic_round_robin> lowest priority for physical mode.\n");
         return NULL;
@@ -360,21 +448,6 @@ void vlapic_EOI_set(struct vlapic *vlapi
 
     if ( vlapic_test_and_clear_vector(vector, vlapic->regs + APIC_TMR) )
         ioapic_update_EOI(vlapic->domain, vector);
-}
-
-static int vlapic_check_vector(struct vlapic *vlapic,
-                        uint32_t dm, uint32_t vector)
-{
-    if ( (dm == APIC_DM_FIXED) && (vector < 16) )
-    {
-        vlapic->err_status |= 0x40;
-        vlapic_accept_irq(vlapic->vcpu, APIC_DM_FIXED,
-                          vlapic_lvt_vector(vlapic, APIC_LVTERR), 0, 0);
-        printk("<vlapic_check_vector>: check failed "
-               " dm %x vector %x\n", dm, vector);
-        return 0;
-    }
-    return 1;
 }
 
 static void vlapic_ipi(struct vlapic *vlapic)
@@ -450,7 +523,7 @@ static uint32_t vlapic_get_tmcct(struct 
         if ( unlikely(!vlapic_lvtt_period(vlapic)) )
         {
             tmcct =  0;
-            // FIXME: should we add interrupt here?
+            /* FIXME: should we add interrupt here? */
         }
         else
         {
@@ -490,13 +563,8 @@ static void vlapic_read_aligned(struct v
         printk("access local APIC ARBPRI register which is for P6\n");
         break;
 
-    case APIC_TMCCT:        //Timer CCR
+    case APIC_TMCCT: /* Timer CCR */
         *result = vlapic_get_tmcct(vlapic);
-        break;
-
-    case APIC_ESR:
-        vlapic->err_write_count = 0;
-        *result = vlapic_get_reg(vlapic, offset);
         break;
 
     default:
@@ -565,31 +633,31 @@ static void vlapic_write(struct vcpu *v,
                     offset, len, val);
 
     /*
-     * According to IA 32 Manual, all resgiters should be accessed with
-     * 32 bits alignment.
+     * According to the IA32 Manual, all accesses should be 32 bits.
+     * Some OSes do 8- or 16-byte accesses, however.
      */
     if ( len != 4 )
     {
         unsigned int tmp;
         unsigned char alignment;
 
-        /* Some kernels do will access with byte/word alignment */
-        printk("Notice: Local APIC write with len = %lx\n",len);
+        gdprintk(XENLOG_INFO, "Notice: Local APIC write with len = %lx\n",len);
+
         alignment = offset & 0x3;
         tmp = vlapic_read(v, offset & ~0x3, 4);
-        switch ( len ) {
+
+        switch ( len )
+        {
         case 1:
-            /* XXX the saddr is a tmp variable from caller, so should be ok
-               But we should still change the following ref to val to
-               local variable later */
             val = (tmp & ~(0xff << (8*alignment))) |
                   ((val & 0xff) << (8*alignment));
             break;
 
         case 2:
-            if ( alignment != 0x0 && alignment != 0x2 )
+            if ( alignment & 1 )
             {
-                printk("alignment error for vlapic with len == 2\n");
+                gdprintk(XENLOG_ERR, "Uneven alignment error for "
+                         "2-byte vlapic access\n");
                 domain_crash_synchronous();
             }
 
@@ -597,22 +665,18 @@ static void vlapic_write(struct vcpu *v,
                   ((val & 0xffff) << (8*alignment));
             break;
 
-        case 3:
-            /* will it happen? */
-            printk("vlapic_write with len = 3 !!!\n");
+        default:
+            gdprintk(XENLOG_ERR, "Local APIC write with len = %lx, "
+                     "should be 4 instead\n", len);
             domain_crash_synchronous();
             break;
-
-        default:
-            printk("Local APIC write with len = %lx, should be 4 instead\n", 
len);
-            domain_crash_synchronous();
-            break;
         }
     }
 
     offset &= 0xff0;
 
-    switch ( offset ) {
+    switch ( offset )
+    {
     case APIC_ID:   /* Local APIC ID */
         vlapic_set_reg(vlapic, APIC_ID, val);
         break;
@@ -638,7 +702,7 @@ static void vlapic_write(struct vcpu *v,
     case APIC_SPIV:
         vlapic_set_reg(vlapic, APIC_SPIV, val & 0x3ff);
 
-        if ( !( val & APIC_SPIV_APIC_ENABLED) )
+        if ( !(val & APIC_SPIV_APIC_ENABLED) )
         {
             int i;
             uint32_t lvt_val;
@@ -666,9 +730,7 @@ static void vlapic_write(struct vcpu *v,
         break;
 
     case APIC_ESR:
-        vlapic->err_write_count = !vlapic->err_write_count;
-        if ( !vlapic->err_write_count )
-            vlapic->err_status = 0;
+        /* Nothing to do. */
         break;
 
     case APIC_ICR:
@@ -681,78 +743,72 @@ static void vlapic_write(struct vcpu *v,
         vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000);
         break;
 
-    case APIC_LVTT:         // LVT Timer Reg
-    case APIC_LVTTHMR:      // LVT Thermal Monitor
-    case APIC_LVTPC:        // LVT Performance Counter
-    case APIC_LVT0:         // LVT LINT0 Reg
-    case APIC_LVT1:         // LVT Lint1 Reg
-    case APIC_LVTERR:       // LVT Error Reg
-        {
-            if ( vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK )
-                val |= APIC_LVT_MASKED;
-
-            val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
-
-            vlapic_set_reg(vlapic, offset, val);
-
-            /* On hardware, when write vector less than 0x20 will error */
-            if ( !(val & APIC_LVT_MASKED) )
-                vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic, offset),
-                                    vlapic_lvt_vector(vlapic, offset));
-
-            if ( !vlapic->vcpu_id && (offset == APIC_LVT0) )
-            {
-                if ( (val & APIC_MODE_MASK) == APIC_DM_EXTINT )
-                    if ( val & APIC_LVT_MASKED)
-                        clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
-                    else
-                        set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+    case APIC_LVTT:         /* LVT Timer Reg */
+    case APIC_LVTTHMR:      /* LVT Thermal Monitor */
+    case APIC_LVTPC:        /* LVT Performance Counter */
+    case APIC_LVT0:         /* LVT LINT0 Reg */
+    case APIC_LVT1:         /* LVT Lint1 Reg */
+    case APIC_LVTERR:       /* LVT Error Reg */
+    {
+        if ( vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK )
+            val |= APIC_LVT_MASKED;
+
+        val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
+
+        vlapic_set_reg(vlapic, offset, val);
+
+        if ( !vlapic->vcpu->vcpu_id && (offset == APIC_LVT0) )
+        {
+            if ( (val & APIC_MODE_MASK) == APIC_DM_EXTINT )
+                if ( val & APIC_LVT_MASKED)
+                    clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
                 else
-                    clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
-            }
-
-        }
-        break;
+                    set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+            else
+                clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+        }
+    }
+    break;
 
     case APIC_TMICT:
-        {
-            s_time_t now = NOW(), offset;
-
-            stop_timer(&vlapic->vlapic_timer);
-
-            vlapic_set_reg(vlapic, APIC_TMICT, val);
-            vlapic_set_reg(vlapic, APIC_TMCCT, val);
-            vlapic->timer_last_update = now;
-
-            offset = APIC_BUS_CYCLE_NS *
-                     vlapic->timer_divide_count * val;
-
-            set_timer(&vlapic->vlapic_timer, now + offset);
-
-            HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                        "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
-                        "timer initial count 0x%x, offset 0x%016"PRIx64", "
-                        "expire @ 0x%016"PRIx64".",
-                        APIC_BUS_CYCLE_NS, now,
-                        vlapic_get_reg(vlapic, APIC_TMICT),
-                        offset, now + offset);
-        }
-        break;
+    {
+        s_time_t now = NOW(), offset;
+
+        stop_timer(&vlapic->vlapic_timer);
+
+        vlapic_set_reg(vlapic, APIC_TMICT, val);
+        vlapic_set_reg(vlapic, APIC_TMCCT, val);
+        vlapic->timer_last_update = now;
+
+        offset = APIC_BUS_CYCLE_NS *
+            vlapic->timer_divide_count * val;
+
+        set_timer(&vlapic->vlapic_timer, now + offset);
+
+        HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
+                    "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
+                    "timer initial count 0x%x, offset 0x%016"PRIx64", "
+                    "expire @ 0x%016"PRIx64".",
+                    APIC_BUS_CYCLE_NS, now,
+                    vlapic_get_reg(vlapic, APIC_TMICT),
+                    offset, now + offset);
+    }
+    break;
 
     case APIC_TDCR:
-        {
-            unsigned int tmp1, tmp2;
-
-            tmp1 = val & 0xf;
-            tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
-            vlapic->timer_divide_count = 0x1 << (tmp2 & 0x7);
-
-            vlapic_set_reg(vlapic, APIC_TDCR, val);
-
-            HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divide count is 0x%x",
-                        vlapic->timer_divide_count);
-        }
-        break;
+    {
+        unsigned int tmp1, tmp2;
+
+        tmp1 = val & 0xf;
+        tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
+        vlapic->timer_divide_count = 0x1 << (tmp2 & 0x7);
+
+        vlapic_set_reg(vlapic, APIC_TDCR, val);
+
+        HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divide count is 0x%x",
+                    vlapic->timer_divide_count);
+    }
+    break;
 
     default:
         printk("Local APIC Write to read-only register\n");
@@ -764,12 +820,9 @@ static int vlapic_range(struct vcpu *v, 
 {
     struct vlapic *vlapic = VLAPIC(v);
 
-    if ( vlapic_global_enabled(vlapic) &&
-         (addr >= vlapic->base_address) &&
-         (addr < vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) )
-        return 1;
-
-    return 0;
+    return (vlapic_global_enabled(vlapic) &&
+            (addr >= vlapic->base_address) &&
+            (addr < vlapic->base_address + PAGE_SIZE));
 }
 
 struct hvm_mmio_handler vlapic_mmio_handler = {
@@ -780,18 +833,15 @@ struct hvm_mmio_handler vlapic_mmio_hand
 
 void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
 {
-    /* When apic disabled */
     if ( vlapic == NULL )
         return;
 
-    if ( vlapic->vcpu_id )
+    if ( vlapic->vcpu->vcpu_id )
         value &= ~MSR_IA32_APICBASE_BSP;
 
     vlapic->apic_base_msr = value;
-    vlapic->base_address = vlapic->apic_base_msr &
-                           MSR_IA32_APICBASE_BASE;
-
-    /* with FSB delivery interrupt, we can restart APIC functionality */
+    vlapic->base_address  = vlapic->apic_base_msr & MSR_IA32_APICBASE_BASE;
+
     if ( !(value & MSR_IA32_APICBASE_ENABLE) )
         set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
     else
@@ -820,7 +870,7 @@ void vlapic_timer_fn(void *data)
     vlapic->timer_last_update = now;
 
     if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
-        vlapic->intr_pending_count[timer_vector]++;
+        vlapic->timer_pending_count++;
 
     if ( vlapic_lvtt_period(vlapic) )
     {
@@ -836,13 +886,6 @@ void vlapic_timer_fn(void *data)
     }
     else
         vlapic_set_reg(vlapic, APIC_TMCCT, 0);
-
-#if 0
-    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
-    {
-        /* TODO: add guest time handling here */
-    }
-#endif
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
                 "now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
@@ -852,86 +895,43 @@ void vlapic_timer_fn(void *data)
                 vlapic_get_reg(vlapic, APIC_TMCCT));
 }
 
-#if 0
-static int
-vlapic_check_direct_intr(struct vcpu *v, int * mode)
+int vlapic_accept_pic_intr(struct vcpu *v)
 {
     struct vlapic *vlapic = VLAPIC(v);
-    int type;
-
-    type = fls(vlapic->direct_intr.deliver_mode) - 1;
-    if ( type == -1 )
+
+    return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
+}
+
+int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+    int highest_irr;
+
+    if ( !vlapic || !vlapic_enabled(vlapic) )
         return -1;
 
-    *mode = type;
-    return 0;
-}
-#endif
-
-int vlapic_accept_pic_intr(struct vcpu *v)
-{
-    struct vlapic *vlapic = VLAPIC(v);
-
-    return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
-}
-
-int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
-{
-    struct vlapic *vlapic = VLAPIC(v);
-
-    if ( vlapic && vlapic_enabled(vlapic) )
-    {
-        int highest_irr = vlapic_find_highest_irr(vlapic);
-
-        if ( highest_irr != -1 &&
-             ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) )
-        {
-            if ( highest_irr < 0x10 )
-            {
-                uint32_t err_vector;
-
-                vlapic->err_status |= 0x20;
-                err_vector = vlapic_lvt_vector(vlapic, APIC_LVTERR);
-
-                HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                            "Sending an illegal vector 0x%x.", highest_irr);
-
-                vlapic_set_irr(err_vector, vlapic);
-                highest_irr = err_vector;
-            }
-
-            *mode = APIC_DM_FIXED;
-            return highest_irr;
-        }
-    }
-    return -1;
-}
-
-int cpu_has_apic_interrupt(struct vcpu* v)
-{
-    struct vlapic *vlapic = VLAPIC(v);
-
-    if (vlapic && vlapic_enabled(vlapic)) {
-        int highest_irr = vlapic_find_highest_irr(vlapic);
-
-        if ( highest_irr != -1 &&
-             ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) ) 
{
-            return 1;
-        }
-    }
-    return 0;
+    highest_irr = vlapic_find_highest_irr(vlapic);
+    if ( (highest_irr == -1) ||
+         ((highest_irr & 0xF0) <= vlapic_get_reg(vlapic, APIC_PROCPRI)) )
+        return -1;
+
+    *mode = APIC_DM_FIXED;
+    return highest_irr;
 }
 
 /* check to see if there is pending interrupt  */
 int cpu_has_pending_irq(struct vcpu *v)
 {
     struct hvm_domain *plat = &v->domain->arch.hvm_domain;
+    int dummy;
 
     /* APIC */
-    if ( cpu_has_apic_interrupt(v) ) return 1;
-    
+    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
+        return 1;
+
     /* PIC */
-    if ( !vlapic_accept_pic_intr(v) ) return 0;
+    if ( !vlapic_accept_pic_intr(v) )
+        return 0;
 
     return plat->interrupt_request;
 }
@@ -943,20 +943,18 @@ void vlapic_post_injection(struct vcpu *
     if ( unlikely(vlapic == NULL) )
         return;
 
-    switch ( deliver_mode ) {
+    switch ( deliver_mode )
+    {
     case APIC_DM_FIXED:
     case APIC_DM_LOWEST:
         vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
         vlapic_clear_irr(vector, vlapic);
         vlapic_update_ppr(vlapic);
-
-        if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) )
-        {
-            if ( vlapic->intr_pending_count[vector] > 0 )
-            {
-                vlapic->intr_pending_count[vector]--;
-                vlapic_set_irr(vector, vlapic);
-            }
+        if ( (vector == vlapic_lvt_vector(vlapic, APIC_LVTT)) &&
+             (vlapic->timer_pending_count != 0) )
+        {
+            vlapic->timer_pending_count--;
+            vlapic_set_irr(vector, vlapic);
         }
         break;
 
@@ -969,7 +967,6 @@ void vlapic_post_injection(struct vcpu *
     case APIC_DM_NMI:
     case APIC_DM_INIT:
     case APIC_DM_STARTUP:
-        vlapic->direct_intr.deliver_mode &= (1 << (deliver_mode >> 8));
         break;
 
     default:
@@ -980,18 +977,10 @@ void vlapic_post_injection(struct vcpu *
 
 static int vlapic_reset(struct vlapic *vlapic)
 {
-    struct vcpu *v;
+    struct vcpu *v = vlapic->vcpu;
     int i;
 
-    ASSERT( vlapic != NULL );
-
-    v = vlapic->vcpu;
-
-    ASSERT( v != NULL );
-
     vlapic->domain = v->domain;
-
-    vlapic->vcpu_id = v->vcpu_id;
 
     vlapic_set_reg(vlapic, APIC_ID, v->vcpu_id << 24);
 
@@ -1045,8 +1034,6 @@ int vlapic_init(struct vcpu *v)
 {
     struct vlapic *vlapic = NULL;
 
-    ASSERT( v != NULL );
-
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
 
     vlapic = xmalloc_bytes(sizeof(struct vlapic));
@@ -1067,11 +1054,9 @@ int vlapic_init(struct vcpu *v)
     }
 
     vlapic->regs = map_domain_page_global(page_to_mfn(vlapic->regs_page));
-
     memset(vlapic->regs, 0, PAGE_SIZE);
 
     VLAPIC(v) = vlapic;
-
     vlapic->vcpu = v;
 
     vlapic_reset(vlapic);
diff -r 2b99c99f96e6 -r 7e52933a46b1 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 30 10:42:27 2006 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 30 13:53:09 2006 +0000
@@ -25,55 +25,10 @@
 
 #define MAX_VECTOR      256
 
-#define VEC_POS(v) ((v)%32)
-#define REG_POS(v) (((v)/32)* 0x10)
-#define vlapic_test_and_set_vector(vec, bitmap)                 \
-    test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
-#define vlapic_test_and_clear_vector(vec, bitmap)               \
-    test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
-#define vlapic_set_vector(vec, bitmap)                          \
-    set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
-#define vlapic_clear_vector(vec, bitmap)                        \
-    clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
-
-static inline int vlapic_find_highest_vector(u32 *bitmap)
-{
-    int word_offset = MAX_VECTOR / 32;
-
-    /* Work backwards through the bitmap (first 32-bit word in every four). */
-    while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) )
-        continue;
-
-    return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32);
-}
-
 #define VLAPIC(v)                       (v->arch.hvm_vcpu.vlapic)
-
-#define VLAPIC_VERSION                  0x00050014
-
-#define VLOCAL_APIC_MEM_LENGTH          (1 << 12)
-
-#define VLAPIC_LVT_NUM                  6
 
 #define VLAPIC_ID(vlapic)   \
     (GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)))
-
-/* followed define is not in apicdef.h */
-#define APIC_SHORT_MASK                  0xc0000
-#define APIC_DEST_NOSHORT                0x0
-#define APIC_DEST_MASK                  0x800
-
-#define vlapic_lvt_enabled(vlapic, lvt_type)    \
-    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
-
-#define vlapic_lvt_vector(vlapic, lvt_type)     \
-    (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
-
-#define vlapic_lvt_dm(vlapic, lvt_type)           \
-    (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
-
-#define vlapic_lvtt_period(vlapic)     \
-    (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
 
 #define _VLAPIC_GLOB_DISABLE            0x0
 #define VLAPIC_GLOB_DISABLE_MASK        0x1
@@ -87,96 +42,50 @@ static inline int vlapic_find_highest_ve
 #define vlapic_global_enabled(vlapic)       \
     (!(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status)))
 
-#define LVT_MASK \
-    APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
-
-#define LINT_MASK   \
-    LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
-    APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
-
-typedef struct direct_intr_info {
-    int deliver_mode;
-    int source[6];
-} direct_intr_info_t;
-
 struct vlapic {
     uint32_t           status;
-    uint32_t           vcpu_id;
     uint64_t           apic_base_msr;
     unsigned long      base_address;
     uint32_t           timer_divide_count;
     struct timer       vlapic_timer;
-    int                intr_pending_count[MAX_VECTOR];
+    int                timer_pending_count;
     int                flush_tpr_threshold;
     s_time_t           timer_last_update;
-    direct_intr_info_t direct_intr;
-    uint32_t           err_status;
-    uint32_t           err_write_count;
     struct vcpu        *vcpu;
     struct domain      *domain;
     struct page_info   *regs_page;
     void               *regs;
 };
 
-static inline int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
+static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
 {
-    vlapic->flush_tpr_threshold = 1;
-    return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
+    return *((uint32_t *)(vlapic->regs + reg));
 }
 
-static inline void vlapic_set_irr(int vector, struct vlapic *vlapic)
-{
-    vlapic->flush_tpr_threshold = 1;
-    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
-}
-
-static inline void vlapic_clear_irr(int vector, struct vlapic *vlapic)
-{
-    vlapic->flush_tpr_threshold = 1;
-    vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
-}
-
-static inline int vlapic_set_irq(struct vlapic *vlapic,
-                                 uint8_t vec, uint8_t trig)
-{
-    int ret;
-
-    ret = vlapic_test_and_set_irr(vec, vlapic);
-    if ( trig )
-        vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
-
-    /* We may need to wake up target vcpu, besides set pending bit here */
-    return ret;
-}
-
-static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
-{
-    return  *( (uint32_t *)(vlapic->regs + reg));
-}
-
-static inline void vlapic_set_reg(struct vlapic *vlapic,
-  uint32_t reg, uint32_t val)
+static inline void vlapic_set_reg(
+    struct vlapic *vlapic, uint32_t reg, uint32_t val)
 {
     *((uint32_t *)(vlapic->regs + reg)) = val;
 }
 
 
-void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
+int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
 
-extern int vlapic_find_highest_irr(struct vlapic *vlapic);
+void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode);
 
-int cpu_has_apic_interrupt(struct vcpu* v);
-int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
+int vlapic_find_highest_irr(struct vlapic *vlapic);
 
-extern int vlapic_init(struct vcpu *vc);
+int cpu_get_apic_interrupt(struct vcpu *v, int *mode);
 
-extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+int vlapic_init(struct vcpu *vc);
 
-extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
+void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+
+uint32_t vlapic_update_ppr(struct vlapic *vlapic);
 
 int vlapic_accept_pic_intr(struct vcpu *v);
 
-struct vlapic* apic_round_robin(struct domain *d,
+struct vlapic *apic_round_robin(struct domain *d,
                                 uint8_t dest_mode,
                                 uint8_t vector,
                                 uint32_t bitmap);

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] HVM: Clean up and simplify vlapic device-model code., Xen patchbot-unstable <=