Inject LMCE to guest if the host MCE is LMCE and the affected vcpu is
known. Otherwise, broadcast MCE to all vcpus on Intel host.

Signed-off-by: Haozhong Zhang <haozhong.zh...@intel.com>
---
Cc: Christoph Egger <cheg...@amazon.de>
Cc: Liu Jinsong <jinsong....@alibaba-inc.com>
Cc: Jan Beulich <jbeul...@suse.com>
Cc: Andrew Cooper <andrew.coop...@citrix.com>
---
 xen/arch/x86/cpu/mcheck/mcaction.c | 14 ++++++++------
 xen/arch/x86/cpu/mcheck/vmce.c     |  9 ++++++++-
 xen/arch/x86/cpu/mcheck/vmce.h     |  2 +-
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/cpu/mcheck/mcaction.c 
b/xen/arch/x86/cpu/mcheck/mcaction.c
index 90c68ff..3410bfd 100644
--- a/xen/arch/x86/cpu/mcheck/mcaction.c
+++ b/xen/arch/x86/cpu/mcheck/mcaction.c
@@ -88,17 +88,19 @@ mc_memerr_dhandler(struct mca_binfo *binfo,
                     goto vmce_failed;
                 }
 
-                if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+                vmce_vcpuid = global->mc_vcpuid;
+                if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+                     (vmce_vcpuid == -1 ||
+                      global->mc_domid != bank->mc_domid ||
+                      !(global->mc_gstatus & MCG_STATUS_LMCE) ||
+                      !d->vcpu[vmce_vcpuid]->arch.vmce.lmce_enabled) )
                     vmce_vcpuid = VMCE_INJECT_BROADCAST;
-                else
-                    vmce_vcpuid = global->mc_vcpuid;
 
                 bank->mc_addr = gfn << PAGE_SHIFT |
                   (bank->mc_addr & (PAGE_SIZE -1 ));
-                /* TODO: support injecting LMCE */
                 if ( fill_vmsr_data(bank, d,
-                                    global->mc_gstatus & ~MCG_STATUS_LMCE,
-                                    vmce_vcpuid == VMCE_INJECT_BROADCAST) == 
-1 )
+                                    global->mc_gstatus,
+                                    vmce_vcpuid) == -1 )
                 {
                     mce_printk(MCE_QUIET, "Fill vMCE# data for DOM%d "
                       "failed\n", bank->mc_domid);
diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
index 1278839..2a4d3f0 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.c
+++ b/xen/arch/x86/cpu/mcheck/vmce.c
@@ -444,14 +444,21 @@ static int vcpu_fill_mc_msrs(struct vcpu *v, uint64_t 
mcg_status,
 }
 
 int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d,
-                   uint64_t gstatus, bool broadcast)
+                   uint64_t gstatus, int vmce_vcpuid)
 {
     struct vcpu *v = d->vcpu[0];
+    bool broadcast = (vmce_vcpuid == VMCE_INJECT_BROADCAST);
     int ret;
 
     if ( mc_bank->mc_domid == (uint16_t)~0 )
         return -EINVAL;
 
+    if ( (gstatus & MCG_STATUS_LMCE) && !broadcast )
+        v = d->vcpu[vmce_vcpuid];
+
+    if ( broadcast )
+        gstatus &= ~MCG_STATUS_LMCE;
+
     ret = vcpu_fill_mc_msrs(v, gstatus, mc_bank->mc_status,
                             mc_bank->mc_addr, mc_bank->mc_misc);
     if ( ret || !broadcast )
diff --git a/xen/arch/x86/cpu/mcheck/vmce.h b/xen/arch/x86/cpu/mcheck/vmce.h
index 74f6381..2797e00 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.h
+++ b/xen/arch/x86/cpu/mcheck/vmce.h
@@ -17,7 +17,7 @@ int vmce_amd_rdmsr(const struct vcpu *, uint32_t msr, 
uint64_t *val);
 int vmce_amd_wrmsr(struct vcpu *, uint32_t msr, uint64_t val);
 
 int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d,
-                   uint64_t gstatus, bool broadcast);
+                   uint64_t gstatus, int vmce_vcpuid);
 
 #define VMCE_INJECT_BROADCAST (-1)
 int inject_vmce(struct domain *d, int vcpu);
-- 
2.10.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

Reply via email to