]> xenbits.xensource.com Git - xen.git/commitdiff
mce: Enhance the vmce injection check logic
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jun 2010 10:34:13 +0000 (11:34 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jun 2010 10:34:13 +0000 (11:34 +0100)
Currently we will not inject vMCE if guest has different mca control
register setup.

This is not enough, we need consider more. If guest has different
family/model, we should not inject guest, because the MCA error code
include model specific information. If guest has not enabled MCE
(i.e. CR4.X86_CR4_MCE is clear), we should not inject vMCE.

One thing need notice. In the memory error handler, we didn't kill the
guest if vMCE is not ready, instead, we will simply ignore the
vMCE. In native, system will reboot if MCE in CR4 is not enabled. We
need contain guest access to the broken memory through eithe software
or hardware method.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
xen/arch/x86/cpu/mcheck/mce.h
xen/arch/x86/cpu/mcheck/mce_intel.c
xen/arch/x86/cpu/mcheck/vmce.c

index 637daca755a49482ac4b297cf1d5a5c3b6fa66af..a66fe2c1fc65ae0daa6d22ac9cd96dbe92184d77 100644 (file)
@@ -48,9 +48,10 @@ void intel_mcheck_timer(struct cpuinfo_x86 *c);
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
 void amd_nonfatal_mcheck_init(struct cpuinfo_x86 *c);
 
+int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d);
+
 u64 mce_cap_init(void);
 extern int firstbank;
-int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d);
 
 int intel_mce_rdmsr(uint32_t msr, uint64_t *val);
 int intel_mce_wrmsr(uint32_t msr, uint64_t val);
index e18e7d23b0d54b4765cc812127b2cc870e69ff1d..838acc95e22da5ca79060447d18e70937ce3a10c 100644 (file)
@@ -654,9 +654,9 @@ static void intel_memerr_dhandler(int bnum,
             BUG_ON( result->owner == DOMID_COW );
             if ( result->owner != DOMID_XEN ) {
                 d = get_domain_by_id(result->owner);
-                if ( mca_ctl_conflict(bank, d) )
+                if ( !is_vmce_ready(bank, d) )
                 {
-                    /* Guest has different MCE ctl with hypervisor */
+                    /* Should not inject vMCE to guest */
                     if ( d )
                         put_domain(d);
                     return;
index b2dca25afe83a29f27cfdeaba5a3e4bf36227c89..7a26a1f0775365455318daf4cabfdcc397414f3c 100644 (file)
@@ -468,7 +468,7 @@ int vmce_init(struct cpuinfo_x86 *c)
     return 0;
 }
 
-int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
+static int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
 {
     int bank_nr;
 
@@ -484,3 +484,79 @@ int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
         return 1;
     return 0;
 }
+
+static int is_hvm_vmce_ready(struct mcinfo_bank *bank, struct domain *d)
+{
+    struct vcpu *v;
+    int no_vmce = 0, i;
+
+    if (!is_hvm_domain(d))
+        return 0;
+
+    /* kill guest if not enabled vMCE */
+    for_each_vcpu(d, v)
+    {
+        if (!(v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_MCE))
+        {
+            no_vmce = 1;
+            break;
+        }
+
+        if (!mce_broadcast)
+            break;
+    }
+
+    if (no_vmce)
+        return 0;
+
+    /* Guest has virtualized family/model information */
+    for ( i = 0; i < MAX_CPUID_INPUT; i++ )
+    {
+        if (d->arch.cpuids[i].input[0] == 0x1)
+        {
+            uint32_t veax = d->arch.cpuids[i].eax, vfam, vmod;
+
+                       vfam = (veax >> 8) & 15;
+                       vmod = (veax >> 4) & 15;
+
+            if (vfam == 0x6 || vfam == 0xf)
+                vmod += ((veax >> 16) & 0xF) << 4;
+                       if (vfam == 0xf)
+                               vfam += (veax >> 20) & 0xff;
+
+            if ( ( vfam != boot_cpu_data.x86 ) ||
+                 (vmod != boot_cpu_data.x86_model) )
+            {
+                dprintk(XENLOG_WARNING,
+                    "No vmce for different virtual family/model cpuid\n");
+                no_vmce = 1;
+            }
+            break;
+        }
+    }
+
+    if (no_vmce)
+        return 0;
+
+    /* Guest has different MCE ctl value setting */
+    if (mca_ctl_conflict(bank, d))
+    {
+        dprintk(XENLOG_WARNING,
+          "No vmce, guest has different mca control setting\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d)
+{
+    if ( d == dom0)
+        return dom0_vmce_enabled();
+
+    /* No vMCE to HVM guest now */
+    if ( is_hvm_domain(d) )
+        return is_hvm_vmce_ready(bank, d);
+
+    return 0;
+}