From patchwork Fri Mar 24 14:46:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Berger X-Patchwork-Id: 9643007 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 693E960327 for ; Fri, 24 Mar 2017 14:48:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5BC2F205FD for ; Fri, 24 Mar 2017 14:48:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4FAF722376; Fri, 24 Mar 2017 14:48:58 +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_ADSP_CUSTOM_MED, DKIM_SIGNED,DKIM_VALID,FREEMAIL_FROM autolearn=ham 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 C1A5E205FD for ; Fri, 24 Mar 2017 14:48:57 +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=cdd4k78h0vGEKwYcVYFwXnWP8+yofk8QGh/h2yikV84=; b=ffAta+2/1VwfDkT5d9OryUxnrJ So84HcsN3e0NzomN4p2OfADukKNAEU2lO0DRA8lHSSrIz+4ICEFmEtmu6W/+2mOefeEk2fAENuh0y 9ca5PdBhYNy3kqd64ANF7ZalBWM01469vLItkGTXkrfkBgPRnB1PhfTMkBEOUiO2SwdE7S2QstMhI FufD0cyFpZJ5p7+Z05C9mj/X4Pgn1VuRfqFs5J4Bv7GUx+8L/RkdlJ0caBzBA3RHarQDurnH6xfau aokWLYkP96pHdYVco6AZYQicAdKWceRJnpyH7pAatob2ZJnixRF7iQWfF4i9IYRHuWE6UjNUSdGA0 q1Y180Bg==; 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 1crQWP-0002qk-DT; Fri, 24 Mar 2017 14:48:57 +0000 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1crQVf-00020F-JG for linux-arm-kernel@lists.infradead.org; Fri, 24 Mar 2017 14:48:13 +0000 Received: by mail-wm0-x244.google.com with SMTP id n11so1065168wma.0 for ; Fri, 24 Mar 2017 07:47:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Hz/snKrsN7FbrqbDJJ60dfHJlwREAio/oRkAA0popus=; b=qpRp5GXyi8DB5torQ7HTsY56o8RGdftB3ldkg85SjSzbP2XjR3wV5y/FVzFnI63Ftn Tu7bf7GJ6GNYBlLUo86aKjy7H5NjEfut/eLGjkD7zieN+4CdFPd6QJUmzvClPzYlmEeP CkuacKWJr+W3pLBtOYUBwnZLPoHaBklM1+LZ2hV1AeVkMnF3PNwhBcGMrwk6gWzN387V 9hJWdUH5X/szDpbU2ERb6G1YSjN4GyUFF8gc0hx3mPS3DuZdozxjs/xtO38T41BBiqTR vdIKM13OxEHeI3vYv6VMkTRETEvtIJzhigheSPJXOg92P1cyhIyuCo9LgZm/ajYSTGoQ pzbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Hz/snKrsN7FbrqbDJJ60dfHJlwREAio/oRkAA0popus=; b=t+/wIek3F2jtvTKe7NubMVSDsRP04vK3qY1oF/Y39IRU0lDFpm6SKs9v/E/GUVzEqY 05iaAAKpb16hr5VW+fNeFiEqntWH1lmSqzjfeNm24NV1x15+POc32pSz5zaWIvXeSQ6c jW6ku+qTmWqMj6P6NANwoqKH/6TTh7TN8Wyz543ExujLVxXRd0M4D8k9FxfPpS8lUfXc prF4NksgKLTI67zL5hue5fLDvgWZgRwKYYxjXbV7nFVy/6nxPyRd6VrUVFvueTppoQYz 578Q0EHoYKwEl61fG+J84gE5fwRrRt5HR+A59n6GJkGe2lo36WZTUFUilAbn/VXZq6iu FqRw== X-Gm-Message-State: AFeK/H1AvVxe+3UunbQu4CTpSOoMFdBIvkA8oLMuC052DgiUzGtChju3G0wb8gosQQ/7jw== X-Received: by 10.28.46.198 with SMTP id u189mr3335544wmu.54.1490366869947; Fri, 24 Mar 2017 07:47:49 -0700 (PDT) Received: from stb-bld-02.irv.broadcom.com ([192.19.255.250]) by smtp.gmail.com with ESMTPSA id k32sm3154947wre.18.2017.03.24.07.47.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 24 Mar 2017 07:47:49 -0700 (PDT) From: Doug Berger To: catalin.marinas@arm.com Subject: [PATCH 3/9] arm64: mm: install SError abort handler Date: Fri, 24 Mar 2017 07:46:26 -0700 Message-Id: <20170324144632.5896-4-opendmb@gmail.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170324144632.5896-1-opendmb@gmail.com> References: <20170324144632.5896-1-opendmb@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170324_074811_809816_E51C7812 X-CRM114-Status: GOOD ( 15.27 ) 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: mark.rutland@arm.com, wangkefeng.wang@huawei.com, linus.walleij@linaro.org, will.deacon@arm.com, mingo@kernel.org, panand@redhat.com, f.fainelli@gmail.com, jonathanh@nvidia.com, bgolaszewski@baylibre.com, bcm-kernel-feedback-list@broadcom.com, shijie.huang@arm.com, opendmb@gmail.com, treding@nvidia.com, devicetree@vger.kernel.org, vladimir.murzin@arm.com, cmetcalf@mellanox.com, suzuki.poulose@arm.com, andre.przywara@arm.com, robh+dt@kernel.org, gregory.0xf0@gmail.com, sandeepa.s.prabhu@gmail.com, horms+renesas@verge.net.au, linux-arm-kernel@lists.infradead.org, mirza.krak@gmail.com, linux-kernel@vger.kernel.org, james.morse@arm.com, olof@lixom.net, computersforpeace@gmail.com 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 This commit adds support for minimal handling of SError aborts and allows them to be hooked by a driver or other part of the kernel to install a custom SError abort handler. The hook function returns the previously registered handler so that handlers may be chained if desired. The handler should return the value 0 if the error has been handled, otherwise the handler should either call the next handler in the chain or return a non-zero value. Since the Instruction Specific Syndrome value for SError aborts is implementation specific the registerred handlers must implement their own parsing of the syndrome. Signed-off-by: Doug Berger --- arch/arm64/include/asm/system_misc.h | 2 ++ arch/arm64/kernel/entry.S | 69 ++++++++++++++++++++++++++++++++---- arch/arm64/mm/fault.c | 31 ++++++++++++++++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index e05f5b8c7c1c..60ac784ff4e6 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -41,6 +41,8 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), int sig, int code, const char *name); +void *hook_serror_handler(int (*fn)(unsigned long, unsigned int, + struct pt_regs *)); struct mm_struct; extern void show_pte(struct mm_struct *mm, unsigned long addr); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 43512d4d7df2..d043d66b390d 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -323,18 +323,18 @@ ENTRY(vectors) ventry el1_sync // Synchronous EL1h ventry el1_irq // IRQ EL1h ventry el1_fiq_invalid // FIQ EL1h - ventry el1_error_invalid // Error EL1h + ventry el1_error // Error EL1h ventry el0_sync // Synchronous 64-bit EL0 ventry el0_irq // IRQ 64-bit EL0 ventry el0_fiq_invalid // FIQ 64-bit EL0 - ventry el0_error_invalid // Error 64-bit EL0 + ventry el0_error // Error 64-bit EL0 #ifdef CONFIG_COMPAT ventry el0_sync_compat // Synchronous 32-bit EL0 ventry el0_irq_compat // IRQ 32-bit EL0 ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 - ventry el0_error_invalid_compat // Error 32-bit EL0 + ventry el0_error_compat // Error 32-bit EL0 #else ventry el0_sync_invalid // Synchronous 32-bit EL0 ventry el0_irq_invalid // IRQ 32-bit EL0 @@ -374,10 +374,6 @@ ENDPROC(el0_error_invalid) el0_fiq_invalid_compat: inv_entry 0, BAD_FIQ, 32 ENDPROC(el0_fiq_invalid_compat) - -el0_error_invalid_compat: - inv_entry 0, BAD_ERROR, 32 -ENDPROC(el0_error_invalid_compat) #endif el1_sync_invalid: @@ -508,6 +504,34 @@ el1_preempt: ret x24 #endif + .align 6 +el1_error: + kernel_entry 1 + mrs x1, esr_el1 // read the syndrome register + lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class + cmp x24, #ESR_ELx_EC_SERROR // SError exception in EL1 + b.ne el1_error_inv +el1_serr: + mrs x0, far_el1 + enable_dbg + // re-enable interrupts if they were enabled in the aborted context + tbnz x23, #7, 1f // PSR_I_BIT + enable_irq +1: + mov x2, sp // struct pt_regs + bl do_serr_abort + + // disable interrupts before pulling preserved data off the stack + disable_irq + kernel_exit 1 +el1_error_inv: + enable_dbg + mov x0, sp + mov x2, x1 + mov x1, #BAD_ERROR + b bad_mode +ENDPROC(el1_error) + /* * EL0 mode handlers. */ @@ -584,6 +608,11 @@ el0_svc_compat: el0_irq_compat: kernel_entry 0, 32 b el0_irq_naked + + .align 6 +el0_error_compat: + kernel_entry 0, 32 + b el0_error_naked #endif el0_da: @@ -705,6 +734,32 @@ el0_irq_naked: b ret_to_user ENDPROC(el0_irq) + .align 6 +el0_error: + kernel_entry 0 +el0_error_naked: + mrs x25, esr_el1 // read the syndrome register + lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class + cmp x24, #ESR_ELx_EC_SERROR // SError exception in EL0 + b.ne el0_error_inv +el0_serr: + mrs x26, far_el1 + // enable interrupts before calling the main handler + enable_dbg_and_irq + ct_user_exit + bic x0, x26, #(0xff << 56) + mov x1, x25 + mov x2, sp + bl do_serr_abort + b ret_to_user +el0_error_inv: + enable_dbg + mov x0, sp + mov x1, #BAD_ERROR + mov x2, x25 + b bad_mode +ENDPROC(el0_error) + /* * Register switch for AArch64. The callee-saved registers need to be saved * and restored. On entry: diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 43319ed58a47..577fecea7c7d 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -705,3 +705,34 @@ int cpu_enable_pan(void *__unused) return 0; } #endif /* CONFIG_ARM64_PAN */ + +static int (*serror_handler)(unsigned long, unsigned int, + struct pt_regs *) __ro_after_init; + +void *__init hook_serror_handler(int (*fn)(unsigned long, unsigned int, + struct pt_regs *)) +{ + void *ret = serror_handler; + + serror_handler = fn; + return ret; +} + +asmlinkage void __exception do_serr_abort(unsigned long addr, unsigned int esr, + struct pt_regs *regs) +{ + struct siginfo info; + + if (serror_handler) + if (!serror_handler(addr, esr, regs)) + return; + + pr_alert("Unhandled SError: (0x%08x) at 0x%016lx\n", esr, addr); + __show_regs(regs); + + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_ILLOPC; + info.si_addr = (void __user *)addr; + arm64_notify_die("", regs, &info, esr); +}