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] x86, vmx: Enable VPID (Virtual Processor

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86, vmx: Enable VPID (Virtual Processor Identification)
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 09 Apr 2008 06:50:23 -0700
Delivery-date: Wed, 09 Apr 2008 06:50:49 -0700
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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1207748089 -3600
# Node ID 0553004fa328b86756a428410d21394fe62bd29a
# Parent  3a213b0e1ac01b7c13b8da10919f1692219cdfb5
x86, vmx: Enable VPID (Virtual Processor Identification)

Allows TLB entries to be retained across VM entry and VM exit, and Xen
can now identify distinct address spaces through a new
virtual-processor ID (VPID) field of the VMCS.

Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>
Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx>
Signed-off-by: Xiaohui Xin <Xiaohui.xin@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/vmcs.c        |   17 ++++++++
 xen/arch/x86/hvm/vmx/vmx.c         |   74 +++++++++++++++++++++++++++++++++++--
 xen/include/asm-x86/hvm/vmx/vmcs.h |   10 ++++-
 xen/include/asm-x86/hvm/vmx/vmx.h  |   44 ++++++++++++++++++----
 4 files changed, 133 insertions(+), 12 deletions(-)

diff -r 3a213b0e1ac0 -r 0553004fa328 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Wed Apr 09 14:10:32 2008 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Wed Apr 09 14:34:49 2008 +0100
@@ -38,6 +38,9 @@
 #include <asm/shadow.h>
 #include <asm/tboot.h>
 
+static int opt_vpid_enabled = 1;
+boolean_param("vpid", opt_vpid_enabled);
+
 /* Dynamic (run-time adjusted) execution control flags. */
 u32 vmx_pin_based_exec_control __read_mostly;
 u32 vmx_cpu_based_exec_control __read_mostly;
@@ -111,6 +114,8 @@ static void vmx_init_vmcs_config(void)
         opt = (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
                SECONDARY_EXEC_WBINVD_EXITING |
                SECONDARY_EXEC_ENABLE_EPT);
+        if ( opt_vpid_enabled )
+            opt |= SECONDARY_EXEC_ENABLE_VPID;
         _vmx_secondary_exec_control = adjust_vmx_controls(
             min, opt, MSR_IA32_VMX_PROCBASED_CTLS2);
     }
@@ -317,6 +322,8 @@ int vmx_cpu_up(void)
 
     ept_sync_all();
 
+    vpid_sync_all();
+
     return 1;
 }
 
@@ -627,6 +634,13 @@ static int construct_vmcs(struct vcpu *v
         __vmwrite(EPT_POINTER_HIGH,
                   d->arch.hvm_domain.vmx.ept_control.eptp >> 32);
 #endif
+    }
+
+    if ( cpu_has_vmx_vpid )
+    {
+        v->arch.hvm_vmx.vpid =
+            v->domain->arch.hvm_domain.vmx.vpid_base + v->vcpu_id;
+        __vmwrite(VIRTUAL_PROCESSOR_ID, v->arch.hvm_vmx.vpid);
     }
 
     vmx_vmcs_exit(v);
@@ -822,6 +836,7 @@ void vmx_do_resume(struct vcpu *v)
         vmx_load_vmcs(v);
         hvm_migrate_timers(v);
         vmx_set_host_env(v);
+        vpid_sync_vcpu_all(v);
     }
 
     debug_state = v->domain->debugger_attached;
@@ -976,6 +991,8 @@ void vmcs_dump_vcpu(struct vcpu *v)
            (uint32_t)vmr(TPR_THRESHOLD));
     printk("EPT pointer = 0x%08x%08x\n",
            (uint32_t)vmr(EPT_POINTER_HIGH), (uint32_t)vmr(EPT_POINTER));
+    printk("Virtual processor ID = 0x%04x\n",
+           (uint32_t)vmr(VIRTUAL_PROCESSOR_ID));
 
     vmx_vmcs_exit(v);
 }
diff -r 3a213b0e1ac0 -r 0553004fa328 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Apr 09 14:10:32 2008 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Apr 09 14:34:49 2008 +0100
@@ -57,6 +57,8 @@ static void vmx_ctxt_switch_to(struct vc
 
 static int  vmx_alloc_vlapic_mapping(struct domain *d);
 static void vmx_free_vlapic_mapping(struct domain *d);
+static int  vmx_alloc_vpid(struct domain *d);
+static void vmx_free_vpid(struct domain *d);
 static void vmx_install_vlapic_mapping(struct vcpu *v);
 static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr);
 static void vmx_update_guest_efer(struct vcpu *v);
@@ -71,18 +73,30 @@ static void vmx_invlpg_intercept(unsigne
 
 static int vmx_domain_initialise(struct domain *d)
 {
+    int rc;
+
     d->arch.hvm_domain.vmx.ept_control.etmt = EPT_DEFAULT_MT;
     d->arch.hvm_domain.vmx.ept_control.gaw  = EPT_DEFAULT_GAW;
     d->arch.hvm_domain.vmx.ept_control.asr  =
         pagetable_get_pfn(d->arch.phys_table);
 
-    return vmx_alloc_vlapic_mapping(d);
+    if ( (rc = vmx_alloc_vpid(d)) != 0 )
+        return rc;
+
+    if ( (rc = vmx_alloc_vlapic_mapping(d)) != 0 )
+    {
+        vmx_free_vpid(d);
+        return rc;
+    }
+
+    return 0;
 }
 
 static void vmx_domain_destroy(struct domain *d)
 {
     ept_sync_domain(d);
     vmx_free_vlapic_mapping(d);
+    vmx_free_vpid(d);
 }
 
 static int vmx_vcpu_initialise(struct vcpu *v)
@@ -1024,6 +1038,7 @@ static void vmx_update_guest_cr(struct v
         }
  
         __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr[3]);
+        vpid_sync_vcpu_all(v);
         break;
     case 4:
         v->arch.hvm_vcpu.hw_cr[4] = HVM_CR4_HOST_MASK;
@@ -1069,9 +1084,15 @@ static void vmx_update_guest_efer(struct
 
 static void vmx_flush_guest_tlbs(void)
 {
-    /* No tagged TLB support on VMX yet.  The fact that we're in Xen
-     * at all means any guest will have a clean TLB when it's next run,
-     * because VMRESUME will flush it for us. */
+    /*
+     * If VPID (i.e. tagged TLB support) is not enabled, the fact that
+     * we're in Xen at all means any guest will have a clean TLB when
+     * it's next run, because VMRESUME will flush it for us.
+     *
+     * If enabled, we invalidate all translations associated with all
+     * VPID values.
+     */
+    vpid_sync_all();
 }
 
 static void __ept_sync_domain(void *info)
@@ -1202,6 +1223,9 @@ static struct hvm_function_table vmx_fun
     .invlpg_intercept     = vmx_invlpg_intercept
 };
 
