From patchwork Thu Feb 22 14:00:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 10235641 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 1693F60209 for ; Thu, 22 Feb 2018 14:08:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E4A628B9F for ; Thu, 22 Feb 2018 14:08:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 030E428BB5; Thu, 22 Feb 2018 14:08:21 +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=ham 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 7BF9B28B9F for ; Thu, 22 Feb 2018 14:08:20 +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=xEDm2GBjD6Qjj0K0arhFi/RH7hasuRyDUIzipm6GIn8=; b=MwpxrH/z9FVjpbqk96xf2me9qr jGoF5GYDUgOFiWgCdKPMmXJdPZxSADVH8HgCnhSbIAU966S8bAASz0nzj11oxI0EhYQU6o2F0gGHS zCDIrb7Y7c1JEz4ztpBUOB74/uGi4FrUBwf/4bMizq+GfDJ6xNUNuMJ2eS1PAFWQAPSGdU1t/aE+g PkCT2YWsfH5CaZCk8Rr7c4eqGEGpbUhzJAgWX/2JXIHTJlSWReJpGWQr3K4pfggVjt0NymbBeDOjG 8cklbRcfIRpOJzxfqPcH2rA3Rios9X+f8QYk2AljxxzT/FyZa91oZUDUZ/pyOjs5vhXGBwGU6Zx2g Xt4lGe7g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eorXZ-0006W9-0O; Thu, 22 Feb 2018 14:08:05 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eorRA-0001E3-5f for linux-arm-kernel@lists.infradead.org; Thu, 22 Feb 2018 14:01:55 +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 E7C4D1682; Thu, 22 Feb 2018 06:01:01 -0800 (PST) Received: from edgewater-inn.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B835E3F578; Thu, 22 Feb 2018 06:01:01 -0800 (PST) Received: by edgewater-inn.cambridge.arm.com (Postfix, from userid 1000) id 56D841AE541A; Thu, 22 Feb 2018 14:01:01 +0000 (GMT) From: Will Deacon To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 6/9] arm64: mm: Rework unhandled user pagefaults to call arm64_force_sig_info Date: Thu, 22 Feb 2018 14:00:54 +0000 Message-Id: <1519308057-4953-7-git-send-email-will.deacon@arm.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1519308057-4953-1-git-send-email-will.deacon@arm.com> References: <1519308057-4953-1-git-send-email-will.deacon@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180222_060128_679668_5620FBE6 X-CRM114-Status: GOOD ( 14.62 ) 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, Will Deacon , dave.martin@arm.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 Reporting unhandled user pagefaults via arm64_force_sig_info means that __do_user_fault can be drastically simplified, since it no longer has to worry about printing the fault information and can consequently just take the siginfo as a parameter. Signed-off-by: Will Deacon --- arch/arm64/mm/fault.c | 87 +++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index fd5928afd9cd..49dfb08a6c4d 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -289,58 +290,31 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, do_exit(SIGKILL); } -static void __do_user_fault(struct task_struct *tsk, unsigned long addr, - unsigned int esr, unsigned int sig, int code, - struct pt_regs *regs, int fault) +static void __do_user_fault(struct siginfo *info, unsigned int esr) { - struct siginfo si; - const struct fault_info *inf; - unsigned int lsb = 0; - - if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) { - inf = esr_to_fault_info(esr); - pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x", - tsk->comm, task_pid_nr(tsk), inf->name, sig, - addr, esr); - print_vma_addr(KERN_CONT ", in ", regs->pc); - pr_cont("\n"); - __show_regs(regs); - } - - tsk->thread.fault_address = addr; - tsk->thread.fault_code = esr; - si.si_signo = sig; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void __user *)addr; - /* - * Either small page or large page may be poisoned. - * In other words, VM_FAULT_HWPOISON_LARGE and - * VM_FAULT_HWPOISON are mutually exclusive. - */ - if (fault & VM_FAULT_HWPOISON_LARGE) - lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); - else if (fault & VM_FAULT_HWPOISON) - lsb = PAGE_SHIFT; - si.si_addr_lsb = lsb; - - force_sig_info(sig, &si, tsk); + current->thread.fault_address = (unsigned long)info->si_addr; + current->thread.fault_code = esr; + arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current); } static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - struct task_struct *tsk = current; - const struct fault_info *inf; - /* * If we are in kernel mode at this point, we have no context to * handle this fault with. */ if (user_mode(regs)) { - inf = esr_to_fault_info(esr); - __do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs, 0); - } else + const struct fault_info *inf = esr_to_fault_info(esr); + struct siginfo si = { + .si_signo = inf->sig, + .si_code = inf->code, + .si_addr = (void __user *)addr, + }; + + __do_user_fault(&si, esr); + } else { __do_kernel_fault(addr, esr, regs); + } } #define VM_FAULT_BADMAP 0x010000 @@ -393,7 +367,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, { struct task_struct *tsk; struct mm_struct *mm; - int fault, sig, code, major = 0; + struct siginfo si; + int fault, major = 0; unsigned long vm_flags = VM_READ | VM_WRITE; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; @@ -525,27 +500,37 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, return 0; } + clear_siginfo(&si); + si.si_addr = (void __user *)addr; + if (fault & VM_FAULT_SIGBUS) { /* * We had some memory, but were unable to successfully fix up * this page fault. */ - sig = SIGBUS; - code = BUS_ADRERR; - } else if (fault & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) { - sig = SIGBUS; - code = BUS_MCEERR_AR; + si.si_signo = SIGBUS; + si.si_code = BUS_ADRERR; + } else if (fault & VM_FAULT_HWPOISON_LARGE) { + unsigned int hindex = VM_FAULT_GET_HINDEX(fault); + + si.si_signo = SIGBUS; + si.si_code = BUS_MCEERR_AR; + si.si_addr_lsb = hstate_index_to_shift(hindex); + } else if (fault & VM_FAULT_HWPOISON) { + si.si_signo = SIGBUS; + si.si_code = BUS_MCEERR_AR; + si.si_addr_lsb = PAGE_SHIFT; } else { /* * Something tried to access memory that isn't in our memory * map. */ - sig = SIGSEGV; - code = fault == VM_FAULT_BADACCESS ? - SEGV_ACCERR : SEGV_MAPERR; + si.si_signo = SIGSEGV; + si.si_code = fault == VM_FAULT_BADACCESS ? + SEGV_ACCERR : SEGV_MAPERR; } - __do_user_fault(tsk, addr, esr, sig, code, regs, fault); + __do_user_fault(&si, esr); return 0; no_context: