2011-06-17 18:45:46 +02:00
|
|
|
References: FATE#309901
|
|
|
|
|
|
|
|
# HG changeset patch
|
|
|
|
# User Wei Huang <wei.huang2@amd.com>
|
|
|
|
# Date 1306569488 -3600
|
|
|
|
# Node ID d7c755c25bb9d6ed77d64cb6736b6c4f339db1bf
|
|
|
|
# Parent f6ce871e568949f5817470f6c7bab6ed1f8f6c13
|
|
|
|
HVM/SVM: enable tsc scaling ratio for SVM
|
|
|
|
|
|
|
|
Future AMD CPUs support TSC scaling. It allows guests to have a
|
|
|
|
different TSC frequency from host system using this formula: guest_tsc
|
|
|
|
= host_tsc * tsc_ratio + vmcb_offset. The tsc_ratio is a 64bit MSR
|
|
|
|
contains a fixed-point number in 8.32 format (8 bits for integer part
|
|
|
|
and 32bits for fractional part). For instance 0x00000003_80000000
|
|
|
|
means tsc_ratio=3.5.
|
|
|
|
|
|
|
|
This patch enables TSC scaling ratio for SVM. With it, guest VMs don't
|
|
|
|
need take #VMEXIT to calculate a translated TSC value when it is
|
|
|
|
running under TSC emulation mode. This can substancially reduce the
|
|
|
|
rdtsc overhead.
|
|
|
|
|
|
|
|
Signed-off-by: Wei Huang <wei.huang2@amd.com>
|
|
|
|
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/arch/x86/hvm/svm/svm.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/arch/x86/hvm/svm/svm.c
|
|
|
|
+++ xen-4.1.2-testing/xen/arch/x86/hvm/svm/svm.c
|
2011-06-17 18:45:46 +02:00
|
|
|
@@ -588,6 +588,22 @@ static void svm_set_segment_register(str
|
|
|
|
static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
|
|
|
|
{
|
|
|
|
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
|
|
|
+ struct domain *d = v->domain;
|
|
|
|
+
|
|
|
|
+ /* Re-adjust the offset value when TSC_RATIO is available */
|
|
|
|
+ if ( cpu_has_tsc_ratio && d->arch.vtsc )
|
|
|
|
+ {
|
|
|
|
+ uint64_t host_tsc, guest_tsc;
|
|
|
|
+
|
|
|
|
+ rdtscll(host_tsc);
|
|
|
|
+ guest_tsc = hvm_get_guest_tsc(v);
|
|
|
|
+
|
|
|
|
+ /* calculate hi,lo parts in 64bits to prevent overflow */
|
|
|
|
+ offset = (((host_tsc >> 32) * d->arch.tsc_khz / cpu_khz) << 32) +
|
|
|
|
+ (host_tsc & 0xffffffffULL) * d->arch.tsc_khz / cpu_khz;
|
|
|
|
+ offset = guest_tsc - offset;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
vmcb_set_tsc_offset(vmcb, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -638,6 +654,19 @@ static void svm_init_hypercall_page(stru
|
|
|
|
*(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
|
|
|
|
}
|
|
|
|
|
|
|
|
+static inline void svm_tsc_ratio_save(struct vcpu *v)
|
|
|
|
+{
|
|
|
|
+ /* Other vcpus might not have vtsc enabled. So disable TSC_RATIO here. */
|
|
|
|
+ if ( cpu_has_tsc_ratio && v->domain->arch.vtsc )
|
|
|
|
+ wrmsrl(MSR_AMD64_TSC_RATIO, DEFAULT_TSC_RATIO);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void svm_tsc_ratio_load(struct vcpu *v)
|
|
|
|
+{
|
|
|
|
+ if ( cpu_has_tsc_ratio && v->domain->arch.vtsc )
|
|
|
|
+ wrmsrl(MSR_AMD64_TSC_RATIO, vcpu_tsc_ratio(v));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void svm_ctxt_switch_from(struct vcpu *v)
|
|
|
|
{
|
|
|
|
int cpu = smp_processor_id();
|
2011-09-15 23:43:21 +02:00
|
|
|
@@ -646,6 +675,7 @@ static void svm_ctxt_switch_from(struct
|
2011-06-17 18:45:46 +02:00
|
|
|
|
|
|
|
svm_save_dr(v);
|
|
|
|
vpmu_save(v);
|
|
|
|
+ svm_tsc_ratio_save(v);
|
|
|
|
|
|
|
|
svm_sync_vmcb(v);
|
|
|
|
svm_vmload(per_cpu(root_vmcb, cpu));
|
|
|
|
@@ -689,6 +719,7 @@ static void svm_ctxt_switch_to(struct vc
|
|
|
|
svm_vmload(vmcb);
|
|
|
|
vmcb->cleanbits.bytes = 0;
|
|
|
|
vpmu_load(v);
|
|
|
|
+ svm_tsc_ratio_load(v);
|
|
|
|
|
|
|
|
if ( cpu_has_rdtscp )
|
|
|
|
wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/arch/x86/hvm/svm/vmcb.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/arch/x86/hvm/svm/vmcb.c
|
|
|
|
+++ xen-4.1.2-testing/xen/arch/x86/hvm/svm/vmcb.c
|
2011-06-17 18:45:46 +02:00
|
|
|
@@ -165,7 +165,9 @@ static int construct_vmcb(struct vcpu *v
|
|
|
|
|
|
|
|
/* TSC. */
|
|
|
|
vmcb->_tsc_offset = 0;
|
|
|
|
- if ( v->domain->arch.vtsc )
|
|
|
|
+
|
|
|
|
+ /* Don't need to intercept RDTSC if CPU supports TSC rate scaling */
|
|
|
|
+ if ( v->domain->arch.vtsc && !cpu_has_tsc_ratio )
|
|
|
|
{
|
|
|
|
vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
|
|
|
|
vmcb->_general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/include/asm-x86/hvm/svm/svm.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/include/asm-x86/hvm/svm/svm.h
|
|
|
|
+++ xen-4.1.2-testing/xen/include/asm-x86/hvm/svm/svm.h
|
2011-06-17 18:45:46 +02:00
|
|
|
@@ -91,5 +91,13 @@ extern u32 svm_feature_flags;
|
|
|
|
#define cpu_has_svm_cleanbits cpu_has_svm_feature(SVM_FEATURE_VMCBCLEAN)
|
|
|
|
#define cpu_has_svm_decode cpu_has_svm_feature(SVM_FEATURE_DECODEASSISTS)
|
|
|
|
#define cpu_has_pause_filter cpu_has_svm_feature(SVM_FEATURE_PAUSEFILTER)
|
|
|
|
+#define cpu_has_tsc_ratio cpu_has_svm_feature(SVM_FEATURE_TSCRATEMSR)
|
|
|
|
+
|
|
|
|
+/* TSC rate */
|
|
|
|
+#define DEFAULT_TSC_RATIO 0x0000000100000000ULL
|
|
|
|
+#define TSC_RATIO_RSVD_BITS 0xffffff0000000000ULL
|
|
|
|
+#define TSC_RATIO(g_khz, h_khz) ( (((u64)(g_khz)<<32)/(u64)(h_khz)) & \
|
|
|
|
+ ~TSC_RATIO_RSVD_BITS )
|
|
|
|
+#define vcpu_tsc_ratio(v) TSC_RATIO((v)->domain->arch.tsc_khz, cpu_khz)
|
|
|
|
|
|
|
|
#endif /* __ASM_X86_HVM_SVM_H__ */
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/include/asm-x86/msr-index.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/include/asm-x86/msr-index.h
|
|
|
|
+++ xen-4.1.2-testing/xen/include/asm-x86/msr-index.h
|
2011-10-18 16:16:28 +02:00
|
|
|
@@ -261,6 +261,9 @@
|
2011-06-17 18:45:46 +02:00
|
|
|
#define MSR_AMD_PATCHLEVEL 0x0000008b
|
|
|
|
#define MSR_AMD_PATCHLOADER 0xc0010020
|
|
|
|
|
|
|
|
+/* AMD TSC RATE MSR */
|
|
|
|
+#define MSR_AMD64_TSC_RATIO 0xc0000104
|
|
|
|
+
|
|
|
|
/* AMD OS Visible Workaround MSRs */
|
|
|
|
#define MSR_AMD_OSVW_ID_LENGTH 0xc0010140
|
|
|
|
#define MSR_AMD_OSVW_STATUS 0xc0010141
|