FPU LWP 8/8: LWP: Add LWP support for SVM guests
PATCH 1/1 FPU LWP 8/8: LWP: Add LWP support for SVM guests
LWP: Add LWP support for SVM guests
This patch enables SVM to handle LWP related MSRs and CPUID. It intercepts guests read/write to LWP_CFG. It also save/restore LWP_CFG when guests touch this MSR. The LWP_CBADDR MSR is not intercepted because this MSR is handled by xsave/xrstor.
# HG changeset patch
# User Wei Huang <[email protected]>
# Date 1304449528 18000
# Node ID 8b4b5cad0089f9c215e84dbcf0145ea533d3ee40 # Parent dbd907bf172c399fc432b973a6668f1ba8545292
LWP: Add LWP support for SVM guests
This patch enables SVM to handle LWP related MSRs and CPUID. It intercepts guests read/write to LWP_CFG. It also save/restore LWP_CFG when guests touch this MSR. The LWP_CBADDR MSR is not intercepted because this MSR is handled by xsave/xrstor.
xen/arch/x86/hvm/svm/svm.c +69 -1
@@ -58,7 +58,8 @@#include <asm/hvm/trace.h> #include <asm/hap.h> #include <asm/apic.h> -#include <asm/debugger.h> +#include <asm/debugger.h> +#include <asm/xstate.h> u32 svm_feature_flags;
@@ -695,6 +696,44 @@ *(u16 *)(hypercall_page + (__HYPERVISOR_iret *32 )) =0x0b0f ;/* ud2 */ } +static inline void svm_lwp_save (struct vcpu *v) +{ +/* Don't mess up with other guests. Disable LWP for next VCPU. */ +if ( v->arch.hvm_svm.guest_lwp_cfg ) +wrmsrl (MSR_AMD64_LWP_CFG ,0x0 ); +} + +static inline void svm_lwp_load (struct vcpu *v) +{ +/* Only LWP_CFG is reloaded. LWP_CBADDR will be reloaded via xrstor. */ +if ( v->arch.hvm_svm.guest_lwp_cfg ) +wrmsrl (MSR_AMD64_LWP_CFG , v->arch.hvm_svm.guest_lwp_cfg); +} + +/* Update LWP_CFG MSR (0xc0000105). Return -1 if error; otherwise returns 0. */ +static int svm_update_lwp_cfg (struct vcpu *v,uint64_t msr_content) +{ +unsigned int eax, ebx, ecx, edx; +uint32_t msr_low; + +if ( cpu_has_lwp ) + { +hvm_cpuid (0x8000001c , &eax, &ebx, &ecx, &edx); + msr_low = (uint32_t )msr_content; + +/* generate #GP if guest tries to turn on unsupported features. */ +if ( msr_low & ~edx) +return -1 ; + +wrmsrl (MSR_AMD64_LWP_CFG , msr_content); +/* CPU might automatically correct reserved bits. So read it back. */ +rdmsrl (MSR_AMD64_LWP_CFG , msr_content); + v->arch.hvm_svm.guest_lwp_cfg = msr_content; + } + +return 0 ; +} +static void svm_ctxt_switch_from (struct vcpu *v) {int cpu =smp_processor_id ();
@@ -703,6 +742,7 @@svm_save_dr (v);vpmu_save (v); +svm_lwp_save (v);svm_sync_vmcb (v);svm_vmload (per_cpu (root_vmcb, cpu));
@@ -746,6 +786,7 @@svm_vmload (vmcb); vmcb->cleanbits.bytes =0 ;vpmu_load (v); +svm_lwp_load (v);if ( cpu_has_rdtscp )wrmsrl (MSR_TSC_AUX ,hvm_msr_tsc_aux (v));
@@ -1120,6 +1161,24 @@if (vlapic_hw_disabled (vcpu_vlapic (v)) )__clear_bit (X86_FEATURE_APIC &31 , edx);break ; +case 0x8000001c : + { +/* LWP capability CPUID */ +uint64_t lwp_cfg = v->arch.hvm_svm.guest_lwp_cfg; + +if ( cpu_has_lwp ) + { +if ( !(v->arch.xcr0 &XSTATE_LWP ) ) + { + *eax =0x0 ; +break ; + } + +/* turn on available bit and other features specified in lwp_cfg */ + *eax = (*edx & lwp_cfg) |0x00000001 ; + } +break ; + }default :break ; }
@@ -1227,6 +1286,10 @@ *msr_content =vmcb_get_lastinttoip (vmcb);break ; +case MSR_AMD64_LWP_CFG : + *msr_content = v->arch.hvm_svm.guest_lwp_cfg; +break ; +case MSR_K7_PERFCTR0 :case MSR_K7_PERFCTR1 :case MSR_K7_PERFCTR2 :
@@ -1323,6 +1386,11 @@case MSR_IA32_LASTINTTOIP :vmcb_set_lastinttoip (vmcb, msr_content); +break ; + +case MSR_AMD64_LWP_CFG : +if (svm_update_lwp_cfg (v, msr_content) <0 ) + goto gpf;break ;case MSR_K7_PERFCTR0 :
xen/arch/x86/hvm/svm/vmcb.c +5 -0
@@ -120,6 +120,11 @@svm_disable_intercept_for_msr (v,MSR_LSTAR );svm_disable_intercept_for_msr (v,MSR_STAR );svm_disable_intercept_for_msr (v,MSR_SYSCALL_MASK ); + +/* LWP_CBADDR MSR is saved and restored by FPU code. So SVM doesn't need to +* intercept it. */ +if ( cpu_has_lwp ) +svm_disable_intercept_for_msr (v,MSR_AMD64_LWP_CBADDR ); vmcb->_msrpm_base_pa = (u64 )virt_to_maddr (arch_svm->msrpm); vmcb->_iopm_base_pa = (u64 )virt_to_maddr (hvm_io_bitmap);
xen/include/asm-x86/cpufeature.h +2 -0
@@ -208,6 +208,8 @@#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) +#define cpu_has_lwp boot_cpu_has(X86_FEATURE_LWP) +#define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON)#define cpu_has_rdtscp boot_cpu_has(X86_FEATURE_RDTSCP)
xen/include/asm-x86/hvm/svm/vmcb.h +3 -0
@@ -512,6 +512,9 @@uint64_t guest_sysenter_cs;uint64_t guest_sysenter_esp;uint64_t guest_sysenter_eip; + +/* AMD lightweight profiling MSR */ +uint64_t guest_lwp_cfg; };struct vmcb_struct *alloc_vmcb (void );
xen/include/asm-x86/msr-index.h +4 -0
@@ -253,6 +253,10 @@#define MSR_AMD_PATCHLEVEL 0x0000008b#define MSR_AMD_PATCHLOADER 0xc0010020 +/* AMD Lightweight Profiling MSRs */ +#define MSR_AMD64_LWP_CFG 0xc0000105 +#define MSR_AMD64_LWP_CBADDR 0xc0000106 +/* AMD OS Visible Workaround MSRs */ #define MSR_AMD_OSVW_ID_LENGTH 0xc0010140#define MSR_AMD_OSVW_STATUS 0xc0010141
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel