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

[Xen-changelog] [xen-unstable] Add RDTSCP instruction support for HVM VMX guest.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260776817 0
# Node ID c61953922215ecde526468d5a2ebe5147eee7529
# Parent  2d072636c4f8b80ac62f49aaeabb04fcdf74760c
Add RDTSCP instruction support for HVM VMX guest.

RDTSCP is introduced in Nehalem processor on Intel platform. Like
RDTSC, RDTSCP will return the TSC value, besides, it will return the
low 32bit of TSC_AUX MSR. Currently Linux kernel will write (node_id
<< 12 | process_id) into that MSR, so that when guest execs RDTSCP, it
will also get processor information.  - This instruction is supported
for HVM only when the hardware has this capability (indicated by
cpuid).

Signed-off-by: Dongxiao Xu <dongxiao.xu@xxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/vmcs.c            |    5 ++
 xen/arch/x86/hvm/vmx/vmx.c             |   76 ++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/cpufeature.h       |    2 
 xen/include/asm-x86/hvm/vmx/vmcs.h     |    2 
 xen/include/asm-x86/hvm/vmx/vmx.h      |    1 
 xen/include/asm-x86/msr-index.h        |    1 
 xen/include/public/arch-x86/hvm/save.h |    1 
 7 files changed, 86 insertions(+), 2 deletions(-)

diff -r 2d072636c4f8 -r c61953922215 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Mon Dec 14 07:46:57 2009 +0000
@@ -593,6 +593,11 @@ static int construct_vmcs(struct vcpu *v
         __vmwrite(PLE_GAP, ple_gap);
         __vmwrite(PLE_WINDOW, ple_window);
     }
+
+#ifdef __x86_64__
+    if ( cpu_has_rdtscp )
+        v->arch.hvm_vmx.secondary_exec_control |= SECONDARY_EXEC_ENABLE_RDTSCP;
+#endif
 
     if ( cpu_has_vmx_secondary_exec_control )
         __vmwrite(SECONDARY_VM_EXEC_CONTROL,
diff -r 2d072636c4f8 -r c61953922215 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Dec 14 07:46:57 2009 +0000
@@ -136,18 +136,31 @@ static void vmx_vcpu_destroy(struct vcpu
 
 static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state);
 
-static u32 msr_index[VMX_MSR_COUNT] =
+static u32 msr_index[] =
 {
     MSR_LSTAR, MSR_STAR, MSR_SYSCALL_MASK
 };
 
+#define MSR_INDEX_SIZE (ARRAY_SIZE(msr_index))
+
 static void vmx_save_host_msrs(void)
 {
     struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
     int i;
 
-    for ( i = 0; i < VMX_MSR_COUNT; i++ )
+    /*
+     * If new MSR is needed to add into msr_index[] and VMX_INDEX_MSR_*** enum,
+     * please note that elements in msr_index[] and VMX_INDEX_MSR_*** enum
+     * are not the same. Currently we only save three MSRs(MSR_LSTAR, MSR_STAR,
+     * and MSR_SYSCALL_MASK into host state. 
+     */
+    BUILD_BUG_ON(MSR_INDEX_SIZE != VMX_INDEX_MSR_TSC_AUX ||
+                 VMX_INDEX_MSR_TSC_AUX != VMX_MSR_COUNT - 1);
+    for ( i = 0; i < MSR_INDEX_SIZE; i++ )
         rdmsrl(msr_index[i], host_msr_state->msrs[i]);
+
+    if ( cpu_has_rdtscp )
+        rdmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
 }
 
 #define WRITE_MSR(address)                                              \
@@ -198,6 +211,21 @@ static enum handler_return long_mode_do_
         msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
         break;
 
+    case MSR_TSC_AUX:
+        if ( cpu_has_rdtscp ) 
+        {
+            msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX];
+            break;
+        }
+        else
+        {
+            HVM_DBG_LOG(DBG_LEVEL_0, "Reading from nonexistence msr 0x%x\n",
+                        ecx);
+            vmx_inject_hw_exception(TRAP_gp_fault, 0);
+            return HNDL_exception_raised;
+        }
+            
+
     default:
         return HNDL_unhandled;
     }
@@ -258,6 +286,20 @@ static enum handler_return long_mode_do_
 
     case MSR_SYSCALL_MASK:
         WRITE_MSR(SYSCALL_MASK);
+
+    case MSR_TSC_AUX:
+        if ( cpu_has_rdtscp )
+        {
+            struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
+            guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = msr_content;
+            wrmsrl(MSR_TSC_AUX, msr_content);
+        }
+        else
+        {
+            HVM_DBG_LOG(DBG_LEVEL_0, "Writing to nonexistence msr 0x%x\n", 
ecx);
+            vmx_inject_hw_exception(TRAP_gp_fault, 0);
+            return HNDL_exception_raised;
+        }
 
     default:
         return HNDL_unhandled;
@@ -289,15 +331,21 @@ static void vmx_restore_host_msrs(void)
         wrmsrl(msr_index[i], host_msr_state->msrs[i]);
         clear_bit(i, &host_msr_state->flags);
     }
+
+    if ( cpu_has_rdtscp )
+        wrmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
 }
 
 static void vmx_save_guest_msrs(struct vcpu *v)
 {
+    struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
     /*
      * We cannot cache SHADOW_GS_BASE while the VCPU runs, as it can
      * be updated at any time via SWAPGS, which we cannot trap.
      */
     rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs);
+    if ( cpu_has_rdtscp )
+        rdmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
 }
 
 static void vmx_restore_guest_msrs(struct vcpu *v)
@@ -333,6 +381,9 @@ static void vmx_restore_guest_msrs(struc
         write_efer((read_efer() & ~EFER_SCE) |
                    (v->arch.hvm_vcpu.guest_efer & EFER_SCE));
     }
+
+    if ( cpu_has_rdtscp )
+        wrmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
 }
 
 #else  /* __i386__ */
@@ -574,6 +625,8 @@ static void vmx_save_cpu_state(struct vc
     data->msr_lstar        = guest_state->msrs[VMX_INDEX_MSR_LSTAR];
     data->msr_star         = guest_state->msrs[VMX_INDEX_MSR_STAR];
     data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
+    if ( cpu_has_rdtscp )
+        data->msr_tsc_aux = guest_state->msrs[VMX_INDEX_MSR_TSC_AUX];
 #endif
 
     data->tsc = hvm_get_guest_tsc(v);
@@ -592,6 +645,8 @@ static void vmx_load_cpu_state(struct vc
 
     v->arch.hvm_vmx.cstar     = data->msr_cstar;
     v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
+    if ( cpu_has_rdtscp )
+        guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = data->msr_tsc_aux;
 #endif
 
     hvm_set_guest_tsc(v, data->tsc);
@@ -1507,6 +1562,14 @@ static void vmx_cpuid_intercept(
                 *edx |= bitmaskof(X86_FEATURE_SYSCALL);
             else
                 *edx &= ~(bitmaskof(X86_FEATURE_SYSCALL));
+
+#ifdef __x86_64__
+            if ( cpu_has_rdtscp )
+                *edx |= bitmaskof(X86_FEATURE_RDTSCP);
+            else
+                *edx &= ~(bitmaskof(X86_FEATURE_RDTSCP));
+#endif
+
             break;
     }
 
@@ -2495,6 +2558,15 @@ asmlinkage void vmx_vmexit_handler(struc
         __update_guest_eip(inst_len);
         hvm_rdtsc_intercept(regs);
         break;
+    case EXIT_REASON_RDTSCP:
+    {
+        struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
+        inst_len = __get_instruction_length();
+        __update_guest_eip(inst_len);
+        hvm_rdtsc_intercept(regs);
+        regs->ecx = (uint32_t)(guest_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
+        break;
+    }
     case EXIT_REASON_VMCALL:
     {
         int rc;
diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h  Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/include/asm-x86/cpufeature.h  Mon Dec 14 07:46:57 2009 +0000
@@ -196,6 +196,8 @@
 
 #define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
 
+#define cpu_has_rdtscp          boot_cpu_has(X86_FEATURE_RDTSCP)
+
 #endif /* __ASM_I386_CPUFEATURE_H */
 
 /* 
diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Mon Dec 14 07:46:57 2009 +0000
@@ -44,6 +44,7 @@ enum {
     VMX_INDEX_MSR_LSTAR = 0,
     VMX_INDEX_MSR_STAR,
     VMX_INDEX_MSR_SYSCALL_MASK,
+    VMX_INDEX_MSR_TSC_AUX,
 
     VMX_MSR_COUNT
 };
@@ -166,6 +167,7 @@ extern u32 vmx_vmentry_control;
 
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
+#define SECONDARY_EXEC_ENABLE_RDTSCP            0x00000008
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING           0x00000040
 #define SECONDARY_EXEC_UNRESTRICTED_GUEST       0x00000080
diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 14 07:46:57 2009 +0000
@@ -110,6 +110,7 @@ void vmx_update_debug_state(struct vcpu 
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
+#define EXIT_REASON_RDTSCP              51
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55
 
diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/msr-index.h
--- a/xen/include/asm-x86/msr-index.h   Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/include/asm-x86/msr-index.h   Mon Dec 14 07:46:57 2009 +0000
@@ -12,6 +12,7 @@
 #define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
 #define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
 #define MSR_SHADOW_GS_BASE     0xc0000102 /* SwapGS GS shadow */
+#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
 
 /* EFER bits: */
 #define _EFER_SCE              0  /* SYSCALL/SYSRET */
diff -r 2d072636c4f8 -r c61953922215 xen/include/public/arch-x86/hvm/save.h
--- a/xen/include/public/arch-x86/hvm/save.h    Mon Dec 14 07:45:04 2009 +0000
+++ b/xen/include/public/arch-x86/hvm/save.h    Mon Dec 14 07:46:57 2009 +0000
@@ -137,6 +137,7 @@ struct hvm_hw_cpu {
     uint64_t msr_cstar;
     uint64_t msr_syscall_mask;
     uint64_t msr_efer;
+    uint64_t msr_tsc_aux;
 
     /* guest's idea of what rdtsc() would return */
     uint64_t tsc;

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