[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Xen MCE test: utilities to inject fake MCE for X86



# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1293186087 0
# Node ID 1bc031edae047e00aebe449f93e0758f0c75e732
# Parent  97779ffa76f5dc0bef8cfaa81b94442fdf2e9a40
Xen MCE test: utilities to inject fake MCE for X86

A software MCE injection tool, which is based on Xen MCE injection
mechanism. It fake MCE error and inject this error to a assigned
Domain Physical Address.  Makefile make sure the tool can be built on
Xen.  A README explain the usage for this tool.

Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Haicheng Li<haicheng.li@xxxxxxxxx>
Signed-off-by: Xudong Hao <xudong.hao@xxxxxxxxx>
---
 tools/tests/mce-test/tools/Makefile     |   27 +
 tools/tests/mce-test/tools/README       |   24 +
 tools/tests/mce-test/tools/xen-mceinj.c |  645 ++++++++++++++++++++++++++++++++
 3 files changed, 696 insertions(+)

diff -r 97779ffa76f5 -r 1bc031edae04 tools/tests/mce-test/tools/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tests/mce-test/tools/Makefile       Fri Dec 24 10:21:27 2010 +0000
@@ -0,0 +1,27 @@
+XEN_ROOT=../../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS   += -Werror
+
+INCLUDES += -I $(XEN_XC)
+INCLUDES += -I $(XEN_LIBXC)
+INCLUDES += -I $(XEN_INCLUDE)
+CFLAGS   += $(INCLUDES)
+
+HDRS     = $(wildcard *.h)
+
+.PHONY: all
+all: xen-mceinj
+
+install: 
+       cp xen-mceinj /usr/sbin/
+
+.PHONY: clean
+clean:
+       $(RM) *.o xen-mceinj
+
+%.o: %.c $(HDRS) Makefile
+       $(CC) -c $(CFLAGS) -o $@ $<
+
+xen-mceinj: %: %.o Makefile
+       $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LDLIBS_libxenctrl) 
$(LDLIBS_libxenguest) $(LDLIBS_libxenstore)
diff -r 97779ffa76f5 -r 1bc031edae04 tools/tests/mce-test/tools/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tests/mce-test/tools/README Fri Dec 24 10:21:27 2010 +0000
@@ -0,0 +1,24 @@
+Xen Machine Check Exception(MCE) error inject tool
+----------------------------------------------
+
+xen-mceinj is a software MCE injection tool, which is based on Xen 
+MCE injection mechanism. It allows to inject machine check errors on the
+software level into a running Xen/dom0/VM. This is intended for
+validation of the Xen machine check handler.
+
+With the help of the Makefile, it is possible to compile a binary file 
+named "xen-mceinj".
+
+Usage
+-----
+$make (make install) --Note: make sure compile xen/tools before do this step
+$./xen-mceinj [OPTION]...
+
+OPTION arguments can be:
+  -D, --dump           dump addr info without error injection
+  -c, --cpu=CPU_ID     target CPU, the default is CPU0
+  -d, --domain=DomID   target domain, the default is Xen itself
+  -p, --page           physical page address, the default is 0x180020
+  -t, --type=error     error type
+
+For detail help, please refer to "./xen-mceinj -h"
diff -r 97779ffa76f5 -r 1bc031edae04 tools/tests/mce-test/tools/xen-mceinj.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tests/mce-test/tools/xen-mceinj.c   Fri Dec 24 10:21:27 2010 +0000
@@ -0,0 +1,645 @@
+/*
+ * xen-mceinj.c: utilities to inject fake MCE for x86.
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ * 
+ * Authors: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
+ *          Haicheng Li <haicheng.li@xxxxxxxxx>
+ *          Xudong Hao <xudong.hao@xxxxxxxxx>
+ */
+
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+
+#include <xenctrl.h>
+#include <xg_private.h>
+#include <xenguest.h>
+#include <inttypes.h>
+#include <sys/time.h>
+#include <xen/arch-x86/xen-mca.h>
+#include <xg_save_restore.h>
+#include <xs.h>
+
+#define MCi_type_CTL        0x0
+#define MCi_type_STATUS     0x1
+#define MCi_type_ADDR       0x2
+#define MCi_type_MISC       0x3
+#define MCi_type_CTL2       0x4
+
+#define INVALID_MSR         ~0UL
+
+/* Intel MSRs */
+#define MSR_IA32_MCG_CAP         0x00000179
+#define MSR_IA32_MCG_STATUS      0x0000017a
+#define MSR_IA32_MCG_CTL         0x0000017b
+#define MSR_IA32_MC0_CTL         0x00000400
+#define MSR_IA32_MC0_STATUS      0x00000401
+#define MSR_IA32_MC0_ADDR        0x00000402
+#define MSR_IA32_MC0_MISC        0x00000403
+#define MSR_IA32_MC0_CTL2        0x00000280
+
+/* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
+#define MCG_STATUS_SRAO_LLC_VAL  0x5
+#define MCE_SRAO_LLC_BANK        0x7
+#define MCi_STATUS_SRAO_LLC_VAL  0xBD2000008000017AUL
+#define MCi_MISC_SRAO_LLC_VAL    0x86UL
+
+/* Memory Patrol Scrub SRAO MCE */
+#define MCG_STATUS_SRAO_MEM_VAL  0x5
+#define MCE_SRAO_MEM_BANK        0x8
+#define MCi_STATUS_SRAO_MEM_VAL  0xBD000000004000CFUL
+#define MCi_MISC_SRAO_MEM_VAL    0x86UL
+
+/* LLC EWB UCNA Error */
+#define MCG_STATUS_UCNA_LLC_VAL  0x0
+#define CMCI_UCNA_LLC_BANK       0x9
+#define MCi_STATUS_UCNA_LLC_VAL  0xBC20000080000136UL
+#define MCi_MISC_UCNA_LLC_VAL    0x86UL
+
+/* Error Types */
+#define MCE_SRAO_MEM        0x0
+#define MCE_SRAO_LLC        0x1
+#define CMCI_UCNA_LLC       0x2
+
+#define LOGFILE stdout
+
+int dump;
+struct xen_mc_msrinject msr_inj;
+
+static void Lprintf(const char *fmt, ...)
+{
+    char *buf;
+    va_list args;
+
+    va_start(args, fmt);
+    vasprintf(&buf, fmt, args);
+    fprintf(LOGFILE, "%s", buf);
+    va_end(args);
+    free(buf);
+}
+
+static void err(xc_interface *xc_handle, const char *fmt, ...)
+{
+    char *buf;
+    va_list args;
+
+    va_start(args, fmt);
+    vasprintf(&buf, fmt, args);
+    perror(buf);
+    va_end(args);
+    free(buf);
+
+    if ( xc_handle )
+        xc_interface_close(xc_handle);
+    exit(EXIT_FAILURE);
+}
+
+static void init_msr_inj(void)
+{
+    memset(&msr_inj, 0, sizeof(msr_inj));
+}
+
+static int flush_msr_inj(xc_interface *xc_handle)
+{
+    struct xen_mc mc;
+
+    mc.cmd = XEN_MC_msrinject;
+    mc.interface_version = XEN_MCA_INTERFACE_VERSION;
+    mc.u.mc_msrinject = msr_inj;
+
+    return xc_mca_op(xc_handle, &mc);
+}
+
+static int mca_cpuinfo(xc_interface *xc_handle)
+{
+    struct xen_mc mc;
+
+    mc.cmd = XEN_MC_physcpuinfo;
+    if (xc_mca_op(xc_handle, &mc))
+        return mc.u.mc_physcpuinfo.ncpus;
+    else
+        return 0;
+}
+
+static int inject_cmci(xc_interface *xc_handle, int cpu_nr)
+{
+    struct xen_mc mc;
+    int nr_cpus;
+
+    memset(&mc, 0, sizeof(struct xen_mc));
+
+    nr_cpus = mca_cpuinfo(xc_handle);
+    if (!nr_cpus)
+        err(xc_handle, "Failed to get mca_cpuinfo\n");
+
+    mc.cmd = XEN_MC_inject_v2;
+    mc.interface_version = XEN_MCA_INTERFACE_VERSION;
+
+    mc.u.mc_inject_v2.flags |= XEN_MC_INJECT_CPU_BROADCAST;
+    mc.u.mc_inject_v2.flags |= XEN_MC_INJECT_TYPE_CMCI;
+    mc.u.mc_inject_v2.cpumap.nr_cpus = nr_cpus;
+
+    return xc_mca_op(xc_handle, &mc);
+}
+
+static int inject_mce(xc_interface *xc_handle, int cpu_nr)
+{
+    struct xen_mc mc;
+
+    memset(&mc, 0, sizeof(struct xen_mc));
+
+    mc.cmd = XEN_MC_mceinject;
+    mc.interface_version = XEN_MCA_INTERFACE_VERSION;
+    mc.u.mc_mceinject.mceinj_cpunr = cpu_nr;
+
+    return xc_mca_op(xc_handle, &mc);
+}
+
+static uint64_t bank_addr(int bank, int type)
+{
+    uint64_t addr;
+
+    switch ( type )
+    {
+        case MCi_type_CTL:
+        case MCi_type_STATUS:
+        case MCi_type_ADDR:
+        case MCi_type_MISC:
+            addr = MSR_IA32_MC0_CTL + (bank * 4) + type;
+            break;
+        case MCi_type_CTL2:
+            addr = MSR_IA32_MC0_CTL2 + bank;
+            break;
+        default:
+            addr = INVALID_MSR;
+            break;
+    }
+
+    return addr;
+}
+
+static int add_msr_intpose(xc_interface *xc_handle,
+                           uint32_t cpu_nr,
+                           uint32_t flags,
+                           uint64_t msr,
+                           uint64_t val)
+{
+    uint32_t count;
+
+    if ( (msr_inj.mcinj_count &&
+         (cpu_nr != msr_inj.mcinj_cpunr || flags != msr_inj.mcinj_flags)) ||
+         msr_inj.mcinj_count == MC_MSRINJ_MAXMSRS )
+    {
+        flush_msr_inj(xc_handle);
+        init_msr_inj();
+    }
+    count= msr_inj.mcinj_count;
+
+    if ( !count )
+    {
+        msr_inj.mcinj_cpunr = cpu_nr;
+        msr_inj.mcinj_flags = flags;
+    }
+    msr_inj.mcinj_msr[count].reg = msr;
+    msr_inj.mcinj_msr[count].value = val;
+    msr_inj.mcinj_count++;
+
+    return 0;
+}
+
+static int add_msr_bank_intpose(xc_interface *xc_handle,
+                                uint32_t cpu_nr,
+                                uint32_t flags,
+                                uint32_t type,
+                                uint32_t bank,
+                                uint64_t val)
+{
+    uint64_t msr;
+
+    msr = bank_addr(bank, type);
+    if ( msr == INVALID_MSR )
+        return -1;
+    return add_msr_intpose(xc_handle, cpu_nr, flags, msr, val);
+}
+
+#define MCE_INVALID_MFN ~0UL
+#define mfn_valid(_mfn) (_mfn != MCE_INVALID_MFN)
+#define mfn_to_pfn(_mfn) (live_m2p[(_mfn)])
+static uint64_t guest_mfn(xc_interface *xc_handle,
+                               uint32_t domain,
+                               uint64_t gpfn)
+{
+    xen_pfn_t *live_m2p = NULL;
+    int ret;
+    unsigned long hvirt_start;
+    unsigned int pt_levels;
+    uint64_t * pfn_buf = NULL;
+    unsigned long max_mfn = 0; /* max mfn of the whole machine */
+    unsigned long m2p_mfn0;
+    unsigned int guest_width;
+    long max_gpfn,i;
+    uint64_t mfn = MCE_INVALID_MFN;
+
+    if ( domain > DOMID_FIRST_RESERVED )
+        return MCE_INVALID_MFN;
+
+    /* Get max gpfn */
+    max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain, 
+                               sizeof(domain)) + 1;
+    if ( max_gpfn <= 0 )
+        err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn);
+
+    Lprintf("Maxium gpfn for dom %d is 0x%lx\n", domain, max_gpfn);
+
+    /* Get max mfn */
+    if ( !get_platform_info(xc_handle, domain,
+                            &max_mfn, &hvirt_start,
+                            &pt_levels, &guest_width) )
+        err(xc_handle, "Failed to get platform information\n");
+
+    /* Get guest's pfn list */
+    pfn_buf = malloc(sizeof(uint64_t) * max_gpfn);
+    if ( !pfn_buf )
+        err(xc_handle, "Failed to alloc pfn buf\n");
+    memset(pfn_buf, 0, sizeof(uint64_t) * max_gpfn);
+
+    ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, max_gpfn);
+    if ( ret < 0 ) {
+        free(pfn_buf);
+        err(xc_handle, "Failed to get pfn list %x\n", ret);
+    }
+
+    /* Now get the m2p table */
+    live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ, &m2p_mfn0);
+    if ( !live_m2p )
+        err(xc_handle, "Failed to map live M2P table\n");
+
+    /* match the mapping */
+    for ( i = 0; i < max_gpfn; i++ )
+    {
+        uint64_t tmp;
+        tmp = pfn_buf[i];
+
+        if (mfn_valid(tmp) &&  (mfn_to_pfn(tmp) == gpfn))
+        {
+            mfn = tmp;
+            Lprintf("We get the mfn 0x%lx for this injection\n", mfn);
+            break;
+        }
+    }
+
+    munmap(live_m2p, M2P_SIZE(max_mfn));
+
+    free(pfn_buf);
+    return mfn;
+}
+
+static uint64_t mca_gpfn_to_mfn(xc_interface *xc_handle,
+                                uint32_t domain,
+                                uint64_t gfn)
+{
+    uint64_t index;
+    long max_gpfn;
+
+    /* If domain is xen, means we want pass index directly */
+    if ( domain == DOMID_XEN )
+        return gfn;
+
+    max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain, 
+                               sizeof(domain)) + 1;
+    if ( max_gpfn <= 0 )
+        err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn);
+    index = gfn % max_gpfn;
+
+    return guest_mfn(xc_handle, domain, index);
+}
+
+static int inject_mcg_status(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint64_t val)
+{
+    return add_msr_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
+                               MSR_IA32_MCG_STATUS, val);
+}
+
+static int inject_mci_status(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint64_t bank,
+                             uint64_t val)
+{
+    return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
+                                    MCi_type_STATUS, bank, val); 
+}
+
+static int inject_mci_misc(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint64_t bank,
+                             uint64_t val)
+{
+    return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
+                                    MCi_type_MISC, bank, val); 
+}
+
+static int inject_mci_addr(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint64_t bank,
+                             uint64_t val)
+{
+    return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
+                                    MCi_type_ADDR, bank, val); 
+}
+
+static int inject_llc_srao(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint32_t domain,
+                             uint64_t gaddr)
+{
+    uint64_t gpfn, mfn, haddr;
+    int ret = 0;
+
+    ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+    ret = inject_mci_status(xc_handle, cpu_nr,
+                            MCE_SRAO_LLC_BANK, MCi_STATUS_SRAO_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+    ret = inject_mci_misc(xc_handle, cpu_nr,
+                          MCE_SRAO_LLC_BANK, MCi_MISC_SRAO_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_MISC MSR\n");
+
+    gpfn = gaddr >> PAGE_SHIFT;
+    mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
+    if (!mfn_valid(mfn))
+        err(xc_handle, "The MFN is not valid\n");
+    haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
+    ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_LLC_BANK, haddr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
+
+    ret = flush_msr_inj(xc_handle);
+    if ( ret )
+        err(xc_handle, "Failed to inject MSR\n");
+    ret = inject_mce(xc_handle, cpu_nr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCE error\n");
+
+    return 0;
+}
+
+static int inject_mem_srao(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint32_t domain,
+                             uint64_t gaddr)
+{
+    uint64_t gpfn, mfn, haddr;
+    int ret = 0;
+
+    ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_MEM_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+    ret = inject_mci_status(xc_handle, cpu_nr,
+                            MCE_SRAO_MEM_BANK, MCi_STATUS_SRAO_MEM_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+    ret = inject_mci_misc(xc_handle, cpu_nr,
+                          MCE_SRAO_MEM_BANK, MCi_MISC_SRAO_MEM_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_MISC MSR\n");
+
+    gpfn = gaddr >> PAGE_SHIFT;
+    mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
+    if (!mfn_valid(mfn))
+        err(xc_handle, "The MFN is not valid\n");
+    haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
+    ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_MEM_BANK, haddr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
+
+    ret = flush_msr_inj(xc_handle);
+    if ( ret )
+        err(xc_handle, "Failed to inject MSR\n");
+    ret = inject_mce(xc_handle, cpu_nr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCE error\n");
+
+    return 0;
+}
+
+static int inject_llc_ucna(xc_interface *xc_handle,
+                             uint32_t cpu_nr,
+                             uint32_t domain,
+                             uint64_t gaddr)
+{
+    uint64_t gpfn, mfn, haddr;
+    int ret = 0;
+
+    ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_UCNA_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+    ret = inject_mci_status(xc_handle, cpu_nr,
+                            CMCI_UCNA_LLC_BANK, MCi_STATUS_UCNA_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+    ret = inject_mci_misc(xc_handle, cpu_nr,
+                          CMCI_UCNA_LLC_BANK, MCi_MISC_UCNA_LLC_VAL);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_MISC MSR\n");
+
+    gpfn = gaddr >> PAGE_SHIFT;
+    mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
+    if (!mfn_valid(mfn))
+        err(xc_handle, "The MFN is not valid\n");
+    haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
+    ret = inject_mci_addr(xc_handle, cpu_nr, CMCI_UCNA_LLC_BANK, haddr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
+
+    ret = flush_msr_inj(xc_handle);
+    if ( ret )
+        err(xc_handle, "Failed to inject MSR\n");
+    ret = inject_cmci(xc_handle, cpu_nr);
+    if ( ret )
+        err(xc_handle, "Failed to inject MCE error\n");
+
+    return 0;
+}
+
+static long xs_get_dom_mem(int domid)
+{
+    char path[128];
+    char *memstr;
+    uint64_t mem;
+    unsigned int plen;
+    struct xs_handle *xs;
+
+    xs = xs_daemon_open();
+    if (!xs)
+        return -1;
+
+    sprintf(path, "/local/domain/%d/memory/target", domid);
+    memstr = xs_read(xs, XBT_NULL, path, &plen);
+    xs_daemon_close(xs);
+
+    if (!memstr || !plen)
+        return -1;
+
+    mem = atoll(memstr)*1024;
+    free(memstr);
+
+    return mem;
+}
+
+static struct option opts[] = {
+    {"cpu", 0, 0, 'c'},
+    {"domain", 0, 0, 'd'},
+    {"dump", 0, 0, 'D'},
+    {"help", 0, 0, 'h'},
+    {"log", 0, 0, 'l'},
+    {"page", 0, 0, 'p'},
+    {"", 0, 0, '\0'}
+};
+
+static void help(void)
+{
+    printf("Usage: xen-mceinj [OPTION]...\n"
+           "\n"
+           "Mandatory arguments to long options are mandatory"
+           "for short options too.\n"
+           "  -D, --dump           dump addr info without error injection\n"
+           "  -c, --cpu=CPU_ID     target CPU\n"
+           "  -d, --domain=DomID   target domain, the default is Xen itself\n"
+           "  -h, --help           print this page\n"
+           "  -p, --phyaddr        physical address\n"
+           "  -t, --type=error     error type\n"
+           "                        0 : MCE_SRAO_MEM\n"
+           "                        1 : MCE_SRAO_LLC\n"
+           "                        2 : CMCI_UCNA_LLC\n"
+           "\n"
+           );
+}
+
+int main(int argc, char *argv[])
+{
+    int type = MCE_SRAO_MEM;
+    int c, opt_index;
+    uint32_t domid;
+    xc_interface *xc_handle;
+    int cpu_nr;
+    int64_t gaddr, gpfn, mfn, haddr, max_gpa;
+
+    /* Default Value */
+    domid = DOMID_XEN;
+    gaddr = 0x180020;
+    cpu_nr = 0;
+
+    init_msr_inj();
+    xc_handle = xc_interface_open(0, 0, 0);
+    if ( !xc_handle ) {
+        Lprintf("Failed to get xc interface\n");
+        exit(EXIT_FAILURE);
+    }
+
+    while ( 1 ) {
+        c = getopt_long(argc, argv, "c:Dd:t:hp:r", opts, &opt_index);
+        if ( c == -1 )
+            break;
+        switch ( c ) {
+        case 'D':
+            dump=1;
+            break;
+        case 'c':
+            cpu_nr = strtol(optarg, &optarg, 10);
+            if ( strlen(optarg) != 0 )
+                err(xc_handle, "Please input a digit parameter for CPU\n");
+            break;
+        case 'd':
+            domid = strtol(optarg, &optarg, 10);
+            if ( strlen(optarg) != 0 )
+                err(xc_handle, "Please input a digit parameter for domain\n");
+            break;
+        case 'p':
+            gaddr = strtol(optarg, &optarg, 0);
+            if ( strlen(optarg) != 0 )
+                err(xc_handle, "Please input correct page address\n");
+            break;
+        case 't':
+            type = strtol(optarg, NULL, 0);
+            break;
+        case 'h':
+        default:
+            help();
+            return 0;
+        }
+    }
+    
+    if ( domid != DOMID_XEN ) {
+        max_gpa = xs_get_dom_mem(domid);
+        Lprintf("get domain %d max gpa is: 0x%lx \n", domid, max_gpa);
+        if ( gaddr >= max_gpa )
+            err(xc_handle, "Fail: gaddr exceeds max_gpa 0x%lx\n", max_gpa);
+    }
+    Lprintf("get gaddr of error inject is: 0x%lx \n", gaddr);
+
+    if ( dump ) {
+        gpfn = gaddr >> PAGE_SHIFT;
+        mfn = mca_gpfn_to_mfn(xc_handle, domid, gpfn);
+        if (!mfn_valid(mfn))
+            err(xc_handle, "The MFN is not valid\n");
+        haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
+        if ( domid == DOMID_XEN )
+            Lprintf("Xen: mfn=0x%lx, haddr=0x%lx\n", mfn, haddr);
+        else 
+            Lprintf("Dom%d: gaddr=0x%lx, gpfn=0x%lx,"
+                    "mfn=0x%lx, haddr=0x%lx\n",
+                    domid, gaddr, gpfn, mfn, haddr);
+        goto out;
+    }
+
+    switch ( type )
+    {
+    case MCE_SRAO_MEM:
+        inject_mem_srao(xc_handle, cpu_nr, domid, gaddr);
+        break;
+    case MCE_SRAO_LLC:
+        inject_llc_srao(xc_handle, cpu_nr, domid, gaddr);
+        break;
+    case CMCI_UCNA_LLC:
+        inject_llc_ucna(xc_handle, cpu_nr, domid, gaddr);
+        break;
+    default:
+        err(xc_handle, "Unsupported error type\n");
+        break;
+    }
+
+out:
+    xc_interface_close(xc_handle);
+    return 0;
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.