qemu-ppc
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]