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

[Xen-changelog] [xen-unstable] [XEN] HVM: Clean up and simplify vlapic device-model code.



# 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


 


Rackspace

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