FPU LWP 4/5: enable LWP for SVM guest
RFC PATCH 1/1 FPU LWP 4/5: enable LWP for SVM guest
This patch enables LWP support for SVM guests. It saves and restores LWP_CFG MSRs on each VCPU context switch. Additionally it handles LWP CPUIDs and MSRs.
# HG changeset patch
# User Wei Huang <[email protected]>
# Date 1302812238 18000
# Branch lwp3
# Node ID ee8656e10937121d2780862351a245ed874273fa # Parent bccbc5ecf62e49482c06149bb94dfc3dee8882f1
SVM: enable LWP for SVM guest
This patch enables LWP support for SVM guests. It saves and restores LWP_CFG MSRs on each VCPU context switch. Additionally it handles LWP CPUIDs and MSRs.
xen/arch/x86/hvm/svm/svm.c +62 -0
@@ -680,6 +680,26 @@ *(u16 *)(hypercall_page + (__HYPERVISOR_iret *32 )) =0x0b0f ;/* ud2 */ } +static void svm_lwp_save (struct vcpu *v) +{ +if ( cpu_has_lwp ) + { +rdmsrl (MSR_AMD64_LWP_CFG , v->arch.hvm_svm.guest_lwp_cfg); +wrmsrl (MSR_AMD64_LWP_CFG ,0x0 ); +/* Disable LWP for next VCPU */ +wrmsrl (MSR_AMD64_LWP_CBADDR ,0x0 ); + } +} + +static void svm_lwp_load (struct vcpu *v) +{ +if ( cpu_has_lwp ) + { +/* Only LWP_CFG is reloaded. LWP_CBADDR will be reloaded via xrstor */ +wrmsrl (MSR_AMD64_LWP_CFG , v->arch.hvm_svm.guest_lwp_cfg); + } +} +static void svm_ctxt_switch_from (struct vcpu *v) {int cpu =smp_processor_id ();
@@ -688,6 +708,7 @@svm_save_dr (v);vpmu_save (v); +svm_lwp_save (v);svm_sync_vmcb (v);svm_vmload (per_cpu (root_vmcb, cpu));
@@ -731,6 +752,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));
@@ -1100,6 +1122,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 avail bit and other features specified in lwp_cfg */ + *eax = (*edx & lwp_cfg) |0x00000001 ; + } +break ; + }default :break ; }
@@ -1189,6 +1229,10 @@case MSR_IA32_LASTINTTOIP : *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 :
@@ -1287,6 +1331,24 @@case MSR_IA32_LASTINTTOIP :vmcb_set_lastinttoip (vmcb, msr_content); +break ; + +case MSR_AMD64_LWP_CFG : +if ( cpu_has_lwp ) + { +unsigned int eax, ebx, ecx, edx; +uint32_t msr_low; + +hvm_cpuid (0x8000001c , &eax, &ebx, &ecx, &edx); + msr_low = (uint32_t )msr_content; + +/* generate #GP if guest triest to turn on unsupported features. */ +if ( msr_low & ~edx) + goto gpf; + +wrmsrl (msr, msr_content); + v->arch.hvm_svm.guest_lwp_cfg = msr_content; + }break ;case MSR_K7_PERFCTR0 :
xen/arch/x86/hvm/svm/vmcb.c +2 -0
@@ -120,6 +120,8 @@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 ); +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
@@ -507,6 +507,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
Quoted 10 lines
Quoted 1 line
Quoted 1 line · Wei Huang
xen/arch/x86/hvm/svm/svm.c +9
-0+static void svm_lwp_save (struct vcpu *v) +{ +if ( cpu_has_lwp ) + { +rdmsrl (MSR_AMD64_LWP_CFG , v->arch.hvm_svm.guest_lwp_cfg); +wrmsrl (MSR_AMD64_LWP_CFG ,0x0 ); +/* Disable LWP for next VCPU */ +wrmsrl (MSR_AMD64_LWP_CBADDR ,0x0 ); + }
xen/arch/x86/hvm/svm/svm.c line 701
Quoted 10 lines
xen/arch/x86/hvm/svm/svm.c +10
-0+} + +static void svm_lwp_load (struct vcpu *v) +{ +if ( cpu_has_lwp ) + { +/* Only LWP_CFG is reloaded. LWP_CBADDR will be reloaded via xrstor */ +wrmsrl (MSR_AMD64_LWP_CFG , v->arch.hvm_svm.guest_lwp_cfg); + } +}
I think I had pointed this out before - to avoid these MSR accesses for guests not using LWP, you should track whether the vCPU has LWP support enabled (e.g. non-zero written into LWP_CFG) and key off of that instead of cpu_has_lwp.
Jan