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

[Xen-changelog] [xen-unstable] svm: Greatly reduce total number of CR8 intercepts



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1189437193 -3600
# Node ID 924c153e0cf90e7c6f9033842d702d0fbc122d29
# Parent  4633e9604da9c51f077285465d63db1820e6f574
svm: Greatly reduce total number of CR8 intercepts

This patch reduces the number of CR8 intercept to a fraction of the
number of CR8 intercepts without.  First, CR8 read intercepts are
completely disabled since the SVM vTPR is kept kept in sync with the
HVM vLAPIC TPR.  Second, CR8 write intercepts are enabled and disabled
based upon certain conditions.  Most of the time, CR8 write intercepts
are disabled.  They are enabled only when there is a pending interrupt
that can't be delivered because of either the current ISR or TPR (aka
PPR) because this is the only time the TPR matters.

With this patch, the number of CR8 intercepts dropped from around
10,000,000 to around 6,000 during boot of Windows 2003 Server 64-bit
(this is a rough estimate).

Signed-off-by: Travis Betak <travis.betak@xxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/intr.c |   35 +++++++++++++++++++++++++++++++++--
 xen/arch/x86/hvm/svm/svm.c  |   10 ++++++++++
 xen/arch/x86/hvm/svm/vmcb.c |   30 ++++++++++++++++++------------
 3 files changed, 61 insertions(+), 14 deletions(-)

diff -r 4633e9604da9 -r 924c153e0cf9 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Mon Sep 10 14:42:30 2007 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c       Mon Sep 10 16:13:13 2007 +0100
@@ -30,6 +30,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/io.h>
 #include <asm/hvm/support.h>
+#include <asm/hvm/vlapic.h>
 #include <asm/hvm/svm/svm.h>
 #include <asm/hvm/svm/intr.h>
 #include <xen/event.h>
@@ -99,6 +100,33 @@ static void enable_intr_window(struct vc
     svm_inject_dummy_vintr(v);
 }
 
