From patchwork Thu Mar 30 10:31:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xie XiuQi X-Patchwork-Id: 9653985 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 C56CF60349 for ; Thu, 30 Mar 2017 11:44:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B89A22857F for ; Thu, 30 Mar 2017 11:44:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD00428585; Thu, 30 Mar 2017 11:44:16 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 2227D2857F for ; Thu, 30 Mar 2017 11:44:16 +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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=u0sWosJAPTISOaXqXOTL/xJxquihLGVEkP7GdprIQrs=; b=d4OZu1IBNIa2Am tSlnAoneVHh5ulj3oB8uyfwuU3WcqZMp83N8a1xpBPhZMGq7v+XdU3+dmHfYdS7a5KvUaoOXjF9Nz B9cSPzvt/4K0ODXLfH3HIHmwdFp2N9n4C4omQ7FvcKyYpNoGdA4gSGTghjzAbzrhI6WF9Nwv1i0Pa 4+tbqQ/FN/IboFHztPv7w6L3Z75d15UkApnAY/Mgnmajsoev0zTYPcn0M8AQPVmKfi+gqEjLiQOku 4SZlnY13Q6+bIARq7Cua21O24EFDSby+avyxmrXkJ2XRXEfZEf8tX3xaaUcnAn+fD3SDO0oRAYzp5 WlMHRtvSQtNpS1m+UelQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ctYUp-0007Zs-4E; Thu, 30 Mar 2017 11:44:07 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ctYUm-0007ZQ-Ry for linux-arm-kernel@bombadil.infradead.org; Thu, 30 Mar 2017 11:44:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:CC:To:From:Sender:Reply-To: 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=kYiC7rYtvu5jbbJKGi1YsR+sgjvDX3+7Ox8wCcCP9yA=; b=IngFGh/rCLWq0ng/tcZzuQOcm WMTCsf/TTqjnz8add4pxP1U1nD8MXg+qlsE1mqxTvAOotAsnFMdPDEKtWC0QwfeLXpRmKwCeT+vve XTAq7gLThwyvGKPLMuuix266W37mVRYM9kMoY/kCv0sUtRkNVWqik1yluiVoFlC3VEMEuvwfVJ0J9 qh1VNcdVx4YNRMIGfXcLUJ+RNBGCkM+iAGvzLeTkzi7H7ENWlZgFIKywoBWUqMn/9gsERuN0XsihB zILBsTf1lRn73OvM0cYUSSFep4bw/AoYaw/AXpoj17wZRUDPZz2qEVugfOiIhMXkPpz3KG8vZfjeC oO/tqJ//Q==; Received: from [45.249.212.189] (helo=dggrg03-dlp.huawei.com) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ctXWC-0006d5-QX for linux-arm-kernel@lists.infradead.org; Thu, 30 Mar 2017 10:41:30 +0000 Received: from 172.30.72.55 (EHLO DGGEML403-HUB.china.huawei.com) ([172.30.72.55]) by dggrg03-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id AKX60252; Thu, 30 Mar 2017 18:34:43 +0800 (CST) Received: from localhost.localdomain.localdomain (10.175.113.25) by DGGEML403-HUB.china.huawei.com (10.3.17.33) with Microsoft SMTP Server id 14.3.301.0; Thu, 30 Mar 2017 18:34:34 +0800 From: Xie XiuQi To: , , , , , , , , Subject: [PATCH v3 4/8] APEI: GHES: reserve a virtual page for SEI context Date: Thu, 30 Mar 2017 18:31:13 +0800 Message-ID: <1490869877-118713-14-git-send-email-xiexiuqi@huawei.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1490869877-118713-1-git-send-email-xiexiuqi@huawei.com> References: <1490869877-118713-1-git-send-email-xiexiuqi@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.113.25] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090203.58DCDF45.001B, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 8b3af72c762b4cafb45ff8ce09f8cf50 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170330_064130_138340_F329192B X-CRM114-Status: GOOD ( 15.19 ) 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: wuquanming@huawei.com, kvm@vger.kernel.org, xiexiuqi@huawei.com, linux-kernel@vger.kernel.org, gengdongjiu@huawei.com, wangxiongfeng2@huawei.com, linux-acpi@vger.kernel.org, zhengqiang10@huawei.com, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org 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 On arm64 platform, SEI may interrupt code which had interrupts masked. But SEI could be masked, so it's not treated as NMI, however SEA is treated as NMI. So, the memory area used to transfer hardware error information from BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer handler. In this patch, we add a virtual page for SEI context. Signed-off-by: Xie XiuQi --- drivers/acpi/apei/ghes.c | 98 +++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 045d101..b1f9b1f 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -108,26 +108,33 @@ /* * Because the memory area used to transfer hardware error information - * from BIOS to Linux can be determined only in NMI, IRQ or timer - * handler, but general ioremap can not be used in atomic context, so - * a special version of atomic ioremap is implemented for that. + * from BIOS to Linux can be determined only in NMI, SEI (ARM64), IRQ or + * timer handler, but general ioremap can not be used in atomic context, + * so a special version of atomic ioremap is implemented for that. */ /* - * Two virtual pages are used, one for IRQ/PROCESS context, the other for - * NMI context (optionally). + * 3 virtual pages are used, one for IRQ/PROCESS context, one for SEI + * (on ARM64 platform), and the other for NMI context (optionally). */ +#ifdef CONFIG_ACPI_APEI_SEI +#define GHES_IOREMAP_PAGES 3 +#define GHES_IOREMAP_SEI_PAGE(base) ((base) + PAGE_SIZE*2) +#else #define GHES_IOREMAP_PAGES 2 +#endif + #define GHES_IOREMAP_IRQ_PAGE(base) (base) #define GHES_IOREMAP_NMI_PAGE(base) ((base) + PAGE_SIZE) /* virtual memory area for atomic ioremap */ static struct vm_struct *ghes_ioremap_area; /* - * These 2 spinlock is used to prevent atomic ioremap virtual memory + * These 3 spinlock is used to prevent atomic ioremap virtual memory * area from being mapped simultaneously. */ static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi); +static DEFINE_SPINLOCK(ghes_ioremap_lock_sei); static DEFINE_SPINLOCK(ghes_ioremap_lock_irq); static struct gen_pool *ghes_estatus_pool; @@ -155,54 +162,55 @@ static void ghes_ioremap_exit(void) free_vm_area(ghes_ioremap_area); } -static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn) +static void __iomem *ghes_ioremap_pfn(u64 pfn) { - unsigned long vaddr; + unsigned long vaddr, flags = 0; phys_addr_t paddr; pgprot_t prot; - vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr); - - paddr = pfn << PAGE_SHIFT; - prot = arch_apei_get_mem_attribute(paddr); - ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot); - - return (void __iomem *)vaddr; -} - -static void __iomem *ghes_ioremap_pfn_irq(u64 pfn) -{ - unsigned long vaddr, paddr; - pgprot_t prot; - - vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr); + if (in_nmi()) { + raw_spin_lock(&ghes_ioremap_lock_nmi); + vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr); + } else if (this_cpu_read(sei_in_process)) { + spin_lock_irqsave(&ghes_ioremap_lock_sei, flags); + vaddr = (unsigned long)GHES_IOREMAP_SEI_PAGE(ghes_ioremap_area->addr); + } else { + spin_lock_irqsave(&ghes_ioremap_lock_irq, flags); + vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr); + } paddr = pfn << PAGE_SHIFT; prot = arch_apei_get_mem_attribute(paddr); - ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot); return (void __iomem *)vaddr; } -static void ghes_iounmap_nmi(void __iomem *vaddr_ptr) +static void ghes_iounmap(void __iomem *vaddr_ptr) { unsigned long vaddr = (unsigned long __force)vaddr_ptr; void *base = ghes_ioremap_area->addr; + unsigned long page, flags = 0; + + if (in_nmi()) { + page = (unsigned long)GHES_IOREMAP_NMI_PAGE(base); + } else if (this_cpu_read(sei_in_process)) { + page = (unsigned long)GHES_IOREMAP_SEI_PAGE(base); + } else { + page = (unsigned long)GHES_IOREMAP_IRQ_PAGE(base); + } - BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base)); + BUG_ON(vaddr != page); unmap_kernel_range_noflush(vaddr, PAGE_SIZE); arch_apei_flush_tlb_one(vaddr); -} - -static void ghes_iounmap_irq(void __iomem *vaddr_ptr) -{ - unsigned long vaddr = (unsigned long __force)vaddr_ptr; - void *base = ghes_ioremap_area->addr; - BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base)); - unmap_kernel_range_noflush(vaddr, PAGE_SIZE); - arch_apei_flush_tlb_one(vaddr); + if (in_nmi()) { + raw_spin_unlock(&ghes_ioremap_lock_nmi); + } else if (this_cpu_read(sei_in_process)) { + spin_unlock_irqrestore(&ghes_ioremap_lock_sei, flags); + } else { + spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags); + } } static int ghes_estatus_pool_init(void) @@ -327,20 +335,13 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, int from_phys) { void __iomem *vaddr; - unsigned long flags = 0; - int in_nmi = in_nmi(); u64 offset; u32 trunk; while (len > 0) { offset = paddr - (paddr & PAGE_MASK); - if (in_nmi) { - raw_spin_lock(&ghes_ioremap_lock_nmi); - vaddr = ghes_ioremap_pfn_nmi(paddr >> PAGE_SHIFT); - } else { - spin_lock_irqsave(&ghes_ioremap_lock_irq, flags); - vaddr = ghes_ioremap_pfn_irq(paddr >> PAGE_SHIFT); - } + vaddr = ghes_ioremap_pfn(paddr >> PAGE_SHIFT); + trunk = PAGE_SIZE - offset; trunk = min(trunk, len); if (from_phys) @@ -350,13 +351,8 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, len -= trunk; paddr += trunk; buffer += trunk; - if (in_nmi) { - ghes_iounmap_nmi(vaddr); - raw_spin_unlock(&ghes_ioremap_lock_nmi); - } else { - ghes_iounmap_irq(vaddr); - spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags); - } + + ghes_iounmap(vaddr); } }