diff options
author | Andrew Cooper <andrew.cooper3@citrix.com> | 2017-09-20 18:33:59 +0100 |
---|---|---|
committer | Andrew Cooper <andrew.cooper3@citrix.com> | 2018-09-24 16:25:36 +0100 |
commit | bd7099a674819c0709bd058793adea2e76b42a6b (patch) | |
tree | 896cf0bba2780b6b3b677b1a788802d16db33fa1 /xen/arch/x86/msr.c | |
parent | cd8015b634b005a3911bd6025351cd854d63a82a (diff) |
x86/msr: Dispatch Xen and Viridian MSRs from guest_{wr,rd}msr()
Despite the complicated diff in {svm,vmx}_msr_write_intercept(), it is just
the 0 case losing one level of indentation, as part of removing the call to
wrmsr_hypervisor_regs().
The case blocks in guest_{wr,rd}msr() use raw numbers, partly for consistency
with the CPUID side of things, but mainly because this is clearer code to
follow. In particular, the Xen block may overlap with the Viridian block if
Viridian is not enabled for the domain, and trying to express this with named
literals caused more confusion that it solved.
Future changes with clean up the individual APIs, including allowing these
MSRs to be usable for vcpus other than current (no callers exist with v !=
current).
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Diffstat (limited to 'xen/arch/x86/msr.c')
-rw-r--r-- | xen/arch/x86/msr.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c index b675f3ac02..6fe3ad7a16 100644 --- a/xen/arch/x86/msr.c +++ b/xen/arch/x86/msr.c @@ -114,9 +114,11 @@ int init_vcpu_msr_policy(struct vcpu *v) int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val) { - const struct cpuid_policy *cp = v->domain->arch.cpuid; - const struct msr_policy *mp = v->domain->arch.msr; + const struct domain *d = v->domain; + const struct cpuid_policy *cp = d->arch.cpuid; + const struct msr_policy *mp = d->arch.msr; const struct vcpu_msrs *msrs = v->arch.msrs; + int ret = X86EMUL_OKAY; switch ( msr ) { @@ -145,11 +147,31 @@ int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val) *val = msrs->misc_features_enables.raw; break; + case 0x40000000 ... 0x400001ff: + if ( is_viridian_domain(d) ) + { + ret = (rdmsr_viridian_regs(msr, val) + ? X86EMUL_OKAY : X86EMUL_EXCEPTION); + break; + } + + /* Fallthrough. */ + case 0x40000200 ... 0x400002ff: + ret = (rdmsr_hypervisor_regs(msr, val) + ? X86EMUL_OKAY : X86EMUL_EXCEPTION); + break; + default: return X86EMUL_UNHANDLEABLE; } - return X86EMUL_OKAY; + /* + * Interim safety check that functions we dispatch to don't alias "Not yet + * handled by the new MSR infrastructure". + */ + ASSERT(ret != X86EMUL_UNHANDLEABLE); + + return ret; gp_fault: return X86EMUL_EXCEPTION; @@ -162,6 +184,7 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) const struct cpuid_policy *cp = d->arch.cpuid; const struct msr_policy *mp = d->arch.msr; struct vcpu_msrs *msrs = v->arch.msrs; + int ret = X86EMUL_OKAY; switch ( msr ) { @@ -252,11 +275,35 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) break; } + case 0x40000000 ... 0x400001ff: + if ( is_viridian_domain(d) ) + { + ret = (wrmsr_viridian_regs(msr, val) + ? X86EMUL_OKAY : X86EMUL_EXCEPTION); + break; + } + + /* Fallthrough. */ + case 0x40000200 ... 0x400002ff: + switch ( wrmsr_hypervisor_regs(msr, val) ) + { + case -ERESTART: ret = X86EMUL_RETRY; break; + case 1: ret = X86EMUL_OKAY; break; + default: ret = X86EMUL_EXCEPTION; break; + } + break; + default: return X86EMUL_UNHANDLEABLE; } - return X86EMUL_OKAY; + /* + * Interim safety check that functions we dispatch to don't alias "Not yet + * handled by the new MSR infrastructure". + */ + ASSERT(ret != X86EMUL_UNHANDLEABLE); + + return ret; gp_fault: return X86EMUL_EXCEPTION; |