# 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
|