]> xenbits.xensource.com Git - xen.git/commitdiff
x86: add CMCI software injection interface
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jun 2010 06:51:31 +0000 (07:51 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jun 2010 06:51:31 +0000 (07:51 +0100)
A new command is added. User can set the target CPU map, since the
CMCI can be triggered on some specific CPUs.  Please be noticed that
the xenctl_cpumap structure is moved from domctl.h to xen.h.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
xen/arch/x86/cpu/mcheck/mce.c
xen/include/public/arch-x86/xen-mca.h
xen/include/public/domctl.h
xen/include/public/xen.h
xen/include/xlat.lst

index 14e97f7887e0375fcfac98cd929b9268260f6b81..25541a134d26bbf2d08372de100e5713f63f9d86 100644 (file)
@@ -1206,6 +1206,12 @@ static void x86_mc_mceinject(void *data)
        __asm__ __volatile__("int $0x12");
 }
 
+static void x86_cmci_inject(void *data)
+{
+       printk("Simulating CMCI on cpu %d\n", smp_processor_id());
+       __asm__ __volatile__("int $0xf7");
+}
+
 #if BITS_PER_LONG == 64
 
 #define        ID2COOKIE(id)   ((mctelem_cookie_t)(id))
@@ -1244,6 +1250,7 @@ CHECK_FIELD_(struct, mc_fetch, fetch_id);
 CHECK_FIELD_(struct, mc_physcpuinfo, ncpus);
 # define CHECK_compat_mc_physcpuinfo struct mc_physcpuinfo
 
+#define CHECK_compat_mc_inject_v2   struct mc_inject_v2
 CHECK_mc;
 # undef CHECK_compat_mc_fetch
 # undef CHECK_compat_mc_physcpuinfo
@@ -1449,6 +1456,52 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u_xen_mc)
                   mc_mceinject, 1);
                break;
 
+       case XEN_MC_inject_v2:
+       {
+               cpumask_t cpumap;
+
+               if (nr_mce_banks == 0)
+                       return x86_mcerr("do_mca #MC", -ENODEV);
+
+               if ( op->u.mc_inject_v2.flags & XEN_MC_INJECT_CPU_BROADCAST )
+                       cpus_copy(cpumap, cpu_online_map);
+               else
+               {
+                       int gcw;
+
+                       cpus_clear(cpumap);
+                       xenctl_cpumap_to_cpumask(&cpumap,
+                                       &op->u.mc_inject_v2.cpumap);
+                       gcw = cpus_weight(cpumap);
+                       cpus_and(cpumap, cpu_online_map, cpumap);
+
+                       if ( cpus_empty(cpumap) )
+                               return x86_mcerr("No online CPU passed\n", -EINVAL);
+                       else if ( gcw != cpus_weight(cpumap) )
+                               dprintk(XENLOG_INFO,
+                                       "Not all required CPUs are online\n");
+               }
+
+               switch (op->u.mc_inject_v2.flags & XEN_MC_INJECT_TYPE_MASK)
+               {
+               case XEN_MC_INJECT_TYPE_MCE:
+                       if ( mce_broadcast &&
+                         !cpus_equal(cpumap, cpu_online_map) )
+                               printk("Not trigger MCE on all CPUs, may HANG!\n");
+                       on_selected_cpus(&cpumap, x86_mc_mceinject, NULL, 1);
+                       break;
+               case XEN_MC_INJECT_TYPE_CMCI:
+                       if ( !cmci_support )
+                               return x86_mcerr(
+                               "No CMCI supported in platform\n", -EINVAL);
+                       on_selected_cpus(&cpumap, x86_cmci_inject, NULL, 1);
+                       break;
+               default:
+                       return x86_mcerr("Wrong mca type\n", -EINVAL);
+               }
+               break;
+       }
+
        default:
                return x86_mcerr("do_mca: bad command", -EINVAL);
        }
index 127971468871234cdb3bbb5d7706a15358bc05c2..dca6b3e8ff1f67fabcd12cd9b5fc5133559ac791 100644 (file)
@@ -404,6 +404,20 @@ struct xen_mc_mceinject {
        unsigned int mceinj_cpunr;      /* target processor id */
 };
 
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#define XEN_MC_inject_v2        6
+#define XEN_MC_INJECT_TYPE_MASK     0x7
+#define XEN_MC_INJECT_TYPE_MCE      0x0
+#define XEN_MC_INJECT_TYPE_CMCI     0x1
+
+#define XEN_MC_INJECT_CPU_BROADCAST 0x8
+
+struct xen_mc_inject_v2 {
+       uint32_t flags;
+       struct xenctl_cpumap cpumap;
+};
+#endif
+
 struct xen_mc {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
@@ -413,6 +427,9 @@ struct xen_mc {
         struct xen_mc_physcpuinfo  mc_physcpuinfo;
         struct xen_mc_msrinject    mc_msrinject;
         struct xen_mc_mceinject    mc_mceinject;
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+        struct xen_mc_inject_v2    mc_inject_v2;
+#endif
     } u;
 };
 typedef struct xen_mc xen_mc_t;
index 5bae1cb406db7603c45a75f091e2d7150e956113..5706726d425a79cc86d850bb872e7976d6ae8e2a 100644 (file)
 
 #define XEN_DOMCTL_INTERFACE_VERSION 0x00000007
 
-struct xenctl_cpumap {
-    XEN_GUEST_HANDLE_64(uint8) bitmap;
-    uint32_t nr_cpus;
-};
-
 /*
  * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
  * If it is specified as zero, an id is auto-allocated and returned.
index 8136b2eaf88c05722d85f378a5f08187db8a85cc..6c783412cfe0a4b72f330a219a547c2d4091acb2 100644 (file)
@@ -690,14 +690,23 @@ __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
 
 /* Default definitions for macros used by domctl/sysctl. */
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
+
 #ifndef uint64_aligned_t
 #define uint64_aligned_t uint64_t
 #endif
 #ifndef XEN_GUEST_HANDLE_64
 #define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
 #endif
+
+#ifndef __ASSEMBLY__
+struct xenctl_cpumap {
+    XEN_GUEST_HANDLE_64(uint8) bitmap;
+    uint32_t nr_cpus;
+};
 #endif
 
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
 #endif /* __XEN_PUBLIC_XEN_H__ */
 
 /*
index daf466f13b2fefd6338764e1827593dbd624a770..2b5b785b463b5b9de13e0875e5f5a57013276cc7 100644 (file)
@@ -2,6 +2,7 @@
 # ! - needs translation
 # ? - needs checking
 ?      dom0_vga_console_info           xen.h
+?   xenctl_cpumap               xen.h
 ?      mmu_update                      xen.h
 !      mmuext_op                       xen.h
 !      start_info                      xen.h