+static unsigned long *vpid_bitmap;
+#define VPID_BITMAP_SIZE ((1u << VMCS_VPID_WIDTH) / MAX_VIRT_CPUS)
+
 void start_vmx(void)
 {
     static int bootstrapped;
@@ -1239,6 +1263,19 @@ void start_vmx(void)
     {
         printk("VMX: EPT is available.\n");
         vmx_function_table.hap_supported = 1;
+    }
+
+    if ( cpu_has_vmx_vpid )
+    {
+        printk("VMX: VPID is available.\n");
+
+        vpid_bitmap = xmalloc_array(
+            unsigned long, BITS_TO_LONGS(VPID_BITMAP_SIZE));
+        BUG_ON(vpid_bitmap == NULL);
+        memset(vpid_bitmap, 0, BITS_TO_LONGS(VPID_BITMAP_SIZE) * sizeof(long));
+
+        /* VPID 0 is used by VMX root mode (the hypervisor). */
+        __set_bit(0, vpid_bitmap);
     }
 
     setup_vmcs_dump();
@@ -1755,6 +1792,35 @@ static void vmx_free_vlapic_mapping(stru
         free_xenheap_page(mfn_to_virt(mfn));
 }
 
+static int vmx_alloc_vpid(struct domain *d)
+{
+    int idx;
+
+    if ( !cpu_has_vmx_vpid )
+        return 0;
+
+    do {
+        idx = find_first_zero_bit(vpid_bitmap, VPID_BITMAP_SIZE);
+        if ( idx >= VPID_BITMAP_SIZE )
+        {
+            dprintk(XENLOG_WARNING, "VMX VPID space exhausted.\n");
+            return -EBUSY;
+        }
+    }
+    while ( test_and_set_bit(idx, vpid_bitmap) );
+
+    d->arch.hvm_domain.vmx.vpid_base = idx * MAX_VIRT_CPUS;
+    return 0;
+}
+
+static void vmx_free_vpid(struct domain *d)
+{
+    if ( !cpu_has_vmx_vpid )
+        return;
+
+    clear_bit(d->arch.hvm_domain.vmx.vpid_base / MAX_VIRT_CPUS, vpid_bitmap);
+}
+
 static void vmx_install_vlapic_mapping(struct vcpu *v)
 {
     paddr_t virt_page_ma, apic_page_ma;
diff -r 3a213b0e1ac0 -r 0553004fa328 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Apr 09 14:10:32 2008 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Apr 09 14:34:49 2008 +0100
@@ -58,7 +58,7 @@ struct vmx_msr_state {
 
 struct vmx_domain {
     unsigned long apic_access_mfn;
-
+    unsigned long vpid_base;
     union {
         struct {
             u64 etmt :3,
@@ -89,6 +89,8 @@ struct arch_vmx_struct {
     /* Cache of cpu execution control. */
     u32                  exec_control;
     u32                  secondary_exec_control;
+
+    u16                  vpid;
 
     /* PMU */
     struct vpmu_struct   vpmu;
@@ -157,6 +159,7 @@ extern u32 vmx_vmentry_control;
 
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
+#define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING           0x00000040
 extern u32 vmx_secondary_exec_control;
 
@@ -176,6 +179,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
     (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
 #define cpu_has_vmx_ept \
     (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT)
+#define cpu_has_vmx_vpid \
+    (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
 
 /* GUEST_INTERRUPTIBILITY_INFO flags. */
 #define VMX_INTR_SHADOW_STI             0x00000001
@@ -185,6 +190,7 @@ extern bool_t cpu_has_vmx_ins_outs_instr
 
 /* VMCS field encodings. */
 enum vmcs_field {
+    VIRTUAL_PROCESSOR_ID            = 0x00000000,
     GUEST_ES_SELECTOR               = 0x00000800,
     GUEST_CS_SELECTOR               = 0x00000802,
     GUEST_SS_SELECTOR               = 0x00000804,
@@ -324,6 +330,8 @@ enum vmcs_field {
     HOST_RIP                        = 0x00006c16,
 };
 
+#define VMCS_VPID_WIDTH 16
+
 void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr);
 int vmx_read_guest_msr(struct vcpu *v, u32 msr, u64 *val);
 int vmx_write_guest_msr(struct vcpu *v, u32 msr, u64 val);
diff -r 3a213b0e1ac0 -r 0553004fa328 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Wed Apr 09 14:10:32 2008 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Wed Apr 09 14:34:49 2008 +0100
@@ -164,6 +164,7 @@ void vmx_realmode(struct cpu_user_regs *
 #define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3\n"
 #define VMWRITE_OPCODE  ".byte 0x0f,0x79\n"
 #define INVEPT_OPCODE   ".byte 0x66,0x0f,0x38,0x80\n"   /* m128,r64/32 */
+#define INVVPID_OPCODE  ".byte 0x66,0x0f,0x38,0x81\n"   /* m128,r64/32 */
 #define VMXOFF_OPCODE   ".byte 0x0f,0x01,0xc4\n"
 #define VMXON_OPCODE    ".byte 0xf3,0x0f,0xc7\n"
 
@@ -260,13 +261,30 @@ static inline void __invept(int ext, u64
         u64 eptp, gpa;
     } operand = {eptp, gpa};
 
-    __asm__ __volatile__ ( INVEPT_OPCODE
-                           MODRM_EAX_08
-                           /* CF==1 or ZF==1 --> rc = -1 */
-                           "ja 1f ; ud2 ; 1:\n"
-                           :
-                           : "a" (&operand), "c" (ext)
-                           : "memory");
+    asm volatile ( INVEPT_OPCODE
+                   MODRM_EAX_08
+                   /* CF==1 or ZF==1 --> rc = -1 */
+                   "ja 1f ; ud2 ; 1:\n"
+                   :
+                   : "a" (&operand), "c" (ext)
+                   : "memory" );
+}
+
+static inline void __invvpid(int ext, u16 vpid, u64 gva)
+{
+    struct {
+        u64 vpid:16;
+        u64 rsvd:48;
+        u64 gva;
+    } __attribute__ ((packed)) operand = {vpid, 0, gva};
+
+    asm volatile ( INVVPID_OPCODE
+                   MODRM_EAX_08
+                   /* CF==1 or ZF==1 --> rc = -1 */
+                   "ja 1f ; ud2 ; 1:\n"
+                   :
+                   : "a" (&operand), "c" (ext)
+                   : "memory" );
 }
 
 static inline void ept_sync_all(void)
@@ -278,6 +296,18 @@ static inline void ept_sync_all(void)
 }
 
 void ept_sync_domain(struct domain *d);
+
+static inline void vpid_sync_vcpu_all(struct vcpu *v)
+{
+    if ( cpu_has_vmx_vpid )
+        __invvpid(1, v->arch.hvm_vmx.vpid, 0);
+}
+
+static inline void vpid_sync_all(void)
+{
+    if ( cpu_has_vmx_vpid )
+        __invvpid(2, 0, 0);
+}
 
 static inline void __vmxoff(void)
 {

_______________________________________________
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] x86, vmx: Enable VPID (Virtual Processor Identification), Xen patchbot-unstable <=