+static void update_cr8_intercept(
+    struct vcpu *v, enum hvm_intack masked_intr_source)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    struct vlapic *vlapic = vcpu_vlapic(v);
+    int max_irr;
+
+    vmcb->cr_intercepts &= ~CR_INTERCEPT_CR8_WRITE;
+
+    /*
+     * If ExtInts are masked then that dominates the TPR --- the 'interrupt
+     * window' has already been enabled in this case.
+     */
+    if ( (masked_intr_source == hvm_intack_lapic) ||
+         (masked_intr_source == hvm_intack_pic) )
+        return;
+
+    /* Is there an interrupt pending at the LAPIC? Nothing to do if not. */
+    if ( !vlapic_enabled(vlapic) || 
+         ((max_irr = vlapic_find_highest_irr(vlapic)) == -1) )
+        return;
+
+    /* Highest-priority pending interrupt is masked by the TPR? */
+    if ( (vmcb->vintr.fields.tpr & 0xf) >= (max_irr >> 4) )
+        vmcb->cr_intercepts |= CR_INTERCEPT_CR8_WRITE;
+}
+
 asmlinkage void svm_intr_assist(void) 
 {
     struct vcpu *v = current;
@@ -113,7 +141,7 @@ asmlinkage void svm_intr_assist(void)
     do {
         intr_source = hvm_vcpu_has_pending_irq(v);
         if ( likely(intr_source == hvm_intack_none) )
-            return;
+            goto out;
 
         /*
          * Pending IRQs must be delayed if:
@@ -133,7 +161,7 @@ asmlinkage void svm_intr_assist(void)
              !hvm_interrupts_enabled(v, intr_source) )
         {
             enable_intr_window(v, intr_source);
-            return;
+            goto out;
         }
     } while ( !hvm_vcpu_ack_pending_irq(v, intr_source, &intr_vector) );
 
@@ -152,6 +180,9 @@ asmlinkage void svm_intr_assist(void)
     intr_source = hvm_vcpu_has_pending_irq(v);
     if ( unlikely(intr_source != hvm_intack_none) )
         enable_intr_window(v, intr_source);
+
+ out:
+    update_cr8_intercept(v, intr_source);
 }
 
 /*
diff -r 4633e9604da9 -r 924c153e0cf9 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Sep 10 14:42:30 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Sep 10 16:13:13 2007 +0100
@@ -2153,6 +2153,16 @@ asmlinkage void svm_vmexit_handler(struc
     eventinj_t eventinj;
     int inst_len, rc;
 
+    /*
+     * Before doing anything else, we need to sync up the VLAPIC's TPR with
+     * SVM's vTPR if CR8 writes are currently disabled.  It's OK if the 
+     * guest doesn't touch the CR8 (e.g. 32-bit Windows) because we update
+     * the vTPR on MMIO writes to the TPR
+     */
+    if ( !(vmcb->cr_intercepts & CR_INTERCEPT_CR8_WRITE) )
+        vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,
+                       (vmcb->vintr.fields.tpr & 0x0F) << 4);
+
     exit_reason = vmcb->exitcode;
 
     HVMTRACE_2D(VMEXIT, v, vmcb->rip, exit_reason);
diff -r 4633e9604da9 -r 924c153e0cf9 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Sep 10 14:42:30 2007 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Sep 10 16:13:13 2007 +0100
@@ -114,23 +114,29 @@ static int construct_vmcb(struct vcpu *v
     svm_asid_init_vcpu(v);
 
     vmcb->general1_intercepts = 
-        GENERAL1_INTERCEPT_INTR         | GENERAL1_INTERCEPT_NMI         |
-        GENERAL1_INTERCEPT_SMI          | GENERAL1_INTERCEPT_INIT        |
-        GENERAL1_INTERCEPT_CPUID        | GENERAL1_INTERCEPT_INVD        |
-        GENERAL1_INTERCEPT_HLT          | GENERAL1_INTERCEPT_INVLPG      | 
-        GENERAL1_INTERCEPT_INVLPGA      | GENERAL1_INTERCEPT_IOIO_PROT   |
-        GENERAL1_INTERCEPT_MSR_PROT     | GENERAL1_INTERCEPT_SHUTDOWN_EVT;
+        GENERAL1_INTERCEPT_INTR        | GENERAL1_INTERCEPT_NMI         |
+        GENERAL1_INTERCEPT_SMI         | GENERAL1_INTERCEPT_INIT        |
+        GENERAL1_INTERCEPT_CPUID       | GENERAL1_INTERCEPT_INVD        |
+        GENERAL1_INTERCEPT_HLT         | GENERAL1_INTERCEPT_INVLPG      | 
+        GENERAL1_INTERCEPT_INVLPGA     | GENERAL1_INTERCEPT_IOIO_PROT   |
+        GENERAL1_INTERCEPT_MSR_PROT    | GENERAL1_INTERCEPT_SHUTDOWN_EVT;
     vmcb->general2_intercepts = 
-        GENERAL2_INTERCEPT_VMRUN  | GENERAL2_INTERCEPT_VMMCALL | 
-        GENERAL2_INTERCEPT_VMLOAD | GENERAL2_INTERCEPT_VMSAVE  |
-        GENERAL2_INTERCEPT_STGI   | GENERAL2_INTERCEPT_CLGI    |
-        GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
+        GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
+        GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
+        GENERAL2_INTERCEPT_STGI        | GENERAL2_INTERCEPT_CLGI        |
+        GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_RDTSCP;
 
     /* Intercept all debug-register writes. */
     vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
 
-    /* Intercept all control-register accesses, except to CR2. */
-    vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
+    /*
+     * Intercept all control-register accesses except for CR2 reads/writes
+     * and CR8 reads (and actually CR8 writes, but that's a special case
+     * that's handled in svm/intr.c). 
+     */
+    vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ |
+                            CR_INTERCEPT_CR2_WRITE |
+                            CR_INTERCEPT_CR8_READ);
 
     /* I/O and MSR permission bitmaps. */
     arch_svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));

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