aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/misc/xen-hvmctx.c2
-rw-r--r--xen/arch/x86/cpu/mcheck/vmce.c22
-rw-r--r--xen/arch/x86/domctl.c24
-rw-r--r--xen/include/asm-x86/mce.h2
-rw-r--r--xen/include/public/arch-x86/hvm/save.h2
-rw-r--r--xen/include/public/domctl.h10
6 files changed, 47 insertions, 15 deletions
diff --git a/tools/misc/xen-hvmctx.c b/tools/misc/xen-hvmctx.c
index 52f714b5de..edcebec00a 100644
--- a/tools/misc/xen-hvmctx.c
+++ b/tools/misc/xen-hvmctx.c
@@ -388,6 +388,8 @@ static void dump_vmce_vcpu(void)
HVM_SAVE_TYPE(VMCE_VCPU) p;
READ(p);
printf(" VMCE_VCPU: caps %" PRIx64 "\n", p.caps);
+ printf(" VMCE_VCPU: bank0 mci_ctl2 %" PRIx64 "\n", p.mci_ctl2_bank0);
+ printf(" VMCE_VCPU: bank1 mci_ctl2 %" PRIx64 "\n", p.mci_ctl2_bank1);
}
int main(int argc, char **argv)
diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
index 1432870e53..cc1d48f524 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.c
+++ b/xen/arch/x86/cpu/mcheck/vmce.c
@@ -68,7 +68,7 @@ void vmce_init_vcpu(struct vcpu *v)
spin_lock_init(&v->arch.vmce.lock);
}
-int vmce_restore_vcpu(struct vcpu *v, uint64_t caps)
+int vmce_restore_vcpu(struct vcpu *v, const struct hvm_vmce_vcpu *ctxt)
{
unsigned long guest_mcg_cap;
@@ -77,16 +77,20 @@ int vmce_restore_vcpu(struct vcpu *v, uint64_t caps)
else
guest_mcg_cap = AMD_GUEST_MCG_CAP;
- if ( caps & ~guest_mcg_cap & ~MCG_CAP_COUNT & ~MCG_CTL_P )
+ if ( ctxt->caps & ~guest_mcg_cap & ~MCG_CAP_COUNT & ~MCG_CTL_P )
{
dprintk(XENLOG_G_ERR, "%s restore: unsupported MCA capabilities"
" %#" PRIx64 " for d%d:v%u (supported: %#Lx)\n",
- is_hvm_vcpu(v) ? "HVM" : "PV", caps, v->domain->domain_id,
- v->vcpu_id, guest_mcg_cap & ~MCG_CAP_COUNT);
+ is_hvm_vcpu(v) ? "HVM" : "PV", ctxt->caps,
+ v->domain->domain_id, v->vcpu_id,
+ guest_mcg_cap & ~MCG_CAP_COUNT);
return -EPERM;
}
- v->arch.vmce.mcg_cap = caps;
+ v->arch.vmce.mcg_cap = ctxt->caps;
+ v->arch.vmce.bank[0].mci_ctl2 = ctxt->mci_ctl2_bank0;
+ v->arch.vmce.bank[1].mci_ctl2 = ctxt->mci_ctl2_bank1;
+
return 0;
}
@@ -291,7 +295,9 @@ static int vmce_save_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h)
for_each_vcpu( d, v ) {
struct hvm_vmce_vcpu ctxt = {
- .caps = v->arch.vmce.mcg_cap
+ .caps = v->arch.vmce.mcg_cap,
+ .mci_ctl2_bank0 = v->arch.vmce.bank[0].mci_ctl2,
+ .mci_ctl2_bank1 = v->arch.vmce.bank[1].mci_ctl2
};
err = hvm_save_entry(VMCE_VCPU, v->vcpu_id, h, &ctxt);
@@ -316,9 +322,9 @@ static int vmce_load_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h)
err = -EINVAL;
}
else
- err = hvm_load_entry(VMCE_VCPU, h, &ctxt);
+ err = hvm_load_entry_zeroextend(VMCE_VCPU, h, &ctxt);
- return err ?: vmce_restore_vcpu(v, ctxt.caps);
+ return err ?: vmce_restore_vcpu(v, &ctxt);
}
HVM_REGISTER_SAVE_RESTORE(VMCE_VCPU, vmce_save_vcpu_ctxt,
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index cb51252ac5..24b317884e 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1066,12 +1066,14 @@ long arch_do_domctl(
evc->syscall32_callback_eip = 0;
evc->syscall32_disables_events = 0;
}
- evc->mcg_cap = v->arch.vmce.mcg_cap;
+ evc->vmce.caps = v->arch.vmce.mcg_cap;
+ evc->vmce.mci_ctl2_bank0 = v->arch.vmce.bank[0].mci_ctl2;
+ evc->vmce.mci_ctl2_bank1 = v->arch.vmce.bank[1].mci_ctl2;
}
else
{
ret = -EINVAL;
- if ( evc->size < offsetof(typeof(*evc), mcg_cap) )
+ if ( evc->size < offsetof(typeof(*evc), vmce) )
goto ext_vcpucontext_out;
if ( !is_hvm_domain(d) )
{
@@ -1101,9 +1103,21 @@ long arch_do_domctl(
evc->syscall32_callback_eip )
goto ext_vcpucontext_out;
- if ( evc->size >= offsetof(typeof(*evc), mcg_cap) +
- sizeof(evc->mcg_cap) )
- ret = vmce_restore_vcpu(v, evc->mcg_cap);
+ BUILD_BUG_ON(offsetof(struct xen_domctl_ext_vcpucontext,
+ mcg_cap) !=
+ offsetof(struct xen_domctl_ext_vcpucontext,
+ vmce.caps));
+ BUILD_BUG_ON(sizeof(evc->mcg_cap) != sizeof(evc->vmce.caps));
+ if ( evc->size >= offsetof(typeof(*evc), vmce) +
+ sizeof(evc->vmce) )
+ ret = vmce_restore_vcpu(v, &evc->vmce);
+ else if ( evc->size >= offsetof(typeof(*evc), mcg_cap) +
+ sizeof(evc->mcg_cap) )
+ {
+ struct hvm_vmce_vcpu vmce = { .caps = evc->mcg_cap };
+
+ ret = vmce_restore_vcpu(v, &vmce);
+ }
}
ret = 0;
diff --git a/xen/include/asm-x86/mce.h b/xen/include/asm-x86/mce.h
index a4eea47782..549bef3ebe 100644
--- a/xen/include/asm-x86/mce.h
+++ b/xen/include/asm-x86/mce.h
@@ -33,7 +33,7 @@ struct vmce {
/* Guest vMCE MSRs virtualization */
extern void vmce_init_vcpu(struct vcpu *);
-extern int vmce_restore_vcpu(struct vcpu *, uint64_t caps);
+extern int vmce_restore_vcpu(struct vcpu *, const struct hvm_vmce_vcpu *);
extern int vmce_wrmsr(uint32_t msr, uint64_t val);
extern int vmce_rdmsr(uint32_t msr, uint64_t *val);
diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h
index 9ae645db8a..8475edbac2 100644
--- a/xen/include/public/arch-x86/hvm/save.h
+++ b/xen/include/public/arch-x86/hvm/save.h
@@ -577,6 +577,8 @@ DECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);
struct hvm_vmce_vcpu {
uint64_t caps;
+ uint64_t mci_ctl2_bank0;
+ uint64_t mci_ctl2_bank1;
};
DECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index f367ce2b2c..a5836470ea 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -32,6 +32,7 @@
#error "domctl operations are intended for use by node control tools only"
#endif
+#include <xen/hvm/save.h>
#include "xen.h"
#include "grant_table.h"
@@ -564,7 +565,14 @@ struct xen_domctl_ext_vcpucontext {
uint16_t sysenter_callback_cs;
uint8_t syscall32_disables_events;
uint8_t sysenter_disables_events;
- uint64_aligned_t mcg_cap;
+#if defined(__GNUC__)
+ union {
+ uint64_aligned_t mcg_cap;
+ struct hvm_vmce_vcpu vmce;
+ };
+#else
+ struct hvm_vmce_vcpu vmce;
+#endif
#endif
};
typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t;