summaryrefslogtreecommitdiff
path: root/xen/arch/x86/msr.c
diff options
context:
space:
mode:
authorAndrew Cooper <andrew.cooper3@citrix.com>2017-09-20 18:33:59 +0100
committerAndrew Cooper <andrew.cooper3@citrix.com>2018-09-24 16:25:36 +0100
commitbd7099a674819c0709bd058793adea2e76b42a6b (patch)
tree896cf0bba2780b6b3b677b1a788802d16db33fa1 /xen/arch/x86/msr.c
parentcd8015b634b005a3911bd6025351cd854d63a82a (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.c55
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;