Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp25361ybt; Tue, 30 Jun 2020 14:03:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwuyC3c5bEXzAQvFHbt72PCm2X481P07Xt6bMC2Hr9IMelxLuOGTMS9mrzkQKyoYvgJ6Y7i X-Received: by 2002:a50:ef10:: with SMTP id m16mr24251951eds.206.1593550607182; Tue, 30 Jun 2020 13:56:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1593550607; cv=none; d=google.com; s=arc-20160816; b=jij3HuY2WKjV5zeGc9n/4XIMfVD8bKSqxD0oZPEQYF1V9wzOrSfngGrCUKO9Z5n4V7 icRkHfNO7q8uOvM5YTqjPxk6XHIMCe/89xLZ/X6rkNSaUxE0MO+1GFTUOuRx5aVSimgy Cl7mD49hyirllmWui4nOpo1a3jrAh05WwIB3Os9FCuJxrP+yVmFDU1EaAmheg5zpC6Cm dqFDrqDIu4EgjVQm7N3FrfKhibP1wuBXILPQnvdey81ByPydsHUGTdab02BneNM4MY9X HzZ+3w2tTzUBeSCNxRNfrULLOqkUDGwb3EH4Bk/PHZwOQLB9I4qGjPQqp4l6ZT41vDPF RT+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=c7zcLo41towzcTLSSQPsFx2WCQsHcZ0KtoumYzuFU2M=; b=XGYjwK3gvFvwMuZla9AY4VfhmfbBlGBo51pJeWLJiFEW+k6jj8dudNk85jL5pkd13Y lpsB3pEkhO8xi7HWdaNQTZ8JBBgnFPIpZG8+N89a7g9TmI8jIv9yvQa726QUhl8HS63Y swnCFto+OUGLZFwFivdqnoB7sL66UNE0X5g49VRxR6yS2ScYvOqlsD9FKMZQEdeMsLpz 4hNedQdfuMPAav022DRpsP5nOgsSSDyrAX9sgbsVt9Cste2UbDki8yB4EP6lWuLSopg6 eVQTq04DiD+vxacB6alQh9Z0wQJhXdgw24wV0GjVErkxa8f2yJALNaVizF5g525TmnSG NKgQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j16si2366026eds.309.2020.06.30.13.56.24; Tue, 30 Jun 2020 13:56:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728440AbgF3Tsr (ORCPT + 99 others); Tue, 30 Jun 2020 15:48:47 -0400 Received: from foss.arm.com ([217.140.110.172]:32894 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728428AbgF3Tso (ORCPT ); Tue, 30 Jun 2020 15:48:44 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6EC6A1045; Tue, 30 Jun 2020 12:48:44 -0700 (PDT) Received: from seattle-bionic.arm.com.Home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8087C3F73C; Tue, 30 Jun 2020 12:48:43 -0700 (PDT) From: Oliver Swede To: Will Deacon , Catalin Marinas Cc: Robin Murphy , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 01/14] arm64: Allow passing fault address to fixup handlers Date: Tue, 30 Jun 2020 19:48:09 +0000 Message-Id: <20200630194822.1082-2-oli.swede@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200630194822.1082-1-oli.swede@arm.com> References: <20200630194822.1082-1-oli.swede@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sam Tebbs Extend fixup_exception() to optionally place the faulting address in a register when returning to a fixup handler. Since A64 instructions must be 4-byte-aligned, we can mimic the IA-64 implementation and encode a flag in the lower bits of the offset field to indicate handlers which expect an address. This will allow us to use more efficient offset addressing modes in usercopy routines, rather than updating the base register on every access just for the sake of inferring where a fault occurred in order to compute the return value upon failure. The choice of x15 is somewhat arbitrary, but with the consideration that as the highest-numbered temporary register with no possible 'special' role in the ABI, it is most likely not used by hand-written assembly code, and thus a minimally-invasive option for imported routines. Signed-off-by: Sam Tebbs [ rm: split into separate patch, use UL(), expand commit message ] Signed-off-by: Robin Murphy Signed-off-by: Oliver Swede --- arch/arm64/include/asm/assembler.h | 9 +++++++++ arch/arm64/include/asm/extable.h | 10 +++++++++- arch/arm64/mm/extable.c | 13 +++++++++---- arch/arm64/mm/fault.c | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 54d181177656..438382a277c8 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,14 @@ alternative_endif .popsection .endm +/* + * Emit an entry into the exception table. + * The fixup handler will receive the faulting address in x15 + */ + .macro _asm_extable_faultaddr, from, to + _asm_extable \from, \to + FIXUP_WITH_ADDR + .endm + #define USER(l, x...) \ 9999: x; \ _asm_extable 9999b, l diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h index 56a4f68b262e..4c4955f2bb44 100644 --- a/arch/arm64/include/asm/extable.h +++ b/arch/arm64/include/asm/extable.h @@ -2,6 +2,12 @@ #ifndef __ASM_EXTABLE_H #define __ASM_EXTABLE_H +#include + +#define FIXUP_WITH_ADDR UL(1) + +#ifndef __ASSEMBLY__ + /* * The exception table consists of pairs of relative offsets: the first * is the relative offset to an instruction that is allowed to fault, @@ -22,5 +28,7 @@ struct exception_table_entry #define ARCH_HAS_RELATIVE_EXTABLE -extern int fixup_exception(struct pt_regs *regs); +extern int fixup_exception(struct pt_regs *regs, unsigned long addr); + +#endif #endif diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c index 81e694af5f8c..e6578c2814b5 100644 --- a/arch/arm64/mm/extable.c +++ b/arch/arm64/mm/extable.c @@ -6,13 +6,18 @@ #include #include -int fixup_exception(struct pt_regs *regs) +int fixup_exception(struct pt_regs *regs, unsigned long addr) { const struct exception_table_entry *fixup; fixup = search_exception_tables(instruction_pointer(regs)); - if (fixup) - regs->pc = (unsigned long)&fixup->fixup + fixup->fixup; - + if (fixup) { + unsigned long offset = fixup->fixup; + if (offset & FIXUP_WITH_ADDR) { + regs->regs[15] = addr; + offset &= ~FIXUP_WITH_ADDR; + } + regs->pc = (unsigned long)&fixup->fixup + offset; + } return fixup != NULL; } diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 8afb238ff335..f80e299dc91b 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -303,7 +303,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, * Are we prepared to handle this kernel fault? * We are almost certainly not prepared to handle instruction faults. */ - if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) + if (!is_el1_instruction_abort(esr) && fixup_exception(regs, addr)) return; if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs), -- 2.17.1