[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 6/6] sPAPR: Support error injection
From: |
Gavin Shan |
Subject: |
[Qemu-ppc] [PATCH 6/6] sPAPR: Support error injection |
Date: |
Wed, 14 May 2014 14:27:29 +1000 |
There're 3 RTAS calls related to error injection: "ibm,open-errinjct",
"ibm,close-errinjct", "ibm,errinjct". The first two are used to
manage error injection tokens and we just emulate them in QEMU. Each
VM is allowed to have one opened token at once to avoid conflicts on
hardware level.
For "ibm,errinjct", we support PCI error injection for now. The
request is routed to host via dedicated syscall.
Signed-off-by: Gavin Shan <address@hidden>
---
hw/ppc/spapr_pci.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/ppc/spapr_rtas.c | 37 +++++++++++++++-
include/hw/ppc/spapr.h | 11 +++++
3 files changed, 161 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 0a3a7cc..5339eaf 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -609,6 +609,113 @@ static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu,
rtas_st(rets, 0, 0);
}
+static void rtas_ibm_open_errinjct(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args, uint32_t nret,
+ target_ulong rets)
+{
+ if ((nargs != 0) || (nret != 2)) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ if (spapr->errinjct_token_opened) {
+ rtas_st(rets, 0, -4);
+ return;
+ }
+
+ /* For simplity, we just use fixed token */
+ spapr->errinjct_token_opened = 1;
+ rtas_st(rets, 0, 0x12345678);
+ rtas_st(rets, 1, 0);
+}
+
+static void rtas_ibm_errinjct(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args, uint32_t nret,
+ target_ulong rets)
+{
+ uint32_t open_token, buf[8], *p;
+ int32_t ej_type, num_ops, i;
+ target_ulong buf_addr;
+ struct rtas_args rargs;
+
+ if ((nargs != 3) || (nret != 1)) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ ej_type = rtas_ld(args, 0);
+ open_token = rtas_ld(args, 1);
+ buf_addr = rtas_ld(args, 2);
+
+ /* Buffer address should be 1KB aligned */
+ if (!spapr->errinjct_token_opened ||
+ open_token != 0x12345678 ||
+ ej_type >= 15 ||
+ buf_addr & 0x3fful) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ /* We only support PCI error injection */
+ if (ej_type == 6) {
+ num_ops = 6;
+ } else if (ej_type == 7) {
+ num_ops = 8;
+ } else {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ p = buf;
+ for (i = 0; i < num_ops; i++) {
+ *p++ = rtas_ld(buf_addr, i);
+ }
+
+ rargs.nargs = 5;
+ rargs.nret = 1;
+ rargs.token = 0x1;
+ rargs.args[0] = 0x1;
+ rargs.args[1] = ej_type;
+ rargs.args[2] = 0x12345678;
+ rargs.args[3] = (uint32_t)(((uint64_t)buf) >> 32);
+ rargs.args[4] = (uint32_t)((uint64_t)buf);
+
+ if (syscall(255, &rargs)) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ rtas_st(rets, 0, 0);
+}
+
+static void rtas_ibm_close_errinjct(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args, uint32_t nret,
+ target_ulong rets)
+{
+ uint32_t open_token;
+
+ if ((nargs != 1) || (nret != 1)) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ open_token = rtas_ld(args, 0);
+ if (!spapr->errinjct_token_opened ||
+ open_token != 0x12345678) {
+ rtas_st(rets, 0, -4);
+ return;
+ }
+
+ spapr->errinjct_token_opened = 0;
+ rtas_st(rets, 0, 0);
+}
+
static int pci_spapr_swizzle(int slot, int pin)
{
return (slot + pin) % PCI_NUM_PINS;
@@ -1142,6 +1249,13 @@ void spapr_pci_rtas_init(void)
rtas_ibm_configure_pe);
spapr_rtas_register("ibm,slot-error-detail",
rtas_ibm_slot_error_detail);
+
+ spapr_rtas_register("ibm,open-errinjct",
+ rtas_ibm_open_errinjct);
+ spapr_rtas_register("ibm,errinjct",
+ rtas_ibm_errinjct);
+ spapr_rtas_register("ibm,close-errinjct",
+ rtas_ibm_close_errinjct);
}
static void spapr_pci_register_types(void)
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index ea4a2b2..836695b 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -324,8 +324,26 @@ int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
hwaddr rtas_size)
{
+ const char *tokens[] = {
+ "fatal",
+ "recovered-random-event",
+ "recovered-special-event",
+ "corrupted-page",
+ "corrupted-slb",
+ "translator-failure",
+ "ioa-bus-error",
+ "ioa-bus-error-64",
+ "platform-specific",
+ "corrupted-dcache-start",
+ "corrupted-dcache-end",
+ "corrupted-icache-start",
+ "corrupted-icache-end",
+ "corrupted-tlb-start",
+ "corrupted-tlb-end"
+ };
+ char errinjct_tokens[1024];
+ int i, fdt_offset, offset;
int ret;
- int i;
ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
if (ret < 0) {
@@ -374,6 +392,23 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr
rtas_addr,
}
}
+
+ /* ibm,errinjct-tokens */
+ offset = 0;
+ for (i = 0; i < ARRAY_SIZE(tokens); i++) {
+ offset += sprintf(errinjct_tokens + offset, "%s", tokens[i]);
+ errinjct_tokens[offset++] = '\0';
+ *(int *)(&errinjct_tokens[offset]) = i+1;
+ offset += sizeof(int);
+ }
+
+ fdt_offset = fdt_path_offset(fdt, "/rtas");
+ ret = fdt_setprop(fdt, fdt_offset, "ibm,errinjct-tokens",
+ errinjct_tokens, offset);
+ if (ret) {
+ fprintf(stderr, "Couldn't finalize ibm,errinjct-tokens property\n");
+ }
+
return 0;
}
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index f1d307f..0285dd9 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -8,6 +8,14 @@ struct VIOsPAPRBus;
struct sPAPRPHBState;
struct sPAPRNVRAM;
+struct rtas_args {
+ uint32_t token;
+ uint32_t nargs;
+ uint32_t nret;
+ uint32_t args[16];
+ uint32_t *rets;
+};
+
#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
typedef struct sPAPREnvironment {
@@ -43,6 +51,9 @@ typedef struct sPAPREnvironment {
int htab_save_index;
bool htab_first_pass;
int htab_fd;
+
+ /* Error injection token */
+ int errinjct_token_opened;
} sPAPREnvironment;
#define H_SUCCESS 0
--
1.8.3.2
- [Qemu-ppc] [PATCH RFC v3 0/6] EEH Support for VFIO PCI Device, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 3/6] VFIO: EEH address mapping, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 6/6] sPAPR: Support error injection,
Gavin Shan <=
- [Qemu-ppc] [PATCH 1/6] headers: Sync with Linux header, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 2/6] PCI: Add sysdata to PCI bus, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 4/6] VFIO: Introduce EEH handler, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 5/6] sPAPR: Support EEH RTAS services, Gavin Shan, 2014/05/14