From: "Egger, Christoph" <chegger@amazon.de>
To: xen-devel <xen-devel@lists.xen.org>
Cc: Liu Jinsong <jinsong.liu@intel.com>, Jan Beulich <JBeulich@suse.com>
Subject: [PATCH v2] tools/xen-mceinj: support AMD
Date: Thu, 30 May 2013 16:33:51 +0200 [thread overview]
Message-ID: <51A7634F.3060906@amazon.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 19254 bytes --]
a8206654c64f:patches chegger$ cat xen_mceinj.diff
commit a277555e158c87aed34196f72eba0a4cf8f0fb38
Author: Christoph Egger <chegger@amazon.de>
Date: Wed Feb 27 14:52:19 2013 +0000
xen-mceinj: Support AMD. Add -e option.
Add support for AMD.
Add -e option to raise an exception.
Signed-off-by: Christoph Egger <chegger@amazon.de>
diff --git a/tools/tests/mce-test/tools/xen-mceinj.c
b/tools/tests/mce-test/tools/xen-mceinj.c
index e3e62f7..7400a02 100644
--- a/tools/tests/mce-test/tools/xen-mceinj.c
+++ b/tools/tests/mce-test/tools/xen-mceinj.c
@@ -1,6 +1,8 @@
/*
* xen-mceinj.c: utilities to inject fake MCE for x86.
* Copyright (c) 2010, Intel Corporation.
+ * Copyright (c) 2012, AMD Cooperation Inc.
+ * Copyright (c) 2013, Amazon.com, Inc. or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -18,6 +20,7 @@
* Authors: Yunhong Jiang <yunhong.jiang@intel.com>
* Haicheng Li <haicheng.li@intel.com>
* Xudong Hao <xudong.hao@intel.com>
+ * Christoph Egger <chegger@amazon.de>
*/
@@ -44,11 +47,14 @@
#define MCi_type_STATUS 0x1
#define MCi_type_ADDR 0x2
#define MCi_type_MISC 0x3
-#define MCi_type_CTL2 0x4
+#define MC4_type_MISC1 0x4
+#define MC4_type_MISC2 0x5
+#define MC4_type_MISC3 0x6
+#define MCi_type_CTL2 0x7
#define INVALID_MSR ~0UL
-/* Intel MSRs */
+/* X86 machine check MSRs */
#define MSR_IA32_MCG_CAP 0x00000179
#define MSR_IA32_MCG_STATUS 0x0000017a
#define MSR_IA32_MCG_CTL 0x0000017b
@@ -56,35 +62,63 @@
#define MSR_IA32_MC0_STATUS 0x00000401
#define MSR_IA32_MC0_ADDR 0x00000402
#define MSR_IA32_MC0_MISC 0x00000403
+
+/* Intel MSRs */
#define MSR_IA32_MC0_CTL2 0x00000280
-/* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
+/* Intel: 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 */
+/* Intel: 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 */
+/* Intel: 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
+/* Intel: Error Types */
+#define INTEL_MCE_SRAO_MEM 0x0
+#define INTEL_MCE_SRAO_LLC 0x1
+#define INTEL_CMCI_UCNA_LLC 0x2
+
+/* AMD: Memory Error */
+#define MCG_STATUS_MEM_VAL 0x5
+#define MCE_MEM_BANK 0x4
+#define MCi_STATUS_MEM_VAL 0xb4000000001c0100UL
+//#define MCi_STATUS_MEM_VAL 0xb600000000000100UL
+#define MCi_MISC_MEM_VAL 0x0
+
+/* AMD: L3 Cache Error */
+#define MCG_STATUS_L3_VAL 0x5
+#define MCE_L3_BANK 0x4
+#define MCi_STATUS_L3_VAL 0xbc000400001c010bULL
+#define MC4_MISC0_VAL 0x0
+#define MC4_MISC1_VAL 0x0
+#define MC4_MISC2_L3_VAL 0xc008000000000003ULL
+
+/* AMD: Error Types */
+#define AMD_MCE_MEM 0x0 /* memory error */
+#define AMD_MCE_L3 0x1 /* l3 cache */
#define LOGFILE stdout
-int dump;
-struct xen_mc_msrinject msr_inj;
+static int dump;
+static int opt_exception;
+static struct xen_mc_msrinject msr_inj;
+
+#define CPU_VENDOR_UNKNOWN -1
+#define CPU_VENDOR_AMD 0
+#define CPU_VENDOR_INTEL 1
+static int cpu_vendor;
+
static void Lprintf(const char *fmt, ...)
{
@@ -145,7 +179,7 @@ static int mca_cpuinfo(xc_interface *xc_handle)
return 0;
}
-static int inject_cmci(xc_interface *xc_handle, int cpu_nr)
+static int intel_inject_cmci(xc_interface *xc_handle)
{
struct xen_mc mc;
int nr_cpus;
@@ -191,6 +225,15 @@ static uint64_t bank_addr(int bank, int type)
case MCi_type_MISC:
addr = MSR_IA32_MC0_CTL + (bank * 4) + type;
break;
+ case MC4_type_MISC1:
+ addr = 0xc0000408;
+ break;
+ case MC4_type_MISC2:
+ addr = 0xc0000409;
+ break;
+ case MC4_type_MISC3:
+ addr = 0xc000040a;
+ break;
case MCi_type_CTL2:
addr = MSR_IA32_MC0_CTL2 + bank;
break;
@@ -356,12 +399,11 @@ static int inject_mci_status(xc_interface *xc_handle,
}
static int inject_mci_misc(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint64_t bank,
- uint64_t val)
+ uint32_t cpu_nr, uint32_t misctype,
+ uint64_t bank, uint64_t val)
{
return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
- MCi_type_MISC, bank, val);
+ MCi_type_MISC + misctype, bank, val);
}
static int inject_mci_addr(xc_interface *xc_handle,
@@ -373,10 +415,8 @@ static int inject_mci_addr(xc_interface *xc_handle,
MCi_type_ADDR, bank, val);
}
-static int inject_llc_srao(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint32_t domain,
- uint64_t gaddr)
+static int intel_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;
@@ -390,7 +430,7 @@ static int inject_llc_srao(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
MCE_SRAO_LLC_BANK, MCi_MISC_SRAO_LLC_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -407,17 +447,18 @@ static int inject_llc_srao(xc_interface *xc_handle,
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");
+
+ if (opt_exception) {
+ 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)
+static int intel_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;
@@ -431,7 +472,7 @@ static int inject_mem_srao(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
MCE_SRAO_MEM_BANK, MCi_MISC_SRAO_MEM_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -448,17 +489,18 @@ static int inject_mem_srao(xc_interface *xc_handle,
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");
+
+ if (opt_exception) {
+ 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)
+static int intel_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;
@@ -472,7 +514,7 @@ static int inject_llc_ucna(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
CMCI_UCNA_LLC_BANK, MCi_MISC_UCNA_LLC_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -489,13 +531,108 @@ static int inject_llc_ucna(xc_interface *xc_handle,
ret = flush_msr_inj(xc_handle);
if ( ret )
err(xc_handle, "Failed to inject MSR\n");
- ret = inject_cmci(xc_handle, cpu_nr);
+ ret = intel_inject_cmci(xc_handle);
if ( ret )
err(xc_handle, "Failed to inject MCE error\n");
return 0;
}
+static int amd_inject_mem(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_MEM_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+ ret = inject_mci_status(xc_handle, cpu_nr,
+ MCE_MEM_BANK, MCi_STATUS_MEM_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
+ MCE_MEM_BANK, MCi_MISC_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_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");
+
+ if (opt_exception) {
+ ret = inject_mce(xc_handle, cpu_nr);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCE error\n");
+ }
+
+ return 0;
+}
+
+static int amd_inject_l3(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_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+ ret = inject_mci_status(xc_handle, cpu_nr,
+ MCE_L3_BANK, MCi_STATUS_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
+ MCE_L3_BANK, MC4_MISC0_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC0 MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 1,
+ MCE_L3_BANK, MC4_MISC1_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC1 MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 2,
+ MCE_L3_BANK, MC4_MISC2_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC2 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_L3_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");
+
+ if (opt_exception) {
+ ret = inject_mce(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];
@@ -508,7 +645,7 @@ static long xs_get_dom_mem(int domid)
if (!xs)
return -1;
- sprintf(path, "/local/domain/%d/memory/target", domid);
+ snprintf(path, sizeof(path), "/local/domain/%d/memory/target", domid);
memstr = xs_read(xs, XBT_NULL, path, &plen);
xs_daemon_close(xs);
@@ -540,30 +677,109 @@ static void help(void)
" -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"
+ " -e raise MCE exception\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"
);
+
+ if (cpu_vendor == CPU_VENDOR_INTEL) {
+ printf(
+ " -t, --type=error error type\n"
+ " 0x0 : SRAO MEM\n"
+ " 0x1 : SRAO LLC\n"
+ " 0x2 : CMCI UCNA LLC\n");
+ }
+ if (cpu_vendor == CPU_VENDOR_AMD) {
+ printf(
+ " -t, --type=error error type\n"
+ " 0x0: DRAM error\n"
+ " 0x1: L3 cache error\n");
+ }
+ printf("\n");
+}
+
+static void cpuid(const unsigned int *input, unsigned int regs[4])
+{
+ unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 :
input[1];
+#ifdef __i386__
+ /* Use the stack to avoid reg constraint failures with some gcc
flags */
+ asm (
+ "push %%ebx; push %%edx\n\t"
+ "cpuid\n\t"
+ "mov %%ebx,4(%4)\n\t"
+ "mov %%edx,12(%4)\n\t"
+ "pop %%edx; pop %%ebx\n\t"
+ : "=a" (regs[0]), "=c" (regs[2])
+ : "0" (input[0]), "1" (count), "S" (regs)
+ : "memory" );
+#else
+ asm (
+ "cpuid"
+ : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+ : "0" (input[0]), "2" (count) );
+#endif
+}
+
+/* Get the manufacturer brand name of the host processor. */
+static void cpuid_brand_get(char *str, size_t len)
+{
+ unsigned int input[2] = { 0, 0 };
+ union {
+ unsigned int regs[4];
+ struct {
+ char eax[4];
+ char ebx[4];
+ char ecx[4];
+ char edx[4];
+ } str_regs;
+ } cpu_branding;
+
+ cpuid(input, cpu_branding.regs);
+
+ snprintf(str, len, "%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpu_branding.str_regs.ebx[0], cpu_branding.str_regs.ebx[1],
+ cpu_branding.str_regs.ebx[2], cpu_branding.str_regs.ebx[3],
+ cpu_branding.str_regs.edx[0], cpu_branding.str_regs.edx[1],
+ cpu_branding.str_regs.edx[2], cpu_branding.str_regs.edx[3],
+ cpu_branding.str_regs.ecx[0], cpu_branding.str_regs.ecx[1],
+ cpu_branding.str_regs.ecx[2], cpu_branding.str_regs.ecx[3]);
}
int main(int argc, char *argv[])
{
- int type = MCE_SRAO_MEM;
+ int type;
int c, opt_index;
uint32_t domid;
xc_interface *xc_handle;
- int cpu_nr;
- int64_t gaddr, gpfn, mfn, haddr, max_gpa;
+ unsigned int cpu_nr;
+ uint64_t gaddr, gpfn, mfn, haddr, max_gpa;
+ char cpu_brand[13];
/* Default Value */
domid = DOMID_XEN;
gaddr = 0x180020;
cpu_nr = 0;
+ cpu_vendor = CPU_VENDOR_UNKNOWN;
+ cpuid_brand_get(cpu_brand, sizeof(cpu_brand));
+ if (strstr(cpu_brand, "AMD"))
+ cpu_vendor = CPU_VENDOR_AMD;
+ if (strstr(cpu_brand, "Intel"))
+ cpu_vendor = CPU_VENDOR_INTEL;
+
+ switch (cpu_vendor) {
+ case CPU_VENDOR_AMD:
+ type = AMD_MCE_MEM;
+ break;
+ case CPU_VENDOR_INTEL:
+ type = INTEL_MCE_SRAO_MEM;
+ break;
+ case CPU_VENDOR_UNKNOWN:
+ default:
+ Lprintf("Unknown cpu vendor on this machine\n");
+ exit(EXIT_FAILURE);
+ }
+
init_msr_inj();
xc_handle = xc_interface_open(0, 0, 0);
if ( !xc_handle ) {
@@ -571,8 +787,8 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- while ( 1 ) {
- c = getopt_long(argc, argv, "c:Dd:t:hp:r", opts, &opt_index);
+ for (;;) {
+ c = getopt_long(argc, argv, "c:Dd:t:hp:r:e", opts, &opt_index);
if ( c == -1 )
break;
switch ( c ) {
@@ -580,23 +796,26 @@ int main(int argc, char *argv[])
dump=1;
break;
case 'c':
- cpu_nr = strtol(optarg, &optarg, 10);
+ cpu_nr = strtoul(optarg, &optarg, 0);
if ( strlen(optarg) != 0 )
err(xc_handle, "Please input a digit parameter for CPU\n");
break;
case 'd':
- domid = strtol(optarg, &optarg, 10);
+ domid = strtoul(optarg, &optarg, 0);
if ( strlen(optarg) != 0 )
err(xc_handle, "Please input a digit parameter for
domain\n");
break;
case 'p':
- gaddr = strtol(optarg, &optarg, 0);
+ gaddr = strtoul(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 'e':
+ opt_exception = 1;
+ break;
case 'h':
default:
help();
@@ -627,19 +846,36 @@ int main(int argc, char *argv[])
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);
+ switch ( cpu_vendor ) {
+ case CPU_VENDOR_INTEL:
+ switch ( type ) {
+ case INTEL_MCE_SRAO_MEM:
+ intel_inject_mem_srao(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case INTEL_MCE_SRAO_LLC:
+ intel_inject_llc_srao(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case INTEL_CMCI_UCNA_LLC:
+ intel_inject_llc_ucna(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ default:
+ err(xc_handle, "Unsupported error type\n");
+ break;
+ }
break;
- default:
- err(xc_handle, "Unsupported error type\n");
+
+ case CPU_VENDOR_AMD:
+ switch ( type ) {
+ case AMD_MCE_MEM:
+ amd_inject_mem(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case AMD_MCE_L3:
+ amd_inject_l3(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ default:
+ err(xc_handle, "Unsupported error type\n");
+ break;
+ }
break;
}
[-- Attachment #2: xen_mceinj.diff --]
[-- Type: text/plain, Size: 19247 bytes --]
commit a277555e158c87aed34196f72eba0a4cf8f0fb38
Author: Christoph Egger <chegger@amazon.de>
Date: Wed Feb 27 14:52:19 2013 +0000
xen-mceinj: Support AMD. Add -e option.
Add support for AMD.
Add -e option to raise an exception.
Signed-off-by: Christoph Egger <chegger@amazon.de>
diff --git a/tools/tests/mce-test/tools/xen-mceinj.c b/tools/tests/mce-test/tools/xen-mceinj.c
index e3e62f7..7400a02 100644
--- a/tools/tests/mce-test/tools/xen-mceinj.c
+++ b/tools/tests/mce-test/tools/xen-mceinj.c
@@ -1,6 +1,8 @@
/*
* xen-mceinj.c: utilities to inject fake MCE for x86.
* Copyright (c) 2010, Intel Corporation.
+ * Copyright (c) 2012, AMD Cooperation Inc.
+ * Copyright (c) 2013, Amazon.com, Inc. or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -18,6 +20,7 @@
* Authors: Yunhong Jiang <yunhong.jiang@intel.com>
* Haicheng Li <haicheng.li@intel.com>
* Xudong Hao <xudong.hao@intel.com>
+ * Christoph Egger <chegger@amazon.de>
*/
@@ -44,11 +47,14 @@
#define MCi_type_STATUS 0x1
#define MCi_type_ADDR 0x2
#define MCi_type_MISC 0x3
-#define MCi_type_CTL2 0x4
+#define MC4_type_MISC1 0x4
+#define MC4_type_MISC2 0x5
+#define MC4_type_MISC3 0x6
+#define MCi_type_CTL2 0x7
#define INVALID_MSR ~0UL
-/* Intel MSRs */
+/* X86 machine check MSRs */
#define MSR_IA32_MCG_CAP 0x00000179
#define MSR_IA32_MCG_STATUS 0x0000017a
#define MSR_IA32_MCG_CTL 0x0000017b
@@ -56,35 +62,63 @@
#define MSR_IA32_MC0_STATUS 0x00000401
#define MSR_IA32_MC0_ADDR 0x00000402
#define MSR_IA32_MC0_MISC 0x00000403
+
+/* Intel MSRs */
#define MSR_IA32_MC0_CTL2 0x00000280
-/* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */
+/* Intel: 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 */
+/* Intel: 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 */
+/* Intel: 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
+/* Intel: Error Types */
+#define INTEL_MCE_SRAO_MEM 0x0
+#define INTEL_MCE_SRAO_LLC 0x1
+#define INTEL_CMCI_UCNA_LLC 0x2
+
+/* AMD: Memory Error */
+#define MCG_STATUS_MEM_VAL 0x5
+#define MCE_MEM_BANK 0x4
+#define MCi_STATUS_MEM_VAL 0xb4000000001c0100UL
+//#define MCi_STATUS_MEM_VAL 0xb600000000000100UL
+#define MCi_MISC_MEM_VAL 0x0
+
+/* AMD: L3 Cache Error */
+#define MCG_STATUS_L3_VAL 0x5
+#define MCE_L3_BANK 0x4
+#define MCi_STATUS_L3_VAL 0xbc000400001c010bULL
+#define MC4_MISC0_VAL 0x0
+#define MC4_MISC1_VAL 0x0
+#define MC4_MISC2_L3_VAL 0xc008000000000003ULL
+
+/* AMD: Error Types */
+#define AMD_MCE_MEM 0x0 /* memory error */
+#define AMD_MCE_L3 0x1 /* l3 cache */
#define LOGFILE stdout
-int dump;
-struct xen_mc_msrinject msr_inj;
+static int dump;
+static int opt_exception;
+static struct xen_mc_msrinject msr_inj;
+
+#define CPU_VENDOR_UNKNOWN -1
+#define CPU_VENDOR_AMD 0
+#define CPU_VENDOR_INTEL 1
+static int cpu_vendor;
+
static void Lprintf(const char *fmt, ...)
{
@@ -145,7 +179,7 @@ static int mca_cpuinfo(xc_interface *xc_handle)
return 0;
}
-static int inject_cmci(xc_interface *xc_handle, int cpu_nr)
+static int intel_inject_cmci(xc_interface *xc_handle)
{
struct xen_mc mc;
int nr_cpus;
@@ -191,6 +225,15 @@ static uint64_t bank_addr(int bank, int type)
case MCi_type_MISC:
addr = MSR_IA32_MC0_CTL + (bank * 4) + type;
break;
+ case MC4_type_MISC1:
+ addr = 0xc0000408;
+ break;
+ case MC4_type_MISC2:
+ addr = 0xc0000409;
+ break;
+ case MC4_type_MISC3:
+ addr = 0xc000040a;
+ break;
case MCi_type_CTL2:
addr = MSR_IA32_MC0_CTL2 + bank;
break;
@@ -356,12 +399,11 @@ static int inject_mci_status(xc_interface *xc_handle,
}
static int inject_mci_misc(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint64_t bank,
- uint64_t val)
+ uint32_t cpu_nr, uint32_t misctype,
+ uint64_t bank, uint64_t val)
{
return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE,
- MCi_type_MISC, bank, val);
+ MCi_type_MISC + misctype, bank, val);
}
static int inject_mci_addr(xc_interface *xc_handle,
@@ -373,10 +415,8 @@ static int inject_mci_addr(xc_interface *xc_handle,
MCi_type_ADDR, bank, val);
}
-static int inject_llc_srao(xc_interface *xc_handle,
- uint32_t cpu_nr,
- uint32_t domain,
- uint64_t gaddr)
+static int intel_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;
@@ -390,7 +430,7 @@ static int inject_llc_srao(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
MCE_SRAO_LLC_BANK, MCi_MISC_SRAO_LLC_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -407,17 +447,18 @@ static int inject_llc_srao(xc_interface *xc_handle,
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");
+
+ if (opt_exception) {
+ 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)
+static int intel_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;
@@ -431,7 +472,7 @@ static int inject_mem_srao(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
MCE_SRAO_MEM_BANK, MCi_MISC_SRAO_MEM_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -448,17 +489,18 @@ static int inject_mem_srao(xc_interface *xc_handle,
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");
+
+ if (opt_exception) {
+ 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)
+static int intel_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;
@@ -472,7 +514,7 @@ static int inject_llc_ucna(xc_interface *xc_handle,
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
- ret = inject_mci_misc(xc_handle, cpu_nr,
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
CMCI_UCNA_LLC_BANK, MCi_MISC_UCNA_LLC_VAL);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
@@ -489,13 +531,108 @@ static int inject_llc_ucna(xc_interface *xc_handle,
ret = flush_msr_inj(xc_handle);
if ( ret )
err(xc_handle, "Failed to inject MSR\n");
- ret = inject_cmci(xc_handle, cpu_nr);
+ ret = intel_inject_cmci(xc_handle);
if ( ret )
err(xc_handle, "Failed to inject MCE error\n");
return 0;
}
+static int amd_inject_mem(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_MEM_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+ ret = inject_mci_status(xc_handle, cpu_nr,
+ MCE_MEM_BANK, MCi_STATUS_MEM_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
+ MCE_MEM_BANK, MCi_MISC_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_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");
+
+ if (opt_exception) {
+ ret = inject_mce(xc_handle, cpu_nr);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCE error\n");
+ }
+
+ return 0;
+}
+
+static int amd_inject_l3(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_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
+
+ ret = inject_mci_status(xc_handle, cpu_nr,
+ MCE_L3_BANK, MCi_STATUS_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 0,
+ MCE_L3_BANK, MC4_MISC0_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC0 MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 1,
+ MCE_L3_BANK, MC4_MISC1_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC1 MSR\n");
+
+ ret = inject_mci_misc(xc_handle, cpu_nr, 2,
+ MCE_L3_BANK, MC4_MISC2_L3_VAL);
+ if ( ret )
+ err(xc_handle, "Failed to inject MC4_MISC2 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_L3_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");
+
+ if (opt_exception) {
+ ret = inject_mce(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];
@@ -508,7 +645,7 @@ static long xs_get_dom_mem(int domid)
if (!xs)
return -1;
- sprintf(path, "/local/domain/%d/memory/target", domid);
+ snprintf(path, sizeof(path), "/local/domain/%d/memory/target", domid);
memstr = xs_read(xs, XBT_NULL, path, &plen);
xs_daemon_close(xs);
@@ -540,30 +677,109 @@ static void help(void)
" -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"
+ " -e raise MCE exception\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"
);
+
+ if (cpu_vendor == CPU_VENDOR_INTEL) {
+ printf(
+ " -t, --type=error error type\n"
+ " 0x0 : SRAO MEM\n"
+ " 0x1 : SRAO LLC\n"
+ " 0x2 : CMCI UCNA LLC\n");
+ }
+ if (cpu_vendor == CPU_VENDOR_AMD) {
+ printf(
+ " -t, --type=error error type\n"
+ " 0x0: DRAM error\n"
+ " 0x1: L3 cache error\n");
+ }
+ printf("\n");
+}
+
+static void cpuid(const unsigned int *input, unsigned int regs[4])
+{
+ unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
+#ifdef __i386__
+ /* Use the stack to avoid reg constraint failures with some gcc flags */
+ asm (
+ "push %%ebx; push %%edx\n\t"
+ "cpuid\n\t"
+ "mov %%ebx,4(%4)\n\t"
+ "mov %%edx,12(%4)\n\t"
+ "pop %%edx; pop %%ebx\n\t"
+ : "=a" (regs[0]), "=c" (regs[2])
+ : "0" (input[0]), "1" (count), "S" (regs)
+ : "memory" );
+#else
+ asm (
+ "cpuid"
+ : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+ : "0" (input[0]), "2" (count) );
+#endif
+}
+
+/* Get the manufacturer brand name of the host processor. */
+static void cpuid_brand_get(char *str, size_t len)
+{
+ unsigned int input[2] = { 0, 0 };
+ union {
+ unsigned int regs[4];
+ struct {
+ char eax[4];
+ char ebx[4];
+ char ecx[4];
+ char edx[4];
+ } str_regs;
+ } cpu_branding;
+
+ cpuid(input, cpu_branding.regs);
+
+ snprintf(str, len, "%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpu_branding.str_regs.ebx[0], cpu_branding.str_regs.ebx[1],
+ cpu_branding.str_regs.ebx[2], cpu_branding.str_regs.ebx[3],
+ cpu_branding.str_regs.edx[0], cpu_branding.str_regs.edx[1],
+ cpu_branding.str_regs.edx[2], cpu_branding.str_regs.edx[3],
+ cpu_branding.str_regs.ecx[0], cpu_branding.str_regs.ecx[1],
+ cpu_branding.str_regs.ecx[2], cpu_branding.str_regs.ecx[3]);
}
int main(int argc, char *argv[])
{
- int type = MCE_SRAO_MEM;
+ int type;
int c, opt_index;
uint32_t domid;
xc_interface *xc_handle;
- int cpu_nr;
- int64_t gaddr, gpfn, mfn, haddr, max_gpa;
+ unsigned int cpu_nr;
+ uint64_t gaddr, gpfn, mfn, haddr, max_gpa;
+ char cpu_brand[13];
/* Default Value */
domid = DOMID_XEN;
gaddr = 0x180020;
cpu_nr = 0;
+ cpu_vendor = CPU_VENDOR_UNKNOWN;
+ cpuid_brand_get(cpu_brand, sizeof(cpu_brand));
+ if (strstr(cpu_brand, "AMD"))
+ cpu_vendor = CPU_VENDOR_AMD;
+ if (strstr(cpu_brand, "Intel"))
+ cpu_vendor = CPU_VENDOR_INTEL;
+
+ switch (cpu_vendor) {
+ case CPU_VENDOR_AMD:
+ type = AMD_MCE_MEM;
+ break;
+ case CPU_VENDOR_INTEL:
+ type = INTEL_MCE_SRAO_MEM;
+ break;
+ case CPU_VENDOR_UNKNOWN:
+ default:
+ Lprintf("Unknown cpu vendor on this machine\n");
+ exit(EXIT_FAILURE);
+ }
+
init_msr_inj();
xc_handle = xc_interface_open(0, 0, 0);
if ( !xc_handle ) {
@@ -571,8 +787,8 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- while ( 1 ) {
- c = getopt_long(argc, argv, "c:Dd:t:hp:r", opts, &opt_index);
+ for (;;) {
+ c = getopt_long(argc, argv, "c:Dd:t:hp:r:e", opts, &opt_index);
if ( c == -1 )
break;
switch ( c ) {
@@ -580,23 +796,26 @@ int main(int argc, char *argv[])
dump=1;
break;
case 'c':
- cpu_nr = strtol(optarg, &optarg, 10);
+ cpu_nr = strtoul(optarg, &optarg, 0);
if ( strlen(optarg) != 0 )
err(xc_handle, "Please input a digit parameter for CPU\n");
break;
case 'd':
- domid = strtol(optarg, &optarg, 10);
+ domid = strtoul(optarg, &optarg, 0);
if ( strlen(optarg) != 0 )
err(xc_handle, "Please input a digit parameter for domain\n");
break;
case 'p':
- gaddr = strtol(optarg, &optarg, 0);
+ gaddr = strtoul(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 'e':
+ opt_exception = 1;
+ break;
case 'h':
default:
help();
@@ -627,19 +846,36 @@ int main(int argc, char *argv[])
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);
+ switch ( cpu_vendor ) {
+ case CPU_VENDOR_INTEL:
+ switch ( type ) {
+ case INTEL_MCE_SRAO_MEM:
+ intel_inject_mem_srao(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case INTEL_MCE_SRAO_LLC:
+ intel_inject_llc_srao(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case INTEL_CMCI_UCNA_LLC:
+ intel_inject_llc_ucna(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ default:
+ err(xc_handle, "Unsupported error type\n");
+ break;
+ }
break;
- default:
- err(xc_handle, "Unsupported error type\n");
+
+ case CPU_VENDOR_AMD:
+ switch ( type ) {
+ case AMD_MCE_MEM:
+ amd_inject_mem(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ case AMD_MCE_L3:
+ amd_inject_l3(xc_handle, cpu_nr, domid, gaddr);
+ break;
+ default:
+ err(xc_handle, "Unsupported error type\n");
+ break;
+ }
break;
}
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next reply other threads:[~2013-05-30 14:33 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-30 14:33 Egger, Christoph [this message]
2013-05-31 8:30 ` [PATCH v2] tools/xen-mceinj: support AMD Jan Beulich
2013-05-31 8:54 ` Ian Campbell
2013-05-31 11:36 ` Liu, Jinsong
2013-05-31 11:31 ` Liu, Jinsong
2013-05-31 11:51 ` Jan Beulich
2013-05-31 14:16 ` Liu, Jinsong
2013-05-31 14:13 ` Christoph Egger
2013-05-31 14:28 ` Jan Beulich
2013-05-31 14:35 ` Liu, Jinsong
2013-05-31 14:51 ` Egger, Christoph
2013-05-31 16:07 ` Liu, Jinsong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51A7634F.3060906@amazon.de \
--to=chegger@amazon.de \
--cc=JBeulich@suse.com \
--cc=jinsong.liu@intel.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).