From patchwork Mon Sep 14 01:36:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 517255 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6696C140338 for ; Mon, 14 Sep 2015 11:43:47 +1000 (AEST) Received: from localhost ([::1]:37807 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZbIo5-00033H-IO for incoming@patchwork.ozlabs.org; Sun, 13 Sep 2015 21:43:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46777) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZbIiL-00022O-1W for qemu-devel@nongnu.org; Sun, 13 Sep 2015 21:37:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZbIiH-0008IY-61 for qemu-devel@nongnu.org; Sun, 13 Sep 2015 21:37:48 -0400 Received: from e23smtp03.au.ibm.com ([202.81.31.145]:49883) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZbIiG-0008Hu-BH for qemu-devel@nongnu.org; Sun, 13 Sep 2015 21:37:45 -0400 Received: from /spool/local by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 14 Sep 2015 11:37:42 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 14 Sep 2015 11:37:40 +1000 X-Helo: d23dlp03.au.ibm.com X-MailFrom: gwshan@linux.vnet.ibm.com X-RcptTo: qemu-ppc@nongnu.org Received: from d23relay10.au.ibm.com (d23relay10.au.ibm.com [9.190.26.77]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id 8552A357804F; Mon, 14 Sep 2015 11:37:39 +1000 (EST) Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t8E1bVI749086630; Mon, 14 Sep 2015 11:37:39 +1000 Received: from d23av01.au.ibm.com (localhost [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t8E1b69r032173; Mon, 14 Sep 2015 11:37:06 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t8E1b5AL031374; Mon, 14 Sep 2015 11:37:05 +1000 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) by ozlabs.au.ibm.com (Postfix) with ESMTP id 80189A03E0; Mon, 14 Sep 2015 11:36:18 +1000 (AEST) Received: from gwshan (shangw.ozlabs.ibm.com [10.61.2.199]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id 7964EE450D; Mon, 14 Sep 2015 11:36:18 +1000 (AEST) Received: by gwshan (Postfix, from userid 1000) id 7398F941B2D; Mon, 14 Sep 2015 11:36:18 +1000 (AEST) From: Gavin Shan To: qemu-devel@nongnu.org Date: Mon, 14 Sep 2015 11:36:15 +1000 Message-Id: <1442194575-8537-8-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1442194575-8537-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1442194575-8537-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15091401-0009-0000-0000-0000020C9D0E X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 202.81.31.145 Cc: lvivier@redhat.com, peter.maydell@linaro.org, thuth@redhat.com, Gavin Shan , qemu-ppc@nongnu.org, david@gibson.dropbear.id.au Subject: [Qemu-devel] [PATCH v8 7/7] sPAPR: Support RTAS call ibm,errinjct X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: David Gibson --- 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 . */ +#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,