debuggers.hg
changeset 22682:1bc031edae04
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@intel.com>
Signed-off-by: Haicheng Li<haicheng.li@intel.com>
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
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@intel.com>
Signed-off-by: Haicheng Li<haicheng.li@intel.com>
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
author | Keir Fraser <keir@xen.org> |
---|---|
date | Fri Dec 24 10:21:27 2010 +0000 (2010-12-24) |
parents | 97779ffa76f5 |
children | ca0b26180f32 |
files | tools/tests/mce-test/tools/Makefile tools/tests/mce-test/tools/README tools/tests/mce-test/tools/xen-mceinj.c |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/tests/mce-test/tools/Makefile Fri Dec 24 10:21:27 2010 +0000 1.3 @@ -0,0 +1,27 @@ 1.4 +XEN_ROOT=../../../.. 1.5 +include $(XEN_ROOT)/tools/Rules.mk 1.6 + 1.7 +CFLAGS += -Werror 1.8 + 1.9 +INCLUDES += -I $(XEN_XC) 1.10 +INCLUDES += -I $(XEN_LIBXC) 1.11 +INCLUDES += -I $(XEN_INCLUDE) 1.12 +CFLAGS += $(INCLUDES) 1.13 + 1.14 +HDRS = $(wildcard *.h) 1.15 + 1.16 +.PHONY: all 1.17 +all: xen-mceinj 1.18 + 1.19 +install: 1.20 + cp xen-mceinj /usr/sbin/ 1.21 + 1.22 +.PHONY: clean 1.23 +clean: 1.24 + $(RM) *.o xen-mceinj 1.25 + 1.26 +%.o: %.c $(HDRS) Makefile 1.27 + $(CC) -c $(CFLAGS) -o $@ $< 1.28 + 1.29 +xen-mceinj: %: %.o Makefile 1.30 + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/tests/mce-test/tools/README Fri Dec 24 10:21:27 2010 +0000 2.3 @@ -0,0 +1,24 @@ 2.4 +Xen Machine Check Exception(MCE) error inject tool 2.5 +---------------------------------------------- 2.6 + 2.7 +xen-mceinj is a software MCE injection tool, which is based on Xen 2.8 +MCE injection mechanism. It allows to inject machine check errors on the 2.9 +software level into a running Xen/dom0/VM. This is intended for 2.10 +validation of the Xen machine check handler. 2.11 + 2.12 +With the help of the Makefile, it is possible to compile a binary file 2.13 +named "xen-mceinj". 2.14 + 2.15 +Usage 2.16 +----- 2.17 +$make (make install) --Note: make sure compile xen/tools before do this step 2.18 +$./xen-mceinj [OPTION]... 2.19 + 2.20 +OPTION arguments can be: 2.21 + -D, --dump dump addr info without error injection 2.22 + -c, --cpu=CPU_ID target CPU, the default is CPU0 2.23 + -d, --domain=DomID target domain, the default is Xen itself 2.24 + -p, --page physical page address, the default is 0x180020 2.25 + -t, --type=error error type 2.26 + 2.27 +For detail help, please refer to "./xen-mceinj -h"
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/tests/mce-test/tools/xen-mceinj.c Fri Dec 24 10:21:27 2010 +0000 3.3 @@ -0,0 +1,645 @@ 3.4 +/* 3.5 + * xen-mceinj.c: utilities to inject fake MCE for x86. 3.6 + * Copyright (c) 2010, Intel Corporation. 3.7 + * 3.8 + * This program is free software; you can redistribute it and/or modify it 3.9 + * under the terms and conditions of the GNU General Public License, 3.10 + * version 2, as published by the Free Software Foundation. 3.11 + * 3.12 + * This program is distributed in the hope it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 3.15 + * more details. 3.16 + * 3.17 + * You should have received a copy of the GNU General Public License along with 3.18 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 3.19 + * Place - Suite 330, Boston, MA 02111-1307 USA. 3.20 + * 3.21 + * Authors: Yunhong Jiang <yunhong.jiang@intel.com> 3.22 + * Haicheng Li <haicheng.li@intel.com> 3.23 + * Xudong Hao <xudong.hao@intel.com> 3.24 + */ 3.25 + 3.26 + 3.27 +#define _GNU_SOURCE 3.28 +#include <stdio.h> 3.29 +#include <stdlib.h> 3.30 +#include <unistd.h> 3.31 +#include <string.h> 3.32 +#include <getopt.h> 3.33 +#include <errno.h> 3.34 +#include <signal.h> 3.35 +#include <stdarg.h> 3.36 + 3.37 +#include <xenctrl.h> 3.38 +#include <xg_private.h> 3.39 +#include <xenguest.h> 3.40 +#include <inttypes.h> 3.41 +#include <sys/time.h> 3.42 +#include <xen/arch-x86/xen-mca.h> 3.43 +#include <xg_save_restore.h> 3.44 +#include <xs.h> 3.45 + 3.46 +#define MCi_type_CTL 0x0 3.47 +#define MCi_type_STATUS 0x1 3.48 +#define MCi_type_ADDR 0x2 3.49 +#define MCi_type_MISC 0x3 3.50 +#define MCi_type_CTL2 0x4 3.51 + 3.52 +#define INVALID_MSR ~0UL 3.53 + 3.54 +/* Intel MSRs */ 3.55 +#define MSR_IA32_MCG_CAP 0x00000179 3.56 +#define MSR_IA32_MCG_STATUS 0x0000017a 3.57 +#define MSR_IA32_MCG_CTL 0x0000017b 3.58 +#define MSR_IA32_MC0_CTL 0x00000400 3.59 +#define MSR_IA32_MC0_STATUS 0x00000401 3.60 +#define MSR_IA32_MC0_ADDR 0x00000402 3.61 +#define MSR_IA32_MC0_MISC 0x00000403 3.62 +#define MSR_IA32_MC0_CTL2 0x00000280 3.63 + 3.64 +/* LLC (Last Level Cache) EWB (Explicit Write Back) SRAO MCE */ 3.65 +#define MCG_STATUS_SRAO_LLC_VAL 0x5 3.66 +#define MCE_SRAO_LLC_BANK 0x7 3.67 +#define MCi_STATUS_SRAO_LLC_VAL 0xBD2000008000017AUL 3.68 +#define MCi_MISC_SRAO_LLC_VAL 0x86UL 3.69 + 3.70 +/* Memory Patrol Scrub SRAO MCE */ 3.71 +#define MCG_STATUS_SRAO_MEM_VAL 0x5 3.72 +#define MCE_SRAO_MEM_BANK 0x8 3.73 +#define MCi_STATUS_SRAO_MEM_VAL 0xBD000000004000CFUL 3.74 +#define MCi_MISC_SRAO_MEM_VAL 0x86UL 3.75 + 3.76 +/* LLC EWB UCNA Error */ 3.77 +#define MCG_STATUS_UCNA_LLC_VAL 0x0 3.78 +#define CMCI_UCNA_LLC_BANK 0x9 3.79 +#define MCi_STATUS_UCNA_LLC_VAL 0xBC20000080000136UL 3.80 +#define MCi_MISC_UCNA_LLC_VAL 0x86UL 3.81 + 3.82 +/* Error Types */ 3.83 +#define MCE_SRAO_MEM 0x0 3.84 +#define MCE_SRAO_LLC 0x1 3.85 +#define CMCI_UCNA_LLC 0x2 3.86 + 3.87 +#define LOGFILE stdout 3.88 + 3.89 +int dump; 3.90 +struct xen_mc_msrinject msr_inj; 3.91 + 3.92 +static void Lprintf(const char *fmt, ...) 3.93 +{ 3.94 + char *buf; 3.95 + va_list args; 3.96 + 3.97 + va_start(args, fmt); 3.98 + vasprintf(&buf, fmt, args); 3.99 + fprintf(LOGFILE, "%s", buf); 3.100 + va_end(args); 3.101 + free(buf); 3.102 +} 3.103 + 3.104 +static void err(xc_interface *xc_handle, const char *fmt, ...) 3.105 +{ 3.106 + char *buf; 3.107 + va_list args; 3.108 + 3.109 + va_start(args, fmt); 3.110 + vasprintf(&buf, fmt, args); 3.111 + perror(buf); 3.112 + va_end(args); 3.113 + free(buf); 3.114 + 3.115 + if ( xc_handle ) 3.116 + xc_interface_close(xc_handle); 3.117 + exit(EXIT_FAILURE); 3.118 +} 3.119 + 3.120 +static void init_msr_inj(void) 3.121 +{ 3.122 + memset(&msr_inj, 0, sizeof(msr_inj)); 3.123 +} 3.124 + 3.125 +static int flush_msr_inj(xc_interface *xc_handle) 3.126 +{ 3.127 + struct xen_mc mc; 3.128 + 3.129 + mc.cmd = XEN_MC_msrinject; 3.130 + mc.interface_version = XEN_MCA_INTERFACE_VERSION; 3.131 + mc.u.mc_msrinject = msr_inj; 3.132 + 3.133 + return xc_mca_op(xc_handle, &mc); 3.134 +} 3.135 + 3.136 +static int mca_cpuinfo(xc_interface *xc_handle) 3.137 +{ 3.138 + struct xen_mc mc; 3.139 + 3.140 + mc.cmd = XEN_MC_physcpuinfo; 3.141 + if (xc_mca_op(xc_handle, &mc)) 3.142 + return mc.u.mc_physcpuinfo.ncpus; 3.143 + else 3.144 + return 0; 3.145 +} 3.146 + 3.147 +static int inject_cmci(xc_interface *xc_handle, int cpu_nr) 3.148 +{ 3.149 + struct xen_mc mc; 3.150 + int nr_cpus; 3.151 + 3.152 + memset(&mc, 0, sizeof(struct xen_mc)); 3.153 + 3.154 + nr_cpus = mca_cpuinfo(xc_handle); 3.155 + if (!nr_cpus) 3.156 + err(xc_handle, "Failed to get mca_cpuinfo\n"); 3.157 + 3.158 + mc.cmd = XEN_MC_inject_v2; 3.159 + mc.interface_version = XEN_MCA_INTERFACE_VERSION; 3.160 + 3.161 + mc.u.mc_inject_v2.flags |= XEN_MC_INJECT_CPU_BROADCAST; 3.162 + mc.u.mc_inject_v2.flags |= XEN_MC_INJECT_TYPE_CMCI; 3.163 + mc.u.mc_inject_v2.cpumap.nr_cpus = nr_cpus; 3.164 + 3.165 + return xc_mca_op(xc_handle, &mc); 3.166 +} 3.167 + 3.168 +static int inject_mce(xc_interface *xc_handle, int cpu_nr) 3.169 +{ 3.170 + struct xen_mc mc; 3.171 + 3.172 + memset(&mc, 0, sizeof(struct xen_mc)); 3.173 + 3.174 + mc.cmd = XEN_MC_mceinject; 3.175 + mc.interface_version = XEN_MCA_INTERFACE_VERSION; 3.176 + mc.u.mc_mceinject.mceinj_cpunr = cpu_nr; 3.177 + 3.178 + return xc_mca_op(xc_handle, &mc); 3.179 +} 3.180 + 3.181 +static uint64_t bank_addr(int bank, int type) 3.182 +{ 3.183 + uint64_t addr; 3.184 + 3.185 + switch ( type ) 3.186 + { 3.187 + case MCi_type_CTL: 3.188 + case MCi_type_STATUS: 3.189 + case MCi_type_ADDR: 3.190 + case MCi_type_MISC: 3.191 + addr = MSR_IA32_MC0_CTL + (bank * 4) + type; 3.192 + break; 3.193 + case MCi_type_CTL2: 3.194 + addr = MSR_IA32_MC0_CTL2 + bank; 3.195 + break; 3.196 + default: 3.197 + addr = INVALID_MSR; 3.198 + break; 3.199 + } 3.200 + 3.201 + return addr; 3.202 +} 3.203 + 3.204 +static int add_msr_intpose(xc_interface *xc_handle, 3.205 + uint32_t cpu_nr, 3.206 + uint32_t flags, 3.207 + uint64_t msr, 3.208 + uint64_t val) 3.209 +{ 3.210 + uint32_t count; 3.211 + 3.212 + if ( (msr_inj.mcinj_count && 3.213 + (cpu_nr != msr_inj.mcinj_cpunr || flags != msr_inj.mcinj_flags)) || 3.214 + msr_inj.mcinj_count == MC_MSRINJ_MAXMSRS ) 3.215 + { 3.216 + flush_msr_inj(xc_handle); 3.217 + init_msr_inj(); 3.218 + } 3.219 + count= msr_inj.mcinj_count; 3.220 + 3.221 + if ( !count ) 3.222 + { 3.223 + msr_inj.mcinj_cpunr = cpu_nr; 3.224 + msr_inj.mcinj_flags = flags; 3.225 + } 3.226 + msr_inj.mcinj_msr[count].reg = msr; 3.227 + msr_inj.mcinj_msr[count].value = val; 3.228 + msr_inj.mcinj_count++; 3.229 + 3.230 + return 0; 3.231 +} 3.232 + 3.233 +static int add_msr_bank_intpose(xc_interface *xc_handle, 3.234 + uint32_t cpu_nr, 3.235 + uint32_t flags, 3.236 + uint32_t type, 3.237 + uint32_t bank, 3.238 + uint64_t val) 3.239 +{ 3.240 + uint64_t msr; 3.241 + 3.242 + msr = bank_addr(bank, type); 3.243 + if ( msr == INVALID_MSR ) 3.244 + return -1; 3.245 + return add_msr_intpose(xc_handle, cpu_nr, flags, msr, val); 3.246 +} 3.247 + 3.248 +#define MCE_INVALID_MFN ~0UL 3.249 +#define mfn_valid(_mfn) (_mfn != MCE_INVALID_MFN) 3.250 +#define mfn_to_pfn(_mfn) (live_m2p[(_mfn)]) 3.251 +static uint64_t guest_mfn(xc_interface *xc_handle, 3.252 + uint32_t domain, 3.253 + uint64_t gpfn) 3.254 +{ 3.255 + xen_pfn_t *live_m2p = NULL; 3.256 + int ret; 3.257 + unsigned long hvirt_start; 3.258 + unsigned int pt_levels; 3.259 + uint64_t * pfn_buf = NULL; 3.260 + unsigned long max_mfn = 0; /* max mfn of the whole machine */ 3.261 + unsigned long m2p_mfn0; 3.262 + unsigned int guest_width; 3.263 + long max_gpfn,i; 3.264 + uint64_t mfn = MCE_INVALID_MFN; 3.265 + 3.266 + if ( domain > DOMID_FIRST_RESERVED ) 3.267 + return MCE_INVALID_MFN; 3.268 + 3.269 + /* Get max gpfn */ 3.270 + max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain, 3.271 + sizeof(domain)) + 1; 3.272 + if ( max_gpfn <= 0 ) 3.273 + err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn); 3.274 + 3.275 + Lprintf("Maxium gpfn for dom %d is 0x%lx\n", domain, max_gpfn); 3.276 + 3.277 + /* Get max mfn */ 3.278 + if ( !get_platform_info(xc_handle, domain, 3.279 + &max_mfn, &hvirt_start, 3.280 + &pt_levels, &guest_width) ) 3.281 + err(xc_handle, "Failed to get platform information\n"); 3.282 + 3.283 + /* Get guest's pfn list */ 3.284 + pfn_buf = malloc(sizeof(uint64_t) * max_gpfn); 3.285 + if ( !pfn_buf ) 3.286 + err(xc_handle, "Failed to alloc pfn buf\n"); 3.287 + memset(pfn_buf, 0, sizeof(uint64_t) * max_gpfn); 3.288 + 3.289 + ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, max_gpfn); 3.290 + if ( ret < 0 ) { 3.291 + free(pfn_buf); 3.292 + err(xc_handle, "Failed to get pfn list %x\n", ret); 3.293 + } 3.294 + 3.295 + /* Now get the m2p table */ 3.296 + live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ, &m2p_mfn0); 3.297 + if ( !live_m2p ) 3.298 + err(xc_handle, "Failed to map live M2P table\n"); 3.299 + 3.300 + /* match the mapping */ 3.301 + for ( i = 0; i < max_gpfn; i++ ) 3.302 + { 3.303 + uint64_t tmp; 3.304 + tmp = pfn_buf[i]; 3.305 + 3.306 + if (mfn_valid(tmp) && (mfn_to_pfn(tmp) == gpfn)) 3.307 + { 3.308 + mfn = tmp; 3.309 + Lprintf("We get the mfn 0x%lx for this injection\n", mfn); 3.310 + break; 3.311 + } 3.312 + } 3.313 + 3.314 + munmap(live_m2p, M2P_SIZE(max_mfn)); 3.315 + 3.316 + free(pfn_buf); 3.317 + return mfn; 3.318 +} 3.319 + 3.320 +static uint64_t mca_gpfn_to_mfn(xc_interface *xc_handle, 3.321 + uint32_t domain, 3.322 + uint64_t gfn) 3.323 +{ 3.324 + uint64_t index; 3.325 + long max_gpfn; 3.326 + 3.327 + /* If domain is xen, means we want pass index directly */ 3.328 + if ( domain == DOMID_XEN ) 3.329 + return gfn; 3.330 + 3.331 + max_gpfn = do_memory_op(xc_handle, XENMEM_maximum_gpfn, &domain, 3.332 + sizeof(domain)) + 1; 3.333 + if ( max_gpfn <= 0 ) 3.334 + err(xc_handle, "Failed to get max_gpfn 0x%lx\n", max_gpfn); 3.335 + index = gfn % max_gpfn; 3.336 + 3.337 + return guest_mfn(xc_handle, domain, index); 3.338 +} 3.339 + 3.340 +static int inject_mcg_status(xc_interface *xc_handle, 3.341 + uint32_t cpu_nr, 3.342 + uint64_t val) 3.343 +{ 3.344 + return add_msr_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE, 3.345 + MSR_IA32_MCG_STATUS, val); 3.346 +} 3.347 + 3.348 +static int inject_mci_status(xc_interface *xc_handle, 3.349 + uint32_t cpu_nr, 3.350 + uint64_t bank, 3.351 + uint64_t val) 3.352 +{ 3.353 + return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE, 3.354 + MCi_type_STATUS, bank, val); 3.355 +} 3.356 + 3.357 +static int inject_mci_misc(xc_interface *xc_handle, 3.358 + uint32_t cpu_nr, 3.359 + uint64_t bank, 3.360 + uint64_t val) 3.361 +{ 3.362 + return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE, 3.363 + MCi_type_MISC, bank, val); 3.364 +} 3.365 + 3.366 +static int inject_mci_addr(xc_interface *xc_handle, 3.367 + uint32_t cpu_nr, 3.368 + uint64_t bank, 3.369 + uint64_t val) 3.370 +{ 3.371 + return add_msr_bank_intpose(xc_handle, cpu_nr, MC_MSRINJ_F_INTERPOSE, 3.372 + MCi_type_ADDR, bank, val); 3.373 +} 3.374 + 3.375 +static int inject_llc_srao(xc_interface *xc_handle, 3.376 + uint32_t cpu_nr, 3.377 + uint32_t domain, 3.378 + uint64_t gaddr) 3.379 +{ 3.380 + uint64_t gpfn, mfn, haddr; 3.381 + int ret = 0; 3.382 + 3.383 + ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_LLC_VAL); 3.384 + if ( ret ) 3.385 + err(xc_handle, "Failed to inject MCG_STATUS MSR\n"); 3.386 + 3.387 + ret = inject_mci_status(xc_handle, cpu_nr, 3.388 + MCE_SRAO_LLC_BANK, MCi_STATUS_SRAO_LLC_VAL); 3.389 + if ( ret ) 3.390 + err(xc_handle, "Failed to inject MCi_STATUS MSR\n"); 3.391 + 3.392 + ret = inject_mci_misc(xc_handle, cpu_nr, 3.393 + MCE_SRAO_LLC_BANK, MCi_MISC_SRAO_LLC_VAL); 3.394 + if ( ret ) 3.395 + err(xc_handle, "Failed to inject MCi_MISC MSR\n"); 3.396 + 3.397 + gpfn = gaddr >> PAGE_SHIFT; 3.398 + mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn); 3.399 + if (!mfn_valid(mfn)) 3.400 + err(xc_handle, "The MFN is not valid\n"); 3.401 + haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1)); 3.402 + ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_LLC_BANK, haddr); 3.403 + if ( ret ) 3.404 + err(xc_handle, "Failed to inject MCi_ADDR MSR\n"); 3.405 + 3.406 + ret = flush_msr_inj(xc_handle); 3.407 + if ( ret ) 3.408 + err(xc_handle, "Failed to inject MSR\n"); 3.409 + ret = inject_mce(xc_handle, cpu_nr); 3.410 + if ( ret ) 3.411 + err(xc_handle, "Failed to inject MCE error\n"); 3.412 + 3.413 + return 0; 3.414 +} 3.415 + 3.416 +static int inject_mem_srao(xc_interface *xc_handle, 3.417 + uint32_t cpu_nr, 3.418 + uint32_t domain, 3.419 + uint64_t gaddr) 3.420 +{ 3.421 + uint64_t gpfn, mfn, haddr; 3.422 + int ret = 0; 3.423 + 3.424 + ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_SRAO_MEM_VAL); 3.425 + if ( ret ) 3.426 + err(xc_handle, "Failed to inject MCG_STATUS MSR\n"); 3.427 + 3.428 + ret = inject_mci_status(xc_handle, cpu_nr, 3.429 + MCE_SRAO_MEM_BANK, MCi_STATUS_SRAO_MEM_VAL); 3.430 + if ( ret ) 3.431 + err(xc_handle, "Failed to inject MCi_STATUS MSR\n"); 3.432 + 3.433 + ret = inject_mci_misc(xc_handle, cpu_nr, 3.434 + MCE_SRAO_MEM_BANK, MCi_MISC_SRAO_MEM_VAL); 3.435 + if ( ret ) 3.436 + err(xc_handle, "Failed to inject MCi_MISC MSR\n"); 3.437 + 3.438 + gpfn = gaddr >> PAGE_SHIFT; 3.439 + mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn); 3.440 + if (!mfn_valid(mfn)) 3.441 + err(xc_handle, "The MFN is not valid\n"); 3.442 + haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1)); 3.443 + ret = inject_mci_addr(xc_handle, cpu_nr, MCE_SRAO_MEM_BANK, haddr); 3.444 + if ( ret ) 3.445 + err(xc_handle, "Failed to inject MCi_ADDR MSR\n"); 3.446 + 3.447 + ret = flush_msr_inj(xc_handle); 3.448 + if ( ret ) 3.449 + err(xc_handle, "Failed to inject MSR\n"); 3.450 + ret = inject_mce(xc_handle, cpu_nr); 3.451 + if ( ret ) 3.452 + err(xc_handle, "Failed to inject MCE error\n"); 3.453 + 3.454 + return 0; 3.455 +} 3.456 + 3.457 +static int inject_llc_ucna(xc_interface *xc_handle, 3.458 + uint32_t cpu_nr, 3.459 + uint32_t domain, 3.460 + uint64_t gaddr) 3.461 +{ 3.462 + uint64_t gpfn, mfn, haddr; 3.463 + int ret = 0; 3.464 + 3.465 + ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS_UCNA_LLC_VAL); 3.466 + if ( ret ) 3.467 + err(xc_handle, "Failed to inject MCG_STATUS MSR\n"); 3.468 + 3.469 + ret = inject_mci_status(xc_handle, cpu_nr, 3.470 + CMCI_UCNA_LLC_BANK, MCi_STATUS_UCNA_LLC_VAL); 3.471 + if ( ret ) 3.472 + err(xc_handle, "Failed to inject MCi_STATUS MSR\n"); 3.473 + 3.474 + ret = inject_mci_misc(xc_handle, cpu_nr, 3.475 + CMCI_UCNA_LLC_BANK, MCi_MISC_UCNA_LLC_VAL); 3.476 + if ( ret ) 3.477 + err(xc_handle, "Failed to inject MCi_MISC MSR\n"); 3.478 + 3.479 + gpfn = gaddr >> PAGE_SHIFT; 3.480 + mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn); 3.481 + if (!mfn_valid(mfn)) 3.482 + err(xc_handle, "The MFN is not valid\n"); 3.483 + haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1)); 3.484 + ret = inject_mci_addr(xc_handle, cpu_nr, CMCI_UCNA_LLC_BANK, haddr); 3.485 + if ( ret ) 3.486 + err(xc_handle, "Failed to inject MCi_ADDR MSR\n"); 3.487 + 3.488 + ret = flush_msr_inj(xc_handle); 3.489 + if ( ret ) 3.490 + err(xc_handle, "Failed to inject MSR\n"); 3.491 + ret = inject_cmci(xc_handle, cpu_nr); 3.492 + if ( ret ) 3.493 + err(xc_handle, "Failed to inject MCE error\n"); 3.494 + 3.495 + return 0; 3.496 +} 3.497 + 3.498 +static long xs_get_dom_mem(int domid) 3.499 +{ 3.500 + char path[128]; 3.501 + char *memstr; 3.502 + uint64_t mem; 3.503 + unsigned int plen; 3.504 + struct xs_handle *xs; 3.505 + 3.506 + xs = xs_daemon_open(); 3.507 + if (!xs) 3.508 + return -1; 3.509 + 3.510 + sprintf(path, "/local/domain/%d/memory/target", domid); 3.511 + memstr = xs_read(xs, XBT_NULL, path, &plen); 3.512 + xs_daemon_close(xs); 3.513 + 3.514 + if (!memstr || !plen) 3.515 + return -1; 3.516 + 3.517 + mem = atoll(memstr)*1024; 3.518 + free(memstr); 3.519 + 3.520 + return mem; 3.521 +} 3.522 + 3.523 +static struct option opts[] = { 3.524 + {"cpu", 0, 0, 'c'}, 3.525 + {"domain", 0, 0, 'd'}, 3.526 + {"dump", 0, 0, 'D'}, 3.527 + {"help", 0, 0, 'h'}, 3.528 + {"log", 0, 0, 'l'}, 3.529 + {"page", 0, 0, 'p'}, 3.530 + {"", 0, 0, '\0'} 3.531 +}; 3.532 + 3.533 +static void help(void) 3.534 +{ 3.535 + printf("Usage: xen-mceinj [OPTION]...\n" 3.536 + "\n" 3.537 + "Mandatory arguments to long options are mandatory" 3.538 + "for short options too.\n" 3.539 + " -D, --dump dump addr info without error injection\n" 3.540 + " -c, --cpu=CPU_ID target CPU\n" 3.541 + " -d, --domain=DomID target domain, the default is Xen itself\n" 3.542 + " -h, --help print this page\n" 3.543 + " -p, --phyaddr physical address\n" 3.544 + " -t, --type=error error type\n" 3.545 + " 0 : MCE_SRAO_MEM\n" 3.546 + " 1 : MCE_SRAO_LLC\n" 3.547 + " 2 : CMCI_UCNA_LLC\n" 3.548 + "\n" 3.549 + ); 3.550 +} 3.551 + 3.552 +int main(int argc, char *argv[]) 3.553 +{ 3.554 + int type = MCE_SRAO_MEM; 3.555 + int c, opt_index; 3.556 + uint32_t domid; 3.557 + xc_interface *xc_handle; 3.558 + int cpu_nr; 3.559 + int64_t gaddr, gpfn, mfn, haddr, max_gpa; 3.560 + 3.561 + /* Default Value */ 3.562 + domid = DOMID_XEN; 3.563 + gaddr = 0x180020; 3.564 + cpu_nr = 0; 3.565 + 3.566 + init_msr_inj(); 3.567 + xc_handle = xc_interface_open(0, 0, 0); 3.568 + if ( !xc_handle ) { 3.569 + Lprintf("Failed to get xc interface\n"); 3.570 + exit(EXIT_FAILURE); 3.571 + } 3.572 + 3.573 + while ( 1 ) { 3.574 + c = getopt_long(argc, argv, "c:Dd:t:hp:r", opts, &opt_index); 3.575 + if ( c == -1 ) 3.576 + break; 3.577 + switch ( c ) { 3.578 + case 'D': 3.579 + dump=1; 3.580 + break; 3.581 + case 'c': 3.582 + cpu_nr = strtol(optarg, &optarg, 10); 3.583 + if ( strlen(optarg) != 0 ) 3.584 + err(xc_handle, "Please input a digit parameter for CPU\n"); 3.585 + break; 3.586 + case 'd': 3.587 + domid = strtol(optarg, &optarg, 10); 3.588 + if ( strlen(optarg) != 0 ) 3.589 + err(xc_handle, "Please input a digit parameter for domain\n"); 3.590 + break; 3.591 + case 'p': 3.592 + gaddr = strtol(optarg, &optarg, 0); 3.593 + if ( strlen(optarg) != 0 ) 3.594 + err(xc_handle, "Please input correct page address\n"); 3.595 + break; 3.596 + case 't': 3.597 + type = strtol(optarg, NULL, 0); 3.598 + break; 3.599 + case 'h': 3.600 + default: 3.601 + help(); 3.602 + return 0; 3.603 + } 3.604 + } 3.605 + 3.606 + if ( domid != DOMID_XEN ) { 3.607 + max_gpa = xs_get_dom_mem(domid); 3.608 + Lprintf("get domain %d max gpa is: 0x%lx \n", domid, max_gpa); 3.609 + if ( gaddr >= max_gpa ) 3.610 + err(xc_handle, "Fail: gaddr exceeds max_gpa 0x%lx\n", max_gpa); 3.611 + } 3.612 + Lprintf("get gaddr of error inject is: 0x%lx \n", gaddr); 3.613 + 3.614 + if ( dump ) { 3.615 + gpfn = gaddr >> PAGE_SHIFT; 3.616 + mfn = mca_gpfn_to_mfn(xc_handle, domid, gpfn); 3.617 + if (!mfn_valid(mfn)) 3.618 + err(xc_handle, "The MFN is not valid\n"); 3.619 + haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1)); 3.620 + if ( domid == DOMID_XEN ) 3.621 + Lprintf("Xen: mfn=0x%lx, haddr=0x%lx\n", mfn, haddr); 3.622 + else 3.623 + Lprintf("Dom%d: gaddr=0x%lx, gpfn=0x%lx," 3.624 + "mfn=0x%lx, haddr=0x%lx\n", 3.625 + domid, gaddr, gpfn, mfn, haddr); 3.626 + goto out; 3.627 + } 3.628 + 3.629 + switch ( type ) 3.630 + { 3.631 + case MCE_SRAO_MEM: 3.632 + inject_mem_srao(xc_handle, cpu_nr, domid, gaddr); 3.633 + break; 3.634 + case MCE_SRAO_LLC: 3.635 + inject_llc_srao(xc_handle, cpu_nr, domid, gaddr); 3.636 + break; 3.637 + case CMCI_UCNA_LLC: 3.638 + inject_llc_ucna(xc_handle, cpu_nr, domid, gaddr); 3.639 + break; 3.640 + default: 3.641 + err(xc_handle, "Unsupported error type\n"); 3.642 + break; 3.643 + } 3.644 + 3.645 +out: 3.646 + xc_interface_close(xc_handle); 3.647 + return 0; 3.648 +}