From patchwork Tue Jun 26 17:01:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Morse X-Patchwork-Id: 10489963 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8B75D6023A for ; Tue, 26 Jun 2018 18:06:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7F19E286E1 for ; Tue, 26 Jun 2018 18:06:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 719AC28710; Tue, 26 Jun 2018 18:06:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D4C24286E1 for ; Tue, 26 Jun 2018 18:06:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=4MZAwGZ7q+hUQcaq039EBuLQ82Mpc11fUyN4wCS+jUQ=; b=OZekEQ9v/XVYn7akjJ2HU8UzbB hlb9Bg84WEPPI9pdrNyqXCFvQ0z02xqQ+mC8Kuyu4lK8EdNoCgW0tupbVtTxGJYYIeAtZl1c7Yq3z yUnL2rJWnmrd35pH7vOgWFW91s8werR2t+CN6SfsKBxxH8mD8QeiVhT2kq4Mb/x1PXWqlqLsZJ2Wl 3CwCBIIGVCZGnU7tOkqX/6+0aJOTALxj4QCz7B3Lvn1u/16rFaa452AD0F97vGksJFSZkJey9A0rY ayv4bv2H5qAt4s0pN7UA2o9He9sURDb+GZfAUN/Tp+WLJn/rFg4RxNfs/HY0OrJBwGkVUM0taXtvY iNakMtdw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fXsMV-0006gQ-Hy; Tue, 26 Jun 2018 18:06:43 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fXsLN-0005zW-PD for linux-arm-kernel@bombadil.infradead.org; Tue, 26 Jun 2018 18:05:33 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=5oEyi1psR52+AKJ96dGQ3WwbRFw+8tTAR3q7/aWhsf4=; b=NV6pdv5CAmTiUeWlOkrjK1FlG ssgerO+7CLXqySzybvq5bW59LOdo8FNK5z+9j2Oqw0ugzYv14B47f3WROaeK8xsvSJNy5Kun9IXBl iR9DYGoaJ7WoRfOHqgJiLlg2eaK7m1e+bG1DckYuTSYHSTHNWzjs4gGepTf+U7KNikirURV7EfVPq RKl1FkcECALgaIkiwcXoLSv6LWpmTyQKGuLPzHdqIjXF6R7i6y+kF5eobxjSg3FDo1pfgkz2L89Zy m9lZ4fUUTQEiC6U5tfGAsK7LPWUy9OqX/5haX+yX+/U5w8ypDci5n/i9Yfc6TX/dyaowHV7Lhoylx 9BzvgN94A==; Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by merlin.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fXrMo-0003cZ-CI for linux-arm-kernel@lists.infradead.org; Tue, 26 Jun 2018 17:02:59 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AECD61713; Tue, 26 Jun 2018 10:02:47 -0700 (PDT) Received: from melchizedek.cambridge.arm.com (melchizedek.cambridge.arm.com [10.1.206.34]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 50E253F318; Tue, 26 Jun 2018 10:02:44 -0700 (PDT) From: James Morse To: linux-acpi@vger.kernel.org Subject: [PATCH v5 14/20] ACPI / APEI: Split ghes_read_estatus() to read CPER length Date: Tue, 26 Jun 2018 18:01:10 +0100 Message-Id: <20180626170116.25825-15-james.morse@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180626170116.25825-1-james.morse@arm.com> References: <20180626170116.25825-1-james.morse@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180626_130258_623066_B8A3FD5A X-CRM114-Status: GOOD ( 19.07 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jonathan.zhang@cavium.com, Rafael Wysocki , Tony Luck , Punit Agrawal , Xie XiuQi , Marc Zyngier , Catalin Marinas , Tyler Baicar , Will Deacon , Christoffer Dall , Dongjiu Geng , linux-mm@kvack.org, Borislav Petkov , James Morse , Naoya Horiguchi , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Len Brown MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP ghes_read_estatus() reads the record address, then the record's header, then performs some sanity checks before reading the records into the provided estatus buffer. We either need to know the size of the records before we call ghes_read_estatus(), or always provide a worst-case sized buffer, as happens today. Add a function to peek at the record's header to find the size. This will let the NMI path allocate the right amount of memory before reading the records, instead of using the worst-case size, and having to copy the records. Split ghes_read_estatus() to create ghes_peek_estatus() which returns the address and size of the CPER records. Signed-off-by: James Morse --- drivers/acpi/apei/ghes.c | 55 ++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 75360525935d..1d59d85b38d2 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -289,11 +289,12 @@ static void ghes_copy_tofrom_phys(void *buffer, phys_addr_t paddr, u32 len, } } -static int ghes_read_estatus(struct ghes *ghes, - struct acpi_hest_generic_status *estatus, - phys_addr_t *buf_paddr, int fixmap_idx) +/* read the CPER block returning its address and size */ +static int ghes_peek_estatus(struct ghes *ghes, int fixmap_idx, + phys_addr_t *buf_paddr, u32 *buf_len) { struct acpi_hest_generic *g = ghes->generic; + struct acpi_hest_generic_status estatus; u32 len; int rc; @@ -308,26 +309,23 @@ static int ghes_read_estatus(struct ghes *ghes, if (!*buf_paddr) return -ENOENT; - ghes_copy_tofrom_phys(estatus, *buf_paddr, - sizeof(*estatus), 1, fixmap_idx); - if (!estatus->block_status) { + ghes_copy_tofrom_phys(&estatus, *buf_paddr, + sizeof(estatus), 1, fixmap_idx); + if (!estatus.block_status) { *buf_paddr = 0; return -ENOENT; } rc = -EIO; - len = cper_estatus_len(estatus); - if (len < sizeof(*estatus)) + len = cper_estatus_len(&estatus); + if (len < sizeof(estatus)) goto err_read_block; if (len > ghes->generic->error_block_length) goto err_read_block; - if (cper_estatus_check_header(estatus)) - goto err_read_block; - ghes_copy_tofrom_phys(estatus + 1, - *buf_paddr + sizeof(*estatus), - len - sizeof(*estatus), 1, fixmap_idx); - if (cper_estatus_check(estatus)) + if (cper_estatus_check_header(&estatus)) goto err_read_block; + *buf_len = len; + rc = 0; err_read_block: @@ -337,6 +335,35 @@ static int ghes_read_estatus(struct ghes *ghes, return rc; } +static int __ghes_read_estatus(struct acpi_hest_generic_status *estatus, + phys_addr_t buf_paddr, size_t buf_len, + int fixmap_idx) +{ + ghes_copy_tofrom_phys(estatus, buf_paddr, buf_len, 1, fixmap_idx); + if (cper_estatus_check(estatus)) { + if (printk_ratelimit()) + pr_warning(FW_WARN GHES_PFX + "Failed to read error status block!\n"); + return -EIO; + } + + return 0; +} + +static int ghes_read_estatus(struct ghes *ghes, + struct acpi_hest_generic_status *estatus, + phys_addr_t *buf_paddr, int fixmap_idx) +{ + int rc; + u32 buf_len; + + rc = ghes_peek_estatus(ghes, fixmap_idx, buf_paddr, &buf_len); + if (rc) + return rc; + + return __ghes_read_estatus(estatus, *buf_paddr, buf_len, fixmap_idx); +} + static void ghes_clear_estatus(struct acpi_hest_generic_status *estatus, phys_addr_t buf_paddr, int fixmap_idx) {