mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/msr: introduce guest_rdmsr()
The new function is responsible for handling RDMSR from both HVM and PV
guests. Currently it handles only 2 MSRs:
MSR_INTEL_PLATFORM_INFO
MSR_INTEL_MISC_FEATURES_ENABLES
It has a different behaviour compared to the old MSR handlers: if MSR
is being handled by guest_rdmsr() then RDMSR will either succeed (if
a guest is allowed to access it based on its MSR policy) or produce
a GP fault. A guest will never see a H/W value of some MSR unknown to
this function.
guest_rdmsr() unifies and replaces the handling code from
vmx_msr_read_intercept() and priv_op_read_msr().
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
This (along with the prep work in init_domain_msr_policy()) also fixes
a bug where Dom0 could probe and find CPUID faulting, even though it
couldn't actually use it.
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
1 parent
e7a370733b
commit
37f074a338
5 files changed
+49
-29
No files matched your search
@@ -3362,11 +3362,16 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
|
||||
struct vcpu *v = current;
|
||||
struct domain *d = v->domain;
|
||||
uint64_t *var_range_base, *fixed_range_base;
|
||||
int ret = X86EMUL_OKAY;
|
||||
int ret;
|
||||
|
||||
var_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.var_ranges;
|
||||
fixed_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.fixed_ranges;
|
||||
|
||||
if ( (ret = guest_rdmsr(v, msr, msr_content)) != X86EMUL_UNHANDLEABLE )
|
||||
return ret;
|
||||
|
||||
ret = X86EMUL_OKAY;
|
||||
|
||||
switch ( msr )
|
||||
{
|
||||
unsigned int index;
|
||||
|
||||
@@ -2907,16 +2907,6 @@ static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
|
||||
goto gp_fault;
|
||||
break;
|
||||
|
||||
case MSR_INTEL_PLATFORM_INFO:
|
||||
*msr_content = MSR_PLATFORM_INFO_CPUID_FAULTING;
|
||||
break;
|
||||
|
||||
case MSR_INTEL_MISC_FEATURES_ENABLES:
|
||||
*msr_content = 0;
|
||||
if ( current->arch.msr->misc_features_enables.cpuid_faulting )
|
||||
*msr_content |= MSR_MISC_FEATURES_CPUID_FAULTING;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( passive_domain_do_rdmsr(msr, msr_content) )
|
||||
goto done;
|
||||
|
||||
@@ -117,6 +117,37 @@ int init_vcpu_msr_policy(struct vcpu *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
|
||||
{
|
||||
const struct msr_domain_policy *dp = v->domain->arch.msr;
|
||||
const struct msr_vcpu_policy *vp = v->arch.msr;
|
||||
|
||||
switch ( msr )
|
||||
{
|
||||
case MSR_INTEL_PLATFORM_INFO:
|
||||
if ( !dp->plaform_info.available )
|
||||
goto gp_fault;
|
||||
*val = (uint64_t)dp->plaform_info.cpuid_faulting <<
|
||||
_MSR_PLATFORM_INFO_CPUID_FAULTING;
|
||||
break;
|
||||
|
||||
case MSR_INTEL_MISC_FEATURES_ENABLES:
|
||||
if ( !vp->misc_features_enables.available )
|
||||
goto gp_fault;
|
||||
*val = (uint64_t)vp->misc_features_enables.cpuid_faulting <<
|
||||
_MSR_MISC_FEATURES_CPUID_FAULTING;
|
||||
break;
|
||||
|
||||
default:
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
}
|
||||
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
gp_fault:
|
||||
return X86EMUL_EXCEPTION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -841,6 +841,10 @@ static int read_msr(unsigned int reg, uint64_t *val,
|
||||
const struct vcpu *curr = current;
|
||||
const struct domain *currd = curr->domain;
|
||||
bool vpmu_msr = false;
|
||||
int ret;
|
||||
|
||||
if ( (ret = guest_rdmsr(curr, reg, val)) != X86EMUL_UNHANDLEABLE )
|
||||
return ret;
|
||||
|
||||
switch ( reg )
|
||||
{
|
||||
@@ -941,24 +945,6 @@ static int read_msr(unsigned int reg, uint64_t *val,
|
||||
*val = 0;
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
case MSR_INTEL_PLATFORM_INFO:
|
||||
if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
|
||||
rdmsr_safe(MSR_INTEL_PLATFORM_INFO, *val) )
|
||||
break;
|
||||
*val = 0;
|
||||
if ( this_cpu(cpuid_faulting_enabled) )
|
||||
*val |= MSR_PLATFORM_INFO_CPUID_FAULTING;
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
case MSR_INTEL_MISC_FEATURES_ENABLES:
|
||||
if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
|
||||
rdmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES, *val) )
|
||||
break;
|
||||
*val = 0;
|
||||
if ( curr->arch.msr->misc_features_enables.cpuid_faulting )
|
||||
*val |= MSR_MISC_FEATURES_CPUID_FAULTING;
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
case MSR_P6_PERFCTR(0) ... MSR_P6_PERFCTR(7):
|
||||
case MSR_P6_EVNTSEL(0) ... MSR_P6_EVNTSEL(3):
|
||||
case MSR_CORE_PERF_FIXED_CTR0 ... MSR_CORE_PERF_FIXED_CTR2:
|
||||
|
||||
@@ -226,6 +226,14 @@ void init_guest_msr_policy(void);
|
||||
int init_domain_msr_policy(struct domain *d);
|
||||
int init_vcpu_msr_policy(struct vcpu *v);
|
||||
|
||||
/*
|
||||
* Below functions can return X86EMUL_UNHANDLEABLE which means that MSR is
|
||||
* not (yet) handled by it and must be processed by legacy handlers. Such
|
||||
* behaviour is needed for transition period until all rd/wrmsr are handled
|
||||
* by the new MSR infrastructure.
|
||||
*/
|
||||
int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_MSR_H */
|
||||