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

[Xen-changelog] [xen-unstable] [HVM][VMX] Enable VMX TPR shadow feature.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 2b99c99f96e67572d33dc1117a6f402ab90d2d3d
# Parent  c33272c2571c7bab7056d8228490700d1df405f9
[HVM][VMX] Enable VMX TPR shadow feature.

x64 Windows uses CR8 to access TPR very frequently. This patch enables
TPR shadow and allows mov-from/to-CR8 to access it directly; tests
indicates it can boost greatly the performance of x64 Windows 2003.

Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/x86/hvm/vlapic.c        |   19 +++++++++++++------
 xen/arch/x86/hvm/vmx/io.c        |   25 +++++++++++++++++++++++++
 xen/arch/x86/hvm/vmx/vmcs.c      |   23 +++++++++++++++--------
 xen/arch/x86/hvm/vmx/vmx.c       |    5 +++++
 xen/include/asm-x86/hvm/vlapic.h |   25 ++++++++++++++++++++++++-
 5 files changed, 82 insertions(+), 15 deletions(-)

diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Mon Oct 30 09:45:17 2006 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Mon Oct 30 10:42:27 2006 +0000
@@ -217,8 +217,7 @@ static int vlapic_accept_irq(struct vcpu
         if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) )
             break;
 
-        if ( vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR) &&
-             trig_mode)
+        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);
@@ -482,6 +481,11 @@ static void vlapic_read_aligned(struct v
     *result = 0;
 
     switch ( offset ) {
+    case APIC_PROCPRI:
+        vlapic_update_ppr(vlapic);
+        *result = vlapic_get_reg(vlapic, offset);
+        break;
+
     case APIC_ARBPRI:
         printk("access local APIC ARBPRI register which is for P6\n");
         break;
@@ -616,6 +620,7 @@ static void vlapic_write(struct vcpu *v,
     case APIC_TASKPRI:
         vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
         vlapic_update_ppr(vlapic);
+        vlapic->flush_tpr_threshold = 1;
         break;
 
     case APIC_EOI:
@@ -814,7 +819,7 @@ void vlapic_timer_fn(void *data)
 
     vlapic->timer_last_update = now;
 
-    if ( vlapic_test_and_set_vector(timer_vector, vlapic->regs + APIC_IRR) )
+    if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
         vlapic->intr_pending_count[timer_vector]++;
 
     if ( vlapic_lvtt_period(vlapic) )
@@ -891,7 +896,7 @@ int cpu_get_apic_interrupt(struct vcpu *
                 HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
                             "Sending an illegal vector 0x%x.", highest_irr);
 
-                vlapic_set_vector(err_vector, vlapic->regs + APIC_IRR);
+                vlapic_set_irr(err_vector, vlapic);
                 highest_irr = err_vector;
             }
 
@@ -942,7 +947,7 @@ void vlapic_post_injection(struct vcpu *
     case APIC_DM_FIXED:
     case APIC_DM_LOWEST:
         vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
-        vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
+        vlapic_clear_irr(vector, vlapic);
         vlapic_update_ppr(vlapic);
 
         if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) )
@@ -950,7 +955,7 @@ void vlapic_post_injection(struct vcpu *
             if ( vlapic->intr_pending_count[vector] > 0 )
             {
                 vlapic->intr_pending_count[vector]--;
-                vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
+                vlapic_set_irr(vector, vlapic);
             }
         }
         break;
@@ -1000,6 +1005,8 @@ static int vlapic_reset(struct vlapic *v
     vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
 
     vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+
+    vlapic->flush_tpr_threshold = 0;
 
     if ( v->vcpu_id == 0 )
         vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Mon Oct 30 09:45:17 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/io.c Mon Oct 30 10:42:27 2006 +0000
@@ -68,6 +68,27 @@ static inline int is_interruptibility_st
     return interruptibility;
 }
 
+#ifdef __x86_64__
+static void update_tpr_threshold(struct vlapic *vlapic)
+{
+    int highest_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);
+    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));
+}
+#else
+#define update_tpr_threshold(v) ((void)0)
+#endif
 
 asmlinkage void vmx_intr_assist(void)
 {
@@ -75,6 +96,7 @@ asmlinkage void vmx_intr_assist(void)
     int highest_vector;
     unsigned long eflags;
     struct vcpu *v = current;
+    struct vlapic *vlapic = VLAPIC(v);
     struct hvm_domain *plat=&v->domain->arch.hvm_domain;
     struct periodic_time *pt = &plat->pl_time.periodic_tm;
     struct hvm_virpic *pic= &plat->vpic;
@@ -97,6 +119,9 @@ asmlinkage void vmx_intr_assist(void)
         if ( callback_irq != 0 )
             pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
     }
+
+    if ( vlapic && vlapic_enabled(vlapic) && vlapic->flush_tpr_threshold )
+        update_tpr_threshold(vlapic);
 
     has_ext_irq = cpu_has_pending_irq(v);
 
diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Mon Oct 30 09:45:17 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Mon Oct 30 10:42:27 2006 +0000
@@ -346,8 +346,21 @@ static void vmx_do_launch(struct vcpu *v
 
     hvm_stts(v);
 
-    if(hvm_apic_support(v->domain))
-        vlapic_init(v);
+    if( hvm_apic_support(v->domain) && (vlapic_init(v) == 0) )
+    {
+#ifdef __x86_64__ 
+        u32 *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
+        u64  vapic_page_addr = 
+                        page_to_maddr(v->arch.hvm_vcpu.vlapic->regs_page);
+
+        *cpu_exec_control   |= CPU_BASED_TPR_SHADOW;
+        *cpu_exec_control   &= ~CPU_BASED_CR8_STORE_EXITING;
+        *cpu_exec_control   &= ~CPU_BASED_CR8_LOAD_EXITING;
+        error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
+        error |= __vmwrite(VIRTUAL_APIC_PAGE_ADDR, vapic_page_addr);
+        error |= __vmwrite(TPR_THRESHOLD, 0);
+#endif
+    }
 
     vmx_set_host_env(v);
     init_timer(&v->arch.hvm_vcpu.hlt_timer, hlt_timer_fn, v, v->processor);
@@ -514,12 +527,6 @@ static inline int construct_vmcs_host(vo
     error |= __vmwrite(HOST_CR4, crn);
 
     error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
-#ifdef __x86_64__
-    /* TBD: support cr8 for 64-bit guest */
-    __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0);
-    __vmwrite(TPR_THRESHOLD, 0);
-    __vmwrite(SECONDARY_VM_EXEC_CONTROL, 0);
-#endif
 
     return error;
 }
diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 30 09:45:17 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 30 10:42:27 2006 +0000
@@ -2409,6 +2409,11 @@ asmlinkage void vmx_vmexit_handler(struc
         vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
         break;
 
+    case EXIT_REASON_TPR_BELOW_THRESHOLD:
+        vlapic_update_ppr(VLAPIC(v));
+        VLAPIC(v)->flush_tpr_threshold = 1;
+        break;
+
     default:
         domain_crash_synchronous();     /* should not happen */
     }
diff -r c33272c2571c -r 2b99c99f96e6 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 30 09:45:17 2006 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 30 10:42:27 2006 +0000
@@ -107,6 +107,7 @@ struct vlapic {
     uint32_t           timer_divide_count;
     struct timer       vlapic_timer;
     int                intr_pending_count[MAX_VECTOR];
+    int                flush_tpr_threshold;
     s_time_t           timer_last_update;
     direct_intr_info_t direct_intr;
     uint32_t           err_status;
@@ -117,12 +118,30 @@ struct vlapic {
     void               *regs;
 };
 
+static inline 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 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_vector(vec, vlapic->regs + APIC_IRR);
+    ret = vlapic_test_and_set_irr(vec, vlapic);
     if ( trig )
         vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
 
@@ -144,12 +163,16 @@ static inline void vlapic_set_reg(struct
 
 void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
 
+extern int vlapic_find_highest_irr(struct vlapic *vlapic);
+
 int cpu_has_apic_interrupt(struct vcpu* v);
 int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
 
 extern int vlapic_init(struct vcpu *vc);
 
 extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+
+extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
 
 int vlapic_accept_pic_intr(struct vcpu *v);
 

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