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] [HVM] vlapic: More cleanups, simplificati

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] vlapic: More cleanups, simplifications and fixes.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 14 Nov 2006 13:50:14 +0000
Delivery-date: Tue, 14 Nov 2006 05:50:05 -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 e0dc5a544ea1e84e6d3f9de916e401e06529ad72
# Parent  5b97dafc7448f645313ef244ca77a4c47bf264e1
[HVM] vlapic: More cleanups, simplifications and fixes.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c       |    2 
 xen/arch/x86/hvm/vlapic.c        |  166 +++++++++++++++++----------------------
 xen/arch/x86/hvm/vmx/io.c        |   19 ++--
 xen/arch/x86/hvm/vmx/vmx.c       |    2 
 xen/include/asm-x86/hvm/vlapic.h |   27 +++---
 5 files changed, 100 insertions(+), 116 deletions(-)

diff -r 5b97dafc7448 -r e0dc5a544ea1 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Nov 13 17:23:49 2006 -0700
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Nov 14 10:44:16 2006 +0000
@@ -990,7 +990,7 @@ static void svm_vmexit_do_cpuid(struct v
         cpuid(input, &eax, &ebx, &ecx, &edx);       
         if (input == 0x00000001 || input == 0x80000001 )
         {
-            if ( !vlapic_global_enabled(vcpu_vlapic(v)) )
+            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
             {
                 /* Since the apic is disabled, avoid any confusion 
                    about SMP cpus being available */
diff -r 5b97dafc7448 -r e0dc5a544ea1 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Mon Nov 13 17:23:49 2006 -0700
+++ b/xen/arch/x86/hvm/vlapic.c Tue Nov 14 10:44:16 2006 +0000
@@ -71,17 +71,22 @@ static unsigned int vlapic_lvt_mask[VLAP
 #define APIC_DEST_NOSHORT                0x0
 #define APIC_DEST_MASK                   0x800
 
-#define vlapic_lvt_enabled(vlapic, lvt_type)    \
+#define vlapic_lvt_enabled(vlapic, lvt_type)                    \
     (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
 
-#define vlapic_lvt_vector(vlapic, lvt_type)     \
+#define vlapic_lvt_vector(vlapic, lvt_type)                     \
     (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
 
-#define vlapic_lvt_dm(vlapic, lvt_type)           \
+#define vlapic_lvt_dm(vlapic, lvt_type)                         \
     (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
 
-#define vlapic_lvtt_period(vlapic)     \
+#define vlapic_lvtt_period(vlapic)                              \
     (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
+
+#define vlapic_base_address(vlapic)                             \
+    (vlapic->apic_base_msr & MSR_IA32_APICBASE_BASE)
+
+static int vlapic_reset(struct vlapic *vlapic);
 
 /*
  * Generic APIC bitmap vector update & search routines.
@@ -238,8 +243,7 @@ static int vlapic_match_dest(struct vcpu
         if ( dest_mode == 0 )
         {
             /* Physical mode. */
-            if ( (dest == 0xFF) || /* broadcast? */
-                 (GET_APIC_ID(vlapic_get_reg(target, APIC_ID)) == dest) )
+            if ( (dest == 0xFF) || (dest == v->vcpu_id) )
                 result = 1;
         }
         else
@@ -283,7 +287,7 @@ static int vlapic_accept_irq(struct vcpu
     case APIC_DM_FIXED:
     case APIC_DM_LOWEST:
         /* FIXME add logic for vcpu on reset */
-        if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) )
+        if ( unlikely(!vlapic_enabled(vlapic)) )
             break;
 
         if ( vlapic_test_and_set_irr(vector, vlapic) && trig_mode )
@@ -319,7 +323,7 @@ static int vlapic_accept_irq(struct vcpu
         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) )
+        if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
         {
             gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n");
             goto exit_and_crash;
@@ -371,21 +375,15 @@ struct vlapic *apic_round_robin(
 
     old = next = d->arch.hvm_domain.round_info[vector];
 
-    /* the vcpu array is arranged according to vcpu_id */
     do {
         if ( ++next == MAX_VIRT_CPUS ) 
             next = 0;
-        if ( (d->vcpu[next] == NULL) ||
-             !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) )
+        if ( (d->vcpu[next] == NULL) || !test_bit(next, &bitmap) )
             continue;
-
-        if ( test_bit(next, &bitmap) )
-        {
-            target = vcpu_vlapic(d->vcpu[next]);
-            if ( vlapic_enabled(target) )
-                break;
-            target = NULL;
-        }
+        target = vcpu_vlapic(d->vcpu[next]);
+        if ( vlapic_enabled(target) )
+            break;
+        target = NULL;
     } while ( next != old );
 
     d->arch.hvm_domain.round_info[vector] = next;
@@ -398,10 +396,9 @@ void vlapic_EOI_set(struct vlapic *vlapi
 {
     int vector = vlapic_find_highest_isr(vlapic);
 
-    /* Not every write EOI will has correpsoning ISR,
-       one example is when Kernel check timer on setup_IO_APIC */
+    /* Some EOI writes may not have a matching to an in-service interrupt. */
     if ( vector == -1 )
-        return ;
+        return;
 
     vlapic_clear_vector(vector, vlapic->regs + APIC_ISR);
 
@@ -538,7 +535,7 @@ static unsigned long vlapic_read(struct 
     unsigned int tmp;
     unsigned long result;
     struct vlapic *vlapic = vcpu_vlapic(v);
-    unsigned int offset = address - vlapic->base_address;
+    unsigned int offset = address - vlapic_base_address(vlapic);
 
     if ( offset > APIC_TDCR )
         return 0;
@@ -588,7 +585,7 @@ static void vlapic_write(struct vcpu *v,
                          unsigned long len, unsigned long val)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-    unsigned int offset = address - vlapic->base_address;
+    unsigned int offset = address - vlapic_base_address(vlapic);
 
     if ( offset != 0xb0 )
         HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
@@ -641,10 +638,6 @@ static void vlapic_write(struct vcpu *v,
 
     switch ( offset )
     {
-    case APIC_ID:   /* Local APIC ID */
-        vlapic_set_reg(vlapic, APIC_ID, val);
-        break;
-
     case APIC_TASKPRI:
         vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
         vlapic->flush_tpr_threshold = 1;
@@ -670,7 +663,7 @@ static void vlapic_write(struct vcpu *v,
             int i;
             uint32_t lvt_val;
 
-            vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
+            vlapic->disabled |= VLAPIC_SW_DISABLED;
 
             for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
             {
@@ -678,17 +671,11 @@ static void vlapic_write(struct vcpu *v,
                 vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i,
                                lvt_val | APIC_LVT_MASKED);
             }
-
-            if ( (vlapic_get_reg(vlapic, APIC_LVT0) & APIC_MODE_MASK)
-                 == APIC_DM_EXTINT )
-                clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
         }
         else
         {
-            vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK;
-            if ( (vlapic_get_reg(vlapic, APIC_LVT0) & APIC_MODE_MASK)
-                  == APIC_DM_EXTINT )
-                set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+            vlapic->disabled &= ~VLAPIC_SW_DISABLED;
+            vlapic->flush_tpr_threshold = 1;
         }
         break;
 
@@ -712,26 +699,11 @@ static void vlapic_write(struct vcpu *v,
     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 )
+        if ( vlapic_sw_disabled(vlapic) )
             val |= APIC_LVT_MASKED;
-
         val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
-
         vlapic_set_reg(vlapic, offset, val);
-
-        if ( (vlapic_vcpu(vlapic)->vcpu_id == 0) && (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);
-            else
-                clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
-        }
-    }
-    break;
+        break;
 
     case APIC_TMICT:
     {
@@ -773,10 +745,8 @@ static int vlapic_range(struct vcpu *v, 
 static int vlapic_range(struct vcpu *v, unsigned long addr)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-
-    return (vlapic_global_enabled(vlapic) &&
-            (addr >= vlapic->base_address) &&
-            (addr < vlapic->base_address + PAGE_SIZE));
+    unsigned long offset  = addr - vlapic_base_address(vlapic);
+    return (!vlapic_hw_disabled(vlapic) && (offset < PAGE_SIZE));
 }
 
 struct hvm_mmio_handler vlapic_mmio_handler = {
@@ -787,17 +757,23 @@ struct hvm_mmio_handler vlapic_mmio_hand
 
 void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
 {
+    if ( (vlapic->apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE )
+    {
+        if ( value & MSR_IA32_APICBASE_ENABLE )
+        {
+            vlapic_reset(vlapic);
+            vlapic->disabled &= ~VLAPIC_HW_DISABLED;
+        }
+        else
+        {
+            vlapic->disabled |= VLAPIC_HW_DISABLED;
+        }
+    }
+
     vlapic->apic_base_msr = value;
-    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
-        clear_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status);
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                "apic base msr is 0x%016"PRIx64", and base address is 0x%lx.",
-                vlapic->apic_base_msr, vlapic->base_address);
+                "apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr);
 }
 
 void vlapic_timer_fn(void *data)
@@ -845,8 +821,15 @@ int vlapic_accept_pic_intr(struct vcpu *
 int vlapic_accept_pic_intr(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-
-    return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
+    uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0);
+
+    /*
+     * Only CPU0 is wired to the 8259A. INTA cycles occur if LINT0 is set up
+     * accept ExtInts, or if the LAPIC is disabled (so LINT0 behaves as INTR).
+     */
+    return ((v->vcpu_id == 0) &&
+            (((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
+             vlapic_hw_disabled(vlapic)));
 }
 
 int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
@@ -854,7 +837,7 @@ int cpu_get_apic_interrupt(struct vcpu *
     struct vlapic *vlapic = vcpu_vlapic(v);
     int highest_irr;
 
-    if ( !vlapic || !vlapic_enabled(vlapic) )
+    if ( !vlapic_enabled(vlapic) )
         return -1;
 
     highest_irr = vlapic_find_highest_irr(vlapic);
@@ -886,9 +869,6 @@ void vlapic_post_injection(struct vcpu *
 void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-
-    if ( unlikely(vlapic == NULL) )
-        return;
 
     switch ( deliver_mode )
     {
@@ -920,36 +900,38 @@ void vlapic_post_injection(struct vcpu *
     }
 }
 
+/* Reset the VLPAIC back to its power-on/reset state. */
 static int vlapic_reset(struct vlapic *vlapic)
 {
     struct vcpu *v = vlapic_vcpu(vlapic);
     int i;
 
-    vlapic_set_reg(vlapic, APIC_ID, v->vcpu_id << 24);
-
+    vlapic_set_reg(vlapic, APIC_ID,  v->vcpu_id << 24);
     vlapic_set_reg(vlapic, APIC_LVR, VLAPIC_VERSION);
+
+    for ( i = 0; i < 8; i++ )
+    {
+        vlapic_set_reg(vlapic, APIC_IRR + 0x10 * i, 0);
+        vlapic_set_reg(vlapic, APIC_ISR + 0x10 * i, 0);
+        vlapic_set_reg(vlapic, APIC_TMR + 0x10 * i, 0);
+    }
+    vlapic_set_reg(vlapic, APIC_ICR,     0);
+    vlapic_set_reg(vlapic, APIC_ICR2,    0);
+    vlapic_set_reg(vlapic, APIC_LDR,     0);
+    vlapic_set_reg(vlapic, APIC_TASKPRI, 0);
+    vlapic_set_reg(vlapic, APIC_TMICT,   0);
+    vlapic_set_reg(vlapic, APIC_TMCCT,   0);
+    vlapic_set_tdcr(vlapic, 0);
+
+    vlapic_set_reg(vlapic, APIC_DFR, 0xffffffffU);
 
     for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
         vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
 
-    vlapic_set_reg(vlapic, APIC_DFR, 0xffffffffU);
-
     vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
-
-    vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
-
-    vlapic->flush_tpr_threshold = 0;
-
-    vlapic_set_tdcr(vlapic, 0);
-
-    vlapic->base_address = vlapic->apic_base_msr &
-                           MSR_IA32_APICBASE_BASE;
-
-    HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                "vcpu=%p, id=%d, vlapic_apic_base_msr=0x%016"PRIx64", "
-                "base_address=0x%0lx.",
-                v,  GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)),
-                vlapic->apic_base_msr, vlapic->base_address);
+    vlapic->disabled |= VLAPIC_SW_DISABLED;
+
+    vlapic->flush_tpr_threshold = 1;
 
     return 1;
 }
@@ -974,6 +956,7 @@ int vlapic_init(struct vcpu *v)
 
     vlapic_reset(vlapic);
 
+    vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
     if ( v->vcpu_id == 0 )
         vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
 
@@ -986,7 +969,6 @@ int vlapic_init(struct vcpu *v)
     {
         vlapic_set_reg(vlapic, APIC_LVT0, APIC_MODE_EXTINT << 8);
         vlapic_set_reg(vlapic, APIC_LVT1, APIC_MODE_NMI << 8);
-        set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
     }
 #endif
 
diff -r 5b97dafc7448 -r e0dc5a544ea1 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Mon Nov 13 17:23:49 2006 -0700
+++ b/xen/arch/x86/hvm/vmx/io.c Tue Nov 14 10:44:16 2006 +0000
@@ -69,20 +69,21 @@ static inline int is_interruptibility_st
 #ifdef __x86_64__
 static void update_tpr_threshold(struct vlapic *vlapic)
 {
-    int highest_irr, tpr;
+    int max_irr, tpr;
 
     /* Clear the work-to-do flag /then/ do the work. */
     vlapic->flush_tpr_threshold = 0;
     mb();
 
-    highest_irr = vlapic_find_highest_irr(vlapic);
+    if ( !vlapic_enabled(vlapic) || 
+         ((max_irr = vlapic_find_highest_irr(vlapic)) == -1) )
+    {
+        __vmwrite(TPR_THRESHOLD, 0);
+        return;
+    }
+
     tpr = vlapic_get_reg(vlapic, APIC_TASKPRI) & 0xF0;
-
-    if ( highest_irr == -1 )
-        __vmwrite(TPR_THRESHOLD, 0);
-    else
-        __vmwrite(TPR_THRESHOLD,
-                  (highest_irr > tpr) ? (tpr >> 4) : (highest_irr >> 4));
+    __vmwrite(TPR_THRESHOLD, (max_irr > tpr) ? (tpr >> 4) : (max_irr >> 4));
 }
 #else
 #define update_tpr_threshold(v) ((void)0)
@@ -115,7 +116,7 @@ asmlinkage void vmx_intr_assist(void)
             pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
     }
 
-    if ( vlapic_enabled(vlapic) && vlapic->flush_tpr_threshold )
+    if ( vlapic->flush_tpr_threshold )
         update_tpr_threshold(vlapic);
 
     has_ext_irq = cpu_has_pending_irq(v);
diff -r 5b97dafc7448 -r e0dc5a544ea1 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Nov 13 17:23:49 2006 -0700
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Nov 14 10:44:16 2006 +0000
@@ -853,7 +853,7 @@ static void vmx_do_cpuid(struct cpu_user
             /* Mask off reserved bits. */
             ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
 
-            if ( !vlapic_global_enabled(vcpu_vlapic(v)) )
+            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
                 clear_bit(X86_FEATURE_APIC, &edx);
     
 #if CONFIG_PAGING_LEVELS >= 3
diff -r 5b97dafc7448 -r e0dc5a544ea1 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Mon Nov 13 17:23:49 2006 -0700
+++ b/xen/include/asm-x86/hvm/vlapic.h  Tue Nov 14 10:44:16 2006 +0000
@@ -33,22 +33,23 @@
 #define VLAPIC_ID(vlapic)   \
     (GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)))
 
-#define _VLAPIC_GLOB_DISABLE            0x0
-#define VLAPIC_GLOB_DISABLE_MASK        0x1
-#define VLAPIC_SOFTWARE_DISABLE_MASK    0x2
-#define _VLAPIC_BSP_ACCEPT_PIC          0x3
-
-#define vlapic_enabled(vlapic)              \
-    (!((vlapic)->status &                   \
-       (VLAPIC_GLOB_DISABLE_MASK | VLAPIC_SOFTWARE_DISABLE_MASK)))
-
-#define vlapic_global_enabled(vlapic)       \
-    (!(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status)))
+/*
+ * APIC can be disabled in two ways:
+ *  1. 'Hardware disable': via IA32_APIC_BASE_MSR[11]
+ *     CPU should behave as if it does not have an APIC.
+ *  2. 'Software disable': via APIC_SPIV[8].
+ *     APIC is visible but does not respond to interrupt messages.
+ */
+#define VLAPIC_HW_DISABLED              0x1
+#define VLAPIC_SW_DISABLED              0x2
+#define vlapic_sw_disabled(vlapic)  ((vlapic)->disabled & VLAPIC_SW_DISABLED)
+#define vlapic_hw_disabled(vlapic)  ((vlapic)->disabled & VLAPIC_HW_DISABLED)
+#define vlapic_disabled(vlapic)     ((vlapic)->disabled)
+#define vlapic_enabled(vlapic)      (!vlapic_disabled(vlapic))
 
 struct vlapic {
-    uint32_t           status;
     uint64_t           apic_base_msr;
-    unsigned long      base_address;
+    uint32_t           disabled; /* VLAPIC_xx_DISABLED */
     uint32_t           timer_divisor;
     struct timer       vlapic_timer;
     int                timer_pending_count;

_______________________________________________
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] [HVM] vlapic: More cleanups, simplifications and fixes., Xen patchbot-unstable <=