From patchwork Fri Jun 9 06:06:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell Currey X-Patchwork-Id: 773667 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wkWzM0rjBz9s72 for ; Fri, 9 Jun 2017 16:07:27 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="PBeZSaV8"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3wkWzL6wNKzDqN8 for ; Fri, 9 Jun 2017 16:07:26 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="PBeZSaV8"; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3wkWyJ3gQ7zDqLL for ; Fri, 9 Jun 2017 16:06:32 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="PBeZSaV8"; dkim-atps=neutral Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id DB57220886; Fri, 9 Jun 2017 02:06:29 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute6.internal (MEProxy); Fri, 09 Jun 2017 02:06:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=fm1; bh=T3obYRXVrcjeT9FI1F5vHZonyEGDLWISv1MixHDR6 dE=; b=PBeZSaV8ctNdxhF/Q1AkXQkAiSha+SiJS8SJp7XDexSkO4KeORfNduDCP JrOJ65n/c/5rYDeaPkSWbDU5fQxhLZqA7jtlJqMlVENbDynoogczJ8X5hyGW6N7y o6v5cyqnNhBT1ULEiszVXBxKUjuTujzHDkJPzOngIxZ6FkQ3YkAXhzd/CNM/dhhs zEZ9maJXeOWU3PLXfcZfnM0wYGKfC+D/Liz271kSdD8oS4zzjmYlmRbUxsGzEZKU cU9DRgjsiltA2fhr9b+s/e9I3AGXDsh/jXO5iguFGCMYsa15yyZ7FBaWFG7OVCND JY62gDTqEKlrYuQe6HRSDeWSuAbnQ== X-ME-Sender: X-Sasl-enc: JrGnJTQ/2yr0VorO92geDkmeMsRr1NhTF8EQQXxDffnw 1496988389 Received: from snap.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 83A1A7E545; Fri, 9 Jun 2017 02:06:28 -0400 (EDT) From: Russell Currey To: skiboot@lists.ozlabs.org Date: Fri, 9 Jun 2017 16:06:06 +1000 Message-Id: <20170609060606.17796-6-ruscur@russell.cc> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170609060606.17796-1-ruscur@russell.cc> References: <20170609060606.17796-1-ruscur@russell.cc> Subject: [Skiboot] [PATCH 5/5] phb4: Error injection for config space X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Implement CFG (config space) error injection. This works the same as PHB3. MMIO and DMA error injection require a rewrite, so they're unsupported for now. While it's not feature complete, this at least provides an easy way to inject an error that will trigger EEH. Signed-off-by: Russell Currey --- hw/phb4.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/hw/phb4.c b/hw/phb4.c index 3a54e034..7bcbc931 100644 --- a/hw/phb4.c +++ b/hw/phb4.c @@ -2511,11 +2511,191 @@ static int64_t phb4_eeh_next_error(struct phb *phb, return OPAL_SUCCESS; } +static int64_t phb4_err_inject_finalize(struct phb4 *phb, uint64_t addr, + uint64_t mask, uint64_t ctrl, + bool is_write) +{ + if (is_write) + ctrl |= PHB_PAPR_ERR_INJ_CTL_WR; + else + ctrl |= PHB_PAPR_ERR_INJ_CTL_RD; + + out_be64(phb->regs + PHB_PAPR_ERR_INJ_ADDR, addr); + out_be64(phb->regs + PHB_PAPR_ERR_INJ_MASK, mask); + out_be64(phb->regs + PHB_PAPR_ERR_INJ_CTL, ctrl); + + return OPAL_SUCCESS; +} + +static int64_t phb4_err_inject_mem32(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write) +{ + return OPAL_UNSUPPORTED; +} + +static int64_t phb4_err_inject_mem64(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write) +{ + return OPAL_UNSUPPORTED; +} + +static int64_t phb4_err_inject_cfg(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write) +{ + uint64_t a, m, prefer, ctrl; + int bdfn; + bool is_bus_pe = false; + + a = 0xffffull; + prefer = 0xffffull; + m = PHB_PAPR_ERR_INJ_MASK_CFG_ALL; + ctrl = PHB_PAPR_ERR_INJ_CTL_CFG; + + for (bdfn = 0; bdfn < RTT_TABLE_ENTRIES; bdfn++) { + if (phb->rte_cache[bdfn] != pe_number) + continue; + + /* The PE can be associated with PCI bus or device */ + is_bus_pe = false; + if ((bdfn + 8) < RTT_TABLE_ENTRIES && + phb->rte_cache[bdfn + 8] == pe_number) + is_bus_pe = true; + + /* Figure out the PCI config address */ + if (prefer == 0xffffull) { + if (is_bus_pe) { + m = PHB_PAPR_ERR_INJ_MASK_CFG; + prefer = SETFIELD(m, 0x0ull, (bdfn >> 8)); + } else { + m = PHB_PAPR_ERR_INJ_MASK_CFG_ALL; + prefer = SETFIELD(m, 0x0ull, bdfn); + } + } + + /* Check the input address is valid or not */ + if (!is_bus_pe && + GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG_ALL, addr) == bdfn) { + a = addr; + break; + } + + if (is_bus_pe && + GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, addr) == (bdfn >> 8)) { + a = addr; + break; + } + } + + /* Invalid PE number */ + if (prefer == 0xffffull) + return OPAL_PARAMETER; + + /* Specified address is out of range */ + if (a == 0xffffull) + a = prefer; + else + m = mask; + + return phb4_err_inject_finalize(phb, a, m, ctrl, is_write); +} + +static int64_t phb4_err_inject_dma(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write, bool is_64bits) +{ + return OPAL_UNSUPPORTED; +} + +static int64_t phb4_err_inject_dma32(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write) +{ + return phb4_err_inject_dma(phb, pe_number, addr, mask, is_write, false); +} + +static int64_t phb4_err_inject_dma64(struct phb4 *phb, uint64_t pe_number, + uint64_t addr, uint64_t mask, + bool is_write) +{ + return phb4_err_inject_dma(phb, pe_number, addr, mask, is_write, true); +} + + static int64_t phb4_err_inject(struct phb *phb, uint64_t pe_number, uint32_t type, uint32_t func, uint64_t addr, uint64_t mask) { - return OPAL_UNSUPPORTED; + struct phb4 *p = phb_to_phb4(phb); + int64_t (*handler)(struct phb4 *p, uint64_t pe_number, + uint64_t addr, uint64_t mask, bool is_write); + bool is_write; + + /* How could we get here without valid RTT? */ + if (!p->tbl_rtt) + return OPAL_HARDWARE; + + /* We can't inject error to the reserved PE */ + if (pe_number == PHB4_RESERVED_PE_NUM(p) || pe_number >= p->num_pes) + return OPAL_PARAMETER; + + /* Clear leftover from last time */ + out_be64(p->regs + PHB_PAPR_ERR_INJ_CTL, 0x0ul); + + switch (func) { + case OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_DATA: + is_write = false; + if (type == OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) + handler = phb4_err_inject_mem64; + else + handler = phb4_err_inject_mem32; + break; + case OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_DATA: + is_write = true; + if (type == OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) + handler = phb4_err_inject_mem64; + else + handler = phb4_err_inject_mem32; + break; + case OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_DATA: + is_write = false; + handler = phb4_err_inject_cfg; + break; + case OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_DATA: + is_write = true; + handler = phb4_err_inject_cfg; + break; + case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_DATA: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_MASTER: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_TARGET: + is_write = false; + if (type == OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) + handler = phb4_err_inject_dma64; + else + handler = phb4_err_inject_dma32; + break; + case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_ADDR: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_DATA: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_MASTER: + case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET: + is_write = true; + if (type == OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) + handler = phb4_err_inject_dma64; + else + handler = phb4_err_inject_dma32; + break; + default: + return OPAL_PARAMETER; + } + + return handler(p, pe_number, addr, mask, is_write); } static int64_t phb4_get_diag_data(struct phb *phb,