diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index ca64903132..466a1a2fac 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -351,13 +351,27 @@ int vcpu_initialise(struct vcpu *v) /* Idle domain */ v->arch.cr3 = __pa(idle_pg_table); rc = 0; + v->arch.msr = ZERO_BLOCK_PTR; /* Catch stray misuses */ } if ( rc ) - vcpu_destroy_fpu(v); - else if ( !is_idle_domain(v->domain) ) + goto fail; + + if ( !is_idle_domain(v->domain) ) + { vpmu_initialise(v); + if ( (rc = init_vcpu_msr_policy(v)) ) + goto fail; + } + + return rc; + + fail: + vcpu_destroy_fpu(v); + xfree(v->arch.msr); + v->arch.msr = NULL; + return rc; } diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c index eac50ec897..b5ad97d3c8 100644 --- a/xen/arch/x86/msr.c +++ b/xen/arch/x86/msr.c @@ -27,9 +27,13 @@ struct msr_domain_policy __read_mostly hvm_max_msr_domain_policy, __read_mostly pv_max_msr_domain_policy; +struct msr_vcpu_policy __read_mostly hvm_max_msr_vcpu_policy, + __read_mostly pv_max_msr_vcpu_policy; + static void __init calculate_hvm_max_policy(void) { struct msr_domain_policy *dp = &hvm_max_msr_domain_policy; + struct msr_vcpu_policy *vp = &hvm_max_msr_vcpu_policy; if ( !hvm_enabled ) return; @@ -40,11 +44,15 @@ static void __init calculate_hvm_max_policy(void) dp->plaform_info.available = true; dp->plaform_info.cpuid_faulting = true; } + + /* 0x00000140 MSR_INTEL_MISC_FEATURES_ENABLES */ + vp->misc_features_enables.available = dp->plaform_info.available; } static void __init calculate_pv_max_policy(void) { struct msr_domain_policy *dp = &pv_max_msr_domain_policy; + struct msr_vcpu_policy *vp = &pv_max_msr_vcpu_policy; /* 0x000000ce MSR_INTEL_PLATFORM_INFO */ if ( cpu_has_cpuid_faulting ) @@ -52,6 +60,9 @@ static void __init calculate_pv_max_policy(void) dp->plaform_info.available = true; dp->plaform_info.cpuid_faulting = true; } + + /* 0x00000140 MSR_INTEL_MISC_FEATURES_ENABLES */ + vp->misc_features_enables.available = dp->plaform_info.available; } void __init init_guest_msr_policy(void) @@ -84,6 +95,28 @@ int init_domain_msr_policy(struct domain *d) return 0; } +int init_vcpu_msr_policy(struct vcpu *v) +{ + struct domain *d = v->domain; + struct msr_vcpu_policy *vp; + + vp = xmalloc(struct msr_vcpu_policy); + + if ( !vp ) + return -ENOMEM; + + *vp = is_pv_domain(d) ? pv_max_msr_vcpu_policy : + hvm_max_msr_vcpu_policy; + + /* See comment in intel_ctxt_switch_levelling() */ + if ( is_control_domain(d) ) + vp->misc_features_enables.available = false; + + v->arch.msr = vp; + + return 0; +} + /* * Local variables: * mode: C diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 1734eb0e25..028bbd2ed3 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -577,6 +577,8 @@ struct arch_vcpu struct arch_vm_event *vm_event; + struct msr_vcpu_policy *msr; + struct { bool next_interrupt_enabled; } monitor; diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h index 5cf7be1821..7c8395b9b3 100644 --- a/xen/include/asm-x86/msr.h +++ b/xen/include/asm-x86/msr.h @@ -212,8 +212,19 @@ struct msr_domain_policy } plaform_info; }; +/* MSR policy object for per-vCPU MSRs */ +struct msr_vcpu_policy +{ + /* 0x00000140 MSR_INTEL_MISC_FEATURES_ENABLES */ + struct { + bool available; /* This MSR is non-architectural */ + bool cpuid_faulting; + } misc_features_enables; +}; + void init_guest_msr_policy(void); int init_domain_msr_policy(struct domain *d); +int init_vcpu_msr_policy(struct vcpu *v); #endif /* !__ASSEMBLY__ */