
commit 61d64a376ea80f9097e7ea599bcd68671b836dc6 upstream. In general, exceptions taken from EL1 need to be handled separately from exceptions taken from EL0, as the logic to handle the two cases can be significantly divergent, and exceptions taken from EL1 typically have more stringent requirements on locking and instrumentation. Subsequent patches will rework the way EL1 UNDEFs are handled in order to address longstanding soundness issues with instrumentation and RCU. In preparation for that rework, this patch splits the existing do_undefinstr() handler into separate do_el0_undef() and do_el1_undef() handlers. Prior to this patch, do_undefinstr() was marked with NOKPROBE_SYMBOL(), preventing instrumentation via kprobes. However, do_undefinstr() invokes other code which can be instrumented, and: * For UNDEFINED exceptions taken from EL0, there is no risk of recursion within kprobes. Therefore it is safe for do_el0_undef to be instrumented with kprobes, and it does not need to be marked with NOKPROBE_SYMBOL(). * For UNDEFINED exceptions taken from EL1, either: (a) The exception is has been taken when manipulating SSBS; these cases are limited and do not occur within code that can be invoked recursively via kprobes. Hence, in these cases instrumentation with kprobes is benign. (b) The exception has been taken for an unknown reason, as other than manipulating SSBS we do not expect to take UNDEFINED exceptions from EL1. Any handling of these exception is best-effort. ... and in either case, marking do_el1_undef() with NOKPROBE_SYMBOL() isn't sufficient to prevent recursion via kprobes as functions it calls (including die()) are instrumentable via kprobes. Hence, it's not worthwhile to mark do_el1_undef() with NOKPROBE_SYMBOL(). The same applies to do_el1_bti() and do_el1_fpac(), so their NOKPROBE_SYMBOL() annotations are also removed. Aside from the new instrumentability, there should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: James Morse <james.morse@arm.com> Cc: Joey Gouly <joey.gouly@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20221019144123.612388-3-mark.rutland@arm.com Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
55 lines
1.9 KiB
C
55 lines
1.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Based on arch/arm/include/asm/exception.h
|
|
*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
*/
|
|
#ifndef __ASM_EXCEPTION_H
|
|
#define __ASM_EXCEPTION_H
|
|
|
|
#include <asm/esr.h>
|
|
#include <asm/ptrace.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#define __exception_irq_entry __irq_entry
|
|
|
|
static inline u32 disr_to_esr(u64 disr)
|
|
{
|
|
unsigned int esr = ESR_ELx_EC_SERROR << ESR_ELx_EC_SHIFT;
|
|
|
|
if ((disr & DISR_EL1_IDS) == 0)
|
|
esr |= (disr & DISR_EL1_ESR_MASK);
|
|
else
|
|
esr |= (disr & ESR_ELx_ISS_MASK);
|
|
|
|
return esr;
|
|
}
|
|
|
|
asmlinkage void noinstr enter_el1_irq_or_nmi(struct pt_regs *regs);
|
|
asmlinkage void noinstr exit_el1_irq_or_nmi(struct pt_regs *regs);
|
|
asmlinkage void enter_from_user_mode(void);
|
|
asmlinkage void exit_to_user_mode(void);
|
|
void arm64_enter_nmi(struct pt_regs *regs);
|
|
void arm64_exit_nmi(struct pt_regs *regs);
|
|
void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
|
|
void do_el0_undef(struct pt_regs *regs, unsigned long esr);
|
|
void do_el1_undef(struct pt_regs *regs, unsigned long esr);
|
|
void do_el0_bti(struct pt_regs *regs);
|
|
void do_el1_bti(struct pt_regs *regs, unsigned long esr);
|
|
asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
|
|
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
|
|
struct pt_regs *regs);
|
|
void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs);
|
|
void do_sve_acc(unsigned int esr, struct pt_regs *regs);
|
|
void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs);
|
|
void do_el0_sys(unsigned long esr, struct pt_regs *regs);
|
|
void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
|
|
void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr);
|
|
void do_el0_cp15(unsigned long esr, struct pt_regs *regs);
|
|
void do_el0_svc(struct pt_regs *regs);
|
|
void do_el0_svc_compat(struct pt_regs *regs);
|
|
void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
|
|
void do_el1_fpac(struct pt_regs *regs, unsigned long esr);
|
|
#endif /* __ASM_EXCEPTION_H */
|