From patchwork Mon Dec 3 18:06:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Morse X-Patchwork-Id: 10710263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F0F031057 for ; Mon, 3 Dec 2018 18:07:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5FB92B47E for ; Mon, 3 Dec 2018 18:07:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D99FF2B495; Mon, 3 Dec 2018 18:07:48 +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,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F16F2B47E for ; Mon, 3 Dec 2018 18:07:48 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5C5A06B6A86; Mon, 3 Dec 2018 13:07:36 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 526606B6A87; Mon, 3 Dec 2018 13:07:36 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3ED5D6B6A88; Mon, 3 Dec 2018 13:07:36 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-ot1-f71.google.com (mail-ot1-f71.google.com [209.85.210.71]) by kanga.kvack.org (Postfix) with ESMTP id 0A75E6B6A86 for ; Mon, 3 Dec 2018 13:07:36 -0500 (EST) Received: by mail-ot1-f71.google.com with SMTP id j18so5866443oth.11 for ; Mon, 03 Dec 2018 10:07:36 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=bBlvTiFpt5mSFqNPhoI7cPO8rL4wf6nBDu/9DNR5+ow=; b=c8Kw8tKgT+9tWiDNwX5F0nEVEHVsERBDhpf6I5thXDxTPTp/IOKtz2GtuRjZB4MuZW N29o2e1teZ+04Ask3b2SnZ94esdOa6fyih2wlUfgB4maTr1y6ZSoSEj1AIcPJ8AMCbKx O8OJCbWNheTzngQE7DqvSfEjYSCnyC8ICgDmNZBcsXKZ+ajA9a9qoUCOBSvkR4psC9bP EvykYEaqeNHp78LKLznJixW9/WJuvu+Et2V0/2+yTme9aVctqJnW6uhVgiSknv1mUWvf 2zzVCCfbjRH+x6iAGhUX0fjOt+oR14tI7SIpB1aVTknKVkPXVrJ71jIJ98tLRoHocYU7 XxVg== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of james.morse@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=james.morse@arm.com X-Gm-Message-State: AA+aEWZOcDkwpNuZ4vpQqdNhAMvaNpWefSh5n51dz2Lc0TnBlD3UFr+J DyK2syT08pHOYSEVgJYbxV06kJfJDV9w16D6C59TbHHxJLEXkNw8AZt7V5GDm34Yg992ljimQHl I5/TkFr1ZbwMkz/2cmzt0kNWTKQnI5AFYmhqsvDoPPo0pWI1qUvoFaXSq+HXDolGJNA== X-Received: by 2002:aca:5e0b:: with SMTP id s11mr11087861oib.62.1543860455786; Mon, 03 Dec 2018 10:07:35 -0800 (PST) X-Google-Smtp-Source: AFSGD/WcxAcqMkrAhyQD3m/km359Fsy9ueknIIFRxUROcd5lK0754FM4MnT8B1e2Jn1yLxe2B2fh X-Received: by 2002:aca:5e0b:: with SMTP id s11mr11087829oib.62.1543860454829; Mon, 03 Dec 2018 10:07:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543860454; cv=none; d=google.com; s=arc-20160816; b=IgPq5MY+8Y25N8Y+pWexP1kP4owBb0vWSxOdj3FFYvgkIqGX3Ampuajg/Y2krE619C 8HhZOwu0OENg0OUIRARCLSka1sH7KabFNdQyEZ2QMsXGBAzJf7E0cJQREFtZVKgBUmsQ N4AoGDgBJFPGqGAN6UElza1pgTkymitM3bBo4+pCmrWBYLGg6kxxBz0o3sptr4b6Fe+b R9Jx5sgbrK9Nf7L11e616r3V6j/cA9sIHLAdP85S9R6M/+09F7lIKeSd/4WP0/lCmeie RIdYkRqVw4cc5KEEUfOSCDFUg0+DR1dLTyo5x9CZVVDPKN7RXJc5sveKpmKlkiNVZDtc RIRw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=bBlvTiFpt5mSFqNPhoI7cPO8rL4wf6nBDu/9DNR5+ow=; b=pa+wDwMckS+kdVqVVFtyToxJLwNX9uUAKHd6jMovsChwD47ciMcaHqcE5WJYK162wW zf0bg2oNNsBlNWrYNZ0Y2SvxxWNYgBqqRPrhGnn11CE/xq4WUhTiFb5Mz129tfGbfuM2 8/UgL7BbUFfxZtjjHi5/SY0j2CiKH20B+3sOKVZnexCg5IgHOGEMFDuT5L/YwM7BwUjv 8t/QiKXxdqW+Kue3kJy24T/KPWYO2MRO48dx1Uo8uhXnO4Q0zGgjDxLnRGLWscecseQ2 EoAXhx8DgHGH+MuJ3S8XXDTfl9R6hfUVqkILM2o7sNzdDAemQ+XgiqYgHY5/OEfzDfUv FbZg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of james.morse@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=james.morse@arm.com Received: from foss.arm.com (usa-sjc-mx-foss1.foss.arm.com. [217.140.101.70]) by mx.google.com with ESMTP id 4si5898124oiz.163.2018.12.03.10.07.34 for ; Mon, 03 Dec 2018 10:07:34 -0800 (PST) Received-SPF: pass (google.com: domain of james.morse@arm.com designates 217.140.101.70 as permitted sender) client-ip=217.140.101.70; Authentication-Results: mx.google.com; spf=pass (google.com: domain of james.morse@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=james.morse@arm.com 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 583751682; Mon, 3 Dec 2018 10:07:34 -0800 (PST) Received: from eglon.cambridge.arm.com (eglon.cambridge.arm.com [10.1.196.105]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8834F3F59C; Mon, 3 Dec 2018 10:07:31 -0800 (PST) From: James Morse To: linux-acpi@vger.kernel.org Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, Borislav Petkov , Marc Zyngier , Christoffer Dall , Will Deacon , Catalin Marinas , Naoya Horiguchi , Rafael Wysocki , Len Brown , Tony Luck , Dongjiu Geng , Xie XiuQi , Fan Wu , James Morse Subject: [PATCH v7 16/25] ACPI / APEI: Let the notification helper specify the fixmap slot Date: Mon, 3 Dec 2018 18:06:04 +0000 Message-Id: <20181203180613.228133-17-james.morse@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181203180613.228133-1-james.morse@arm.com> References: <20181203180613.228133-1-james.morse@arm.com> MIME-Version: 1.0 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP ghes_copy_tofrom_phys() uses a different fixmap slot depending on in_nmi(). This doesn't work when there are multiple NMI-like notifications, that could interrupt each other. As with the locking, move the chosen fixmap_idx to the notification helper. This only matters for NMI-like notifications, anything calling ghes_proc() can use the IRQ fixmap slot as its already holding an irqsave spinlock. This lets us collapse the ghes_ioremap_pfn_*() helpers. Signed-off-by: James Morse Reviewed-by: Borislav Petkov --- The fixmap-idx and vaddr are passed back to ghes_unmap() to allow ioremap() to be used in process context in the future. This will let us send tlbi-ipi for notifications that don't mask irqs. --- drivers/acpi/apei/ghes.c | 79 +++++++++++++++------------------------- 1 file changed, 30 insertions(+), 49 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 30490eff7704..b5c31f65a1c0 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -127,38 +128,24 @@ static atomic_t ghes_estatus_cache_alloced; static int ghes_panic_timeout __read_mostly = 30; -static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn) +static void __iomem *ghes_map(u64 pfn, int fixmap_idx) { phys_addr_t paddr; pgprot_t prot; - paddr = pfn << PAGE_SHIFT; + paddr = PFN_PHYS(pfn); prot = arch_apei_get_mem_attribute(paddr); - __set_fixmap(FIX_APEI_GHES_NMI, paddr, prot); + __set_fixmap(fixmap_idx, paddr, prot); - return (void __iomem *) fix_to_virt(FIX_APEI_GHES_NMI); + return (void __iomem *) __fix_to_virt(fixmap_idx); } -static void __iomem *ghes_ioremap_pfn_irq(u64 pfn) +static void ghes_unmap(int fixmap_idx, void __iomem *vaddr) { - phys_addr_t paddr; - pgprot_t prot; - - paddr = pfn << PAGE_SHIFT; - prot = arch_apei_get_mem_attribute(paddr); - __set_fixmap(FIX_APEI_GHES_IRQ, paddr, prot); + int _idx = virt_to_fix((unsigned long)vaddr); - return (void __iomem *) fix_to_virt(FIX_APEI_GHES_IRQ); -} - -static void ghes_iounmap_nmi(void) -{ - clear_fixmap(FIX_APEI_GHES_NMI); -} - -static void ghes_iounmap_irq(void) -{ - clear_fixmap(FIX_APEI_GHES_IRQ); + WARN_ON_ONCE(fixmap_idx != _idx); + clear_fixmap(fixmap_idx); } int ghes_estatus_pool_init(int num_ghes) @@ -268,20 +255,15 @@ static inline int ghes_severity(int severity) } static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, - int from_phys) + int from_phys, int fixmap_idx) { void __iomem *vaddr; - int in_nmi = in_nmi(); u64 offset; u32 trunk; while (len > 0) { offset = paddr - (paddr & PAGE_MASK); - if (in_nmi) { - vaddr = ghes_ioremap_pfn_nmi(paddr >> PAGE_SHIFT); - } else { - vaddr = ghes_ioremap_pfn_irq(paddr >> PAGE_SHIFT); - } + vaddr = ghes_map(PHYS_PFN(paddr), fixmap_idx); trunk = PAGE_SIZE - offset; trunk = min(trunk, len); if (from_phys) @@ -291,15 +273,12 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, len -= trunk; paddr += trunk; buffer += trunk; - if (in_nmi) { - ghes_iounmap_nmi(); - } else { - ghes_iounmap_irq(); - } + ghes_unmap(fixmap_idx, vaddr); } } -static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr) +static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr, int fixmap_idx) + { struct acpi_hest_generic *g = ghes->generic; u32 len; @@ -317,7 +296,7 @@ static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr) return -ENOENT; ghes_copy_tofrom_phys(ghes->estatus, *buf_paddr, - sizeof(*ghes->estatus), 1); + sizeof(*ghes->estatus), 1, fixmap_idx); if (!ghes->estatus->block_status) { *buf_paddr = 0; return -ENOENT; @@ -333,7 +312,7 @@ static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr) goto err_read_block; ghes_copy_tofrom_phys(ghes->estatus + 1, *buf_paddr + sizeof(*ghes->estatus), - len - sizeof(*ghes->estatus), 1); + len - sizeof(*ghes->estatus), 1, fixmap_idx); if (cper_estatus_check(ghes->estatus)) goto err_read_block; rc = 0; @@ -346,12 +325,13 @@ static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr) return rc; } -static void ghes_clear_estatus(struct ghes *ghes, u64 buf_paddr) +static void ghes_clear_estatus(struct ghes *ghes, u64 buf_paddr, int fixmap_idx) { ghes->estatus->block_status = 0; if (buf_paddr) ghes_copy_tofrom_phys(ghes->estatus, buf_paddr, - sizeof(ghes->estatus->block_status), 0); + sizeof(ghes->estatus->block_status), 0, + fixmap_idx); } static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) @@ -673,7 +653,7 @@ static int ghes_proc(struct ghes *ghes) u64 buf_paddr; int rc; - rc = ghes_read_estatus(ghes, &buf_paddr); + rc = ghes_read_estatus(ghes, &buf_paddr, FIX_APEI_GHES_IRQ); if (rc) goto out; @@ -688,7 +668,7 @@ static int ghes_proc(struct ghes *ghes) ghes_do_proc(ghes, ghes->estatus); out: - ghes_clear_estatus(ghes, buf_paddr); + ghes_clear_estatus(ghes, buf_paddr, FIX_APEI_GHES_IRQ); if (rc == -ENOENT) return rc; @@ -864,13 +844,13 @@ static void __process_error(struct ghes *ghes) #endif } -static int _in_nmi_notify_one(struct ghes *ghes) +static int _in_nmi_notify_one(struct ghes *ghes, int fixmap_idx) { u64 buf_paddr; int sev; - if (ghes_read_estatus(ghes, &buf_paddr)) { - ghes_clear_estatus(ghes, buf_paddr); + if (ghes_read_estatus(ghes, &buf_paddr, fixmap_idx)) { + ghes_clear_estatus(ghes, buf_paddr, fixmap_idx); return -ENOENT; } @@ -881,7 +861,7 @@ static int _in_nmi_notify_one(struct ghes *ghes) } __process_error(ghes); - ghes_clear_estatus(ghes, buf_paddr); + ghes_clear_estatus(ghes, buf_paddr, fixmap_idx); if (is_hest_type_generic_v2(ghes) && ghes_ack_error(ghes->generic_v2)) pr_warn_ratelimited(FW_WARN GHES_PFX @@ -890,14 +870,15 @@ static int _in_nmi_notify_one(struct ghes *ghes) return 0; } -static int ghes_estatus_queue_notified(struct list_head *rcu_list) +static int ghes_estatus_queue_notified(struct list_head *rcu_list, + int fixmap_idx) { int ret = -ENOENT; struct ghes *ghes; rcu_read_lock(); list_for_each_entry_rcu(ghes, rcu_list, list) { - if (!_in_nmi_notify_one(ghes)) + if (!_in_nmi_notify_one(ghes, fixmap_idx)) ret = 0; } rcu_read_unlock(); @@ -921,7 +902,7 @@ int ghes_notify_sea(void) int rv; raw_spin_lock(&ghes_notify_lock_sea); - rv = ghes_estatus_queue_notified(&ghes_sea); + rv = ghes_estatus_queue_notified(&ghes_sea, FIX_APEI_GHES_NMI); raw_spin_unlock(&ghes_notify_lock_sea); return rv; @@ -964,7 +945,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) return ret; raw_spin_lock(&ghes_notify_lock_nmi); - if (!ghes_estatus_queue_notified(&ghes_nmi)) + if (!ghes_estatus_queue_notified(&ghes_nmi, FIX_APEI_GHES_NMI)) ret = NMI_HANDLED; raw_spin_unlock(&ghes_notify_lock_nmi);