[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH v8 7/7] sPAPR: Support RTAS call ibm,errinjct
From: |
Gavin Shan |
Subject: |
[Qemu-ppc] [PATCH v8 7/7] sPAPR: Support RTAS call ibm,errinjct |
Date: |
Mon, 14 Sep 2015 11:36:15 +1000 |
The patch supports RTAS call "ibm,errinjct" to allow injecting
EEH errors to VFIO PCI devices. The implementation is similiar
to EEH support for VFIO PCI devices: The RTAS request is captured
by QEMU and routed to spapr_phb_vfio_eeh_inject_error() where the
request is translated to VFIO container IOCTL command to be handled
by the host.
Signed-off-by: Gavin Shan <address@hidden>
Reviewed-by: David Gibson <address@hidden>
---
hw/ppc/spapr_pci.c | 30 ++++++++++++++++++
hw/ppc/spapr_pci_vfio.c | 32 +++++++++++++++++++
hw/ppc/spapr_rtas.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci-host/spapr.h | 3 ++
include/hw/ppc/spapr.h | 9 +++++-
5 files changed, 150 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 1b7559d..93d6d1b 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -646,6 +646,36 @@ param_error_exit:
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
}
+int spapr_rtas_errinjct_ioa(sPAPRMachineState *spapr,
+ target_ulong param_buf,
+ bool is_64bits)
+{
+ sPAPRPHBState *sphb;
+ uint64_t buid, addr, mask;
+ uint32_t func;
+
+ if (is_64bits) {
+ addr = rtas_ldq(param_buf, 0);
+ mask = rtas_ldq(param_buf, 2);
+ buid = rtas_ldq(param_buf, 5);
+ func = rtas_ld(param_buf, 7);
+ } else {
+ addr = rtas_ld(param_buf, 0);
+ mask = rtas_ld(param_buf, 1);
+ buid = rtas_ldq(param_buf, 3);
+ func = rtas_ld(param_buf, 5);
+ }
+
+ /* Find PHB */
+ sphb = spapr_pci_find_phb(spapr, buid);
+ if (!sphb || sphb->vfio_num == 0) {
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ /* Handle the request */
+ return spapr_phb_vfio_eeh_inject_error(sphb, func, addr, mask, is_64bits);
+}
+
static int pci_spapr_swizzle(int slot, int pin)
{
return (slot + pin) % PCI_NUM_PINS;
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 48137d5..8949398 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -17,6 +17,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "asm-powerpc/eeh.h"
+
#include "hw/ppc/spapr.h"
#include "hw/pci-host/spapr.h"
#include "hw/pci/msix.h"
@@ -189,6 +191,36 @@ int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
return RTAS_OUT_SUCCESS;
}
+int spapr_phb_vfio_eeh_inject_error(sPAPRPHBState *sphb,
+ uint32_t func, uint64_t addr,
+ uint64_t mask, bool is_64bits)
+{
+ struct vfio_eeh_pe_op op = {
+ .op = VFIO_EEH_PE_INJECT_ERR,
+ .argsz = sizeof(op)
+ };
+ int ret = RTAS_OUT_SUCCESS;
+
+ op.err.type = is_64bits ? EEH_ERR_TYPE_64 : EEH_ERR_TYPE_32;
+ op.err.addr = addr;
+ op.err.mask = mask;
+ if (func <= EEH_ERR_FUNC_MAX) {
+ op.err.func = func;
+ } else {
+ ret = RTAS_OUT_PARAM_ERROR;
+ goto out;
+ }
+
+ if (vfio_container_ioctl(&sphb->iommu_as, VFIO_EEH_PE_OP, &op) < 0) {
+ ret = RTAS_OUT_HW_ERROR;
+ goto out;
+ }
+
+ ret = RTAS_OUT_SUCCESS;
+out:
+ return ret;
+}
+
static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 5520fd2..684cd7a 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -637,6 +637,54 @@ out:
rtas_st(rets, 1, ret);
}
+static void rtas_ibm_errinjct(PowerPCCPU *cpu,
+ sPAPRMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args, uint32_t nret,
+ target_ulong rets)
+{
+ target_ulong param_buf;
+ uint32_t type, open_token;
+ int32_t ret;
+
+ /* Sanity check on number of arguments */
+ if (nargs != 3 || nret != 1) {
+ ret = RTAS_OUT_PARAM_ERROR;
+ goto out;
+ }
+
+ /* Check if we have opened token */
+ open_token = rtas_ld(args, 1);
+ if (!(spapr->errinjct_token & 1) ||
+ spapr->errinjct_token != open_token) {
+ ret = RTAS_OUT_CLOSE_ERROR;
+ goto out;
+ }
+
+ /* The parameter buffer should be 1KB aligned */
+ param_buf = rtas_ld(args, 2);
+ if (param_buf & 0x3ff) {
+ ret = RTAS_OUT_PARAM_ERROR;
+ goto out;
+ }
+
+ /* Check the error type */
+ type = rtas_ld(args, 0);
+ switch (type) {
+ case RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR:
+ ret = spapr_rtas_errinjct_ioa(spapr, param_buf, false);
+ break;
+ case RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR64:
+ ret = spapr_rtas_errinjct_ioa(spapr, param_buf, true);
+ break;
+ default:
+ ret = RTAS_OUT_PARAM_ERROR;
+ }
+
+out:
+ rtas_st(rets, 0, ret);
+}
+
static void rtas_ibm_close_errinjct(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
@@ -723,6 +771,33 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr
rtas_addr,
int i;
uint32_t lrdr_capacity[5];
MachineState *machine = MACHINE(qdev_get_machine());
+ char errinjct_tokens[1024];
+ int fdt_offset, offset;
+ const int tokens[] = {
+ RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR,
+ RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR64
+ };
+ const char *token_strings[] = {
+ "ioa-bus-error",
+ "ioa-bus-error-64"
+ };
+
+ /* ibm,errinjct-tokens */
+ offset = 0;
+ for (i = 0; i < ARRAY_SIZE(tokens); i++) {
+ offset += sprintf(errinjct_tokens + offset, "%s", token_strings[i]);
+ errinjct_tokens[offset++] = '\0';
+ stl_be_p(&errinjct_tokens[offset], tokens[i]);
+ offset += sizeof(int);
+ }
+
+ fdt_offset = fdt_path_offset(fdt, "/rtas");
+ ret = fdt_setprop(fdt, fdt_offset, "ibm,errinjct-tokens",
+ errinjct_tokens, offset);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't add ibm,errinjct-tokens\n");
+ return ret;
+ }
ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
if (ret < 0) {
@@ -818,6 +893,8 @@ static void core_rtas_register_types(void)
rtas_ibm_configure_connector);
spapr_rtas_register(RTAS_IBM_OPEN_ERRINJCT, "ibm,open-errinjct",
rtas_ibm_open_errinjct);
+ spapr_rtas_register(RTAS_IBM_ERRINJCT, "ibm,errinjct",
+ rtas_ibm_errinjct);
spapr_rtas_register(RTAS_IBM_CLOSE_ERRINJCT, "ibm,close-errinjct",
rtas_ibm_close_errinjct);
}
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 7f3c712..13ccdaf 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -137,6 +137,9 @@ int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state);
int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option);
int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb);
+int spapr_phb_vfio_eeh_inject_error(sPAPRPHBState *sphb,
+ uint32_t func, uint64_t addr,
+ uint64_t mask, bool is_64bits);
void spapr_phb_vfio_eeh_reenable(sPAPRPHBState *sphb);
#endif /* __HW_SPAPR_PCI_H__ */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 7931e18..66aea5c 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -408,6 +408,10 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
#define RTAS_SLOT_TEMP_ERR_LOG 1
#define RTAS_SLOT_PERM_ERR_LOG 2
+/* ibm,errinjct */
+#define RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR 7
+#define RTAS_ERRINJCT_TYPE_IOA_BUS_ERROR64 8
+
/* RTAS return codes */
#define RTAS_OUT_SUCCESS 0
#define RTAS_OUT_NO_ERRORS_FOUND 1
@@ -462,8 +466,9 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
#define RTAS_IBM_SLOT_ERROR_DETAIL (RTAS_TOKEN_BASE + 0x25)
#define RTAS_IBM_OPEN_ERRINJCT (RTAS_TOKEN_BASE + 0x26)
#define RTAS_IBM_CLOSE_ERRINJCT (RTAS_TOKEN_BASE + 0x27)
+#define RTAS_IBM_ERRINJCT (RTAS_TOKEN_BASE + 0x28)
-#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x28)
+#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x29)
/* RTAS ibm,get-system-parameter token values */
#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
@@ -600,6 +605,8 @@ int spapr_dma_dt(void *fdt, int node_off, const char
*propname,
int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
sPAPRTCETable *tcet);
void spapr_pci_switch_vga(bool big_endian);
+int spapr_rtas_errinjct_ioa(sPAPRMachineState *spapr,
+ target_ulong param_buf, bool is_64bits);
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc);
void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc);
void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
--
2.1.0
- [Qemu-ppc] [PATCH v8 0/7] sPAPR: Support EEH Error Injection, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 3/7] scripts: Submit changes while updating linux headers, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 2/7] scripts: Include arch/powerpc/include/uapi/asm/eeh.h, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 1/7] scripts: Allow include "stdint.h" in virtio headers, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 4/7] Synchronize Linux headers from kernel 4.3.0-rc1, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 6/7] sPAPR: Support RTAS call ibm, {open, close}-errinjct, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 5/7] Obsolete PCI_MSIX_FLAGS_BIRMASK, Gavin Shan, 2015/09/13
- [Qemu-ppc] [PATCH v8 7/7] sPAPR: Support RTAS call ibm,errinjct,
Gavin Shan <=
- Re: [Qemu-ppc] [PATCH v8 0/7] sPAPR: Support EEH Error Injection, David Gibson, 2015/09/14