From patchwork Mon May 5 01:28:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 4111261 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 714159F44A for ; Mon, 5 May 2014 01:28:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6DFFF20254 for ; Mon, 5 May 2014 01:28:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2A86E2037A for ; Mon, 5 May 2014 01:28:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754154AbaEEB2N (ORCPT ); Sun, 4 May 2014 21:28:13 -0400 Received: from e23smtp04.au.ibm.com ([202.81.31.146]:53280 "EHLO e23smtp04.au.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754133AbaEEB2G (ORCPT ); Sun, 4 May 2014 21:28:06 -0400 Received: from /spool/local by e23smtp04.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 5 May 2014 11:28:05 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp04.au.ibm.com (202.81.31.210) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 5 May 2014 11:28:02 +1000 Received: from d23relay05.au.ibm.com (d23relay05.au.ibm.com [9.190.235.152]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id 6DFF13578047; Mon, 5 May 2014 11:28:02 +1000 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay05.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s4516kHP1311020; Mon, 5 May 2014 11:06:46 +1000 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s451S1Kr011827; Mon, 5 May 2014 11:28:01 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.190.163.12]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s451S08C011819; Mon, 5 May 2014 11:28:00 +1000 Received: from shangw (haven.au.ibm.com [9.190.164.82]) by ozlabs.au.ibm.com (Postfix) with ESMTP id B799DA0117; Mon, 5 May 2014 11:28:00 +1000 (EST) Received: by shangw (Postfix, from userid 1000) id A4BEF3E0370; Mon, 5 May 2014 11:28:22 +1000 (EST) From: Gavin Shan To: linuxppc-dev@lists.ozlabs.org, kvm@vger.kernel.org, kvm-ppc@vger.kernel.org Cc: alex.williamson@redhat.com, benh@kernel.crashing.org, aik@ozlabs.ru, qiudayu@linux.vnet.ibm.com, Gavin Shan Subject: [PATCH 22/22] powerpc/powernv: Support PCI error injection Date: Mon, 5 May 2014 11:28:11 +1000 Message-Id: <1399253291-3975-23-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1399253291-3975-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1399253291-3975-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14050501-9264-0000-0000-00000601377C Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The patch introduces the infrastructure of error injection backend for PowerNV platform. For now, we just implement logic to inject PCI errors. We need support injecting other types of errors in future. Signed-off-by: Gavin Shan --- arch/powerpc/include/asm/book3s_errinjct.h | 19 +++ arch/powerpc/platforms/powernv/Makefile | 1 + arch/powerpc/platforms/powernv/errinjct.c | 215 +++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 arch/powerpc/platforms/powernv/errinjct.c diff --git a/arch/powerpc/include/asm/book3s_errinjct.h b/arch/powerpc/include/asm/book3s_errinjct.h index 35712be..75443ad 100644 --- a/arch/powerpc/include/asm/book3s_errinjct.h +++ b/arch/powerpc/include/asm/book3s_errinjct.h @@ -56,6 +56,25 @@ struct kvm_errinjct_token { struct list_head list; }; +/* Argument buffer for various operations */ +struct kvm_errinjct_ioa_bus { + uint32_t addr; + uint32_t mask; + uint32_t cfg_addr; + uint32_t buid_hi; + uint32_t buid_lo; + uint32_t op; +}; + +struct kvm_errinjct_ioa_bus64 { + uint64_t addr; + uint64_t mask; + uint32_t cfg_addr; + uint32_t buid_hi; + uint32_t buid_lo; + uint32_t op; +}; + int kvm_errinjct_register(int opcode, kvm_errinjct_func handler); int kvm_errinjct_unregister(int opcode); void kvmppc_errinjct_rtas(struct kvm_vcpu *vcpu, diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index d8ea670..d096b18 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o obj-$(CONFIG_KVM_EEH) += eeh-rtas.o +obj-$(CONFIG_KVM_ERRINJCT) += errinjct.o obj-$(CONFIG_PPC_SCOM) += opal-xscom.o obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o diff --git a/arch/powerpc/platforms/powernv/errinjct.c b/arch/powerpc/platforms/powernv/errinjct.c new file mode 100644 index 0000000..ccc7853 --- /dev/null +++ b/arch/powerpc/platforms/powernv/errinjct.c @@ -0,0 +1,215 @@ +/* + * Backend for error injection implemented on PowerNV platform. + * + * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2014. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "powernv.h" +#include "pci.h" + +static int powernv_errinjct_ioa(struct kvm_vcpu *vcpu, rtas_arg_t buf) +{ + struct OpalErrinjct ej; + struct kvm_errinjct_ioa_bus args; + struct eeh_vfio_pci_addr addr; + struct eeh_pe *pe; + struct pnv_phb *phb; + long rc; + int ret = 0; + + /* Word aligned buffer */ + if (buf & 0x3) { + ret = -3; + goto out; + } + + /* Copy over argument */ + ret = kvm_read_guest(vcpu->kvm, buf, &args, sizeof(args)); + if (ret) { + pr_warn("%s: Can't copyover arguments (%d)\n", + __func__, ret); + ret = -3; + goto out; + } + + /* + * Sanity check on operation. We don't support optional + * operation (20) and last one (21) for now. + */ + if (args.op < 0 || args.op > 21) { + ret = -3; + goto out; + } else if (args.op >= 20) { + ret = -1; + goto out; + } + + /* + * Only do error injection on passthrou PE. It's notable + * the "cfg_addr" is guest PE address + */ + addr.kvm = vcpu->kvm; + addr.buid_hi = args.buid_hi; + addr.buid_lo = args.buid_lo; + addr.pe_addr = args.cfg_addr; + pe = eeh_vfio_pe_get(&addr); + if (!pe) { + pr_warn("%s: Can't find passed PE (%08x-%08x-%08x)\n", + __func__, args.buid_hi, args.buid_lo, args.cfg_addr); + ret = -3; + goto out; + } + + /* + * Calling to OPAL API. We need host PE address + * and PHB host BUID. + */ + phb = pe->phb->private_data; + + ej.type = OpalErrinjctTypeIoaBusError; + ej.ioa.addr = args.addr; + ej.ioa.mask = args.mask; + ej.ioa.phb_id = phb->opal_id; + ej.ioa.pe = pe->addr; + ej.ioa.function = args.op; + rc = opal_err_injct(&ej); + if (rc != OPAL_SUCCESS) { + pr_warn("%s: OPAL API returns %ld\n", __func__, rc); + ret = -1; + goto out; + } + + ret = 0; +out: + return ret; +} + +static int powernv_errinjct_ioa64(struct kvm_vcpu *vcpu, rtas_arg_t buf) +{ + struct OpalErrinjct ej; + struct kvm_errinjct_ioa_bus64 args; + struct eeh_vfio_pci_addr addr; + struct eeh_pe *pe; + struct pnv_phb *phb; + long rc; + int ret = 0; + + /* Double word aligned buffer */ + if (buf & 0x7) { + ret = -3; + goto out; + } + + /* Copy over argument */ + ret = kvm_read_guest(vcpu->kvm, buf, &args, sizeof(args)); + if (ret) { + pr_warn("%s: Can't copyover arguments (%d)\n", + __func__, ret); + ret = -3; + goto out; + } + + /* + * Sanity check on operation. We don't support optional + * operation (20) and last one (21) for now. + */ + if (args.op < 0 || args.op > 21) { + ret = -3; + goto out; + } else if (args.op >= 20) { + ret = -1; + goto out; + } + + /* + * Only do error injection on passthrou PE. It's notable + * that "cfg_addr" is guest PE address + */ + addr.kvm = vcpu->kvm; + addr.buid_hi = args.buid_hi; + addr.buid_lo = args.buid_lo; + addr.pe_addr = args.cfg_addr; + pe = eeh_vfio_pe_get(&addr); + if (!pe) { + pr_warn("%s: Can't find passed PE (%08x-%08x-%08x)\n", + __func__, args.buid_hi, args.buid_lo, args.cfg_addr); + ret = -3; + goto out; + } + + /* + * Calling to OPAL API. We need host PE address + * and PHB host BUID. + */ + phb = pe->phb->private_data; + + ej.type = OpalErrinjctTypeIoaBusError64; + ej.ioa64.addr = args.addr; + ej.ioa64.mask = args.mask; + ej.ioa64.phb_id = phb->opal_id; + ej.ioa64.pe = pe->addr; + ej.ioa64.function = args.op; + rc = opal_err_injct(&ej); + if (rc != OPAL_SUCCESS) { + pr_warn("%s: OPAL API returns %ld\n", __func__, rc); + ret = -1; + goto out; + } + + /* Success */ + ret = 0; +out: + return ret; +} + +static struct kvm_errinjct_handler handlers[] = { + { .opcode = kvm_errinjct_ioa_bus_error, + .handler = powernv_errinjct_ioa + }, + { .opcode = kvm_errinjct_ioa_bus_error_64, + .handler = powernv_errinjct_ioa64 + } +}; + +static int __init powernv_errinjct_init(void) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(handlers); i++) { + ret = kvm_errinjct_register(handlers[i].opcode, + handlers[i].handler); + if (ret) { + pr_warn("%s: Failure registering handler %d (%d)\n", + __func__, handlers[i].opcode, ret); + return ret; + } + } + + return 0; +} + +module_init(powernv_errinjct_init);