File 23897-x86-mce-offline-again.patch of Package xen

# HG changeset patch
# User Keir Fraser <keir@xen.org>
# Date 1317413803 -3600
# Node ID 2215d7d7382617adbe97831fe35752a027917d1d
# Parent  d568e2313fd6f055b66a6c3cb2bca6372b77692e
X86 MCE: Prevent malicious guest access broken page again

To avoid recursive mce.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Committed-by: Keir Fraser <keir@xen.org>

Index: xen-4.1.2-testing/xen/arch/x86/cpu/mcheck/mce_intel.c
===================================================================
--- xen-4.1.2-testing.orig/xen/arch/x86/cpu/mcheck/mce_intel.c
+++ xen-4.1.2-testing/xen/arch/x86/cpu/mcheck/mce_intel.c
@@ -639,6 +639,8 @@ static void intel_memerr_dhandler(int bn
     /* This is free page */
     if (status & PG_OFFLINE_OFFLINED)
         result->result = MCA_RECOVERED;
+    else if (status & PG_OFFLINE_AGAIN)
+        result->result = MCA_NO_ACTION;
     else if (status & PG_OFFLINE_PENDING) {
         /* This page has owner */
         if (status & PG_OFFLINE_OWNED) {
Index: xen-4.1.2-testing/xen/common/page_alloc.c
===================================================================
--- xen-4.1.2-testing.orig/xen/common/page_alloc.c
+++ xen-4.1.2-testing/xen/common/page_alloc.c
@@ -38,6 +38,7 @@
 #include <xen/tmem.h>
 #include <xen/tmem_xen.h>
 #include <public/sysctl.h>
+#include <public/sched.h>
 #include <asm/page.h>
 #include <asm/numa.h>
 #include <asm/flushtlb.h>
@@ -708,6 +709,19 @@ int offline_page(unsigned long mfn, int
         return -EINVAL;
     }
 
+    /*
+     * NB. When broken page belong to guest, usually hypervisor will
+     * notify the guest to handle the broken page. However, hypervisor
+     * need to prevent malicious guest access the broken page again.
+     * Under such case, hypervisor shutdown guest, preventing recursive mce.
+     */
+    if ( (pg->count_info & PGC_broken) && (owner = page_get_owner(pg)) )
+    {
+        *status = PG_OFFLINE_AGAIN;
+        domain_shutdown(owner, SHUTDOWN_crash);
+        return 0;
+    }
+
     spin_lock(&heap_lock);
 
     old_info = mark_page_offline(pg, broken);
Index: xen-4.1.2-testing/xen/include/public/sysctl.h
===================================================================
--- xen-4.1.2-testing.orig/xen/include/public/sysctl.h
+++ xen-4.1.2-testing/xen/include/public/sysctl.h
@@ -399,6 +399,7 @@ struct xen_sysctl_page_offline_op {
 #define PG_OFFLINE_OFFLINED  (0x1UL << 1)
 #define PG_OFFLINE_PENDING   (0x1UL << 2)
 #define PG_OFFLINE_FAILED    (0x1UL << 3)
+#define PG_OFFLINE_AGAIN     (0x1UL << 4)
 
 #define PG_ONLINE_FAILED     PG_OFFLINE_FAILED
 #define PG_ONLINE_ONLINED    PG_OFFLINE_OFFLINED
openSUSE Build Service is sponsored by