diff options
| author | Harry Moulton <harry.moulton@arm.com> | 2026-04-16 13:29:14 +0000 |
|---|---|---|
| committer | Andrew Turner <andrew@FreeBSD.org> | 2026-04-16 14:22:24 +0000 |
| commit | 6f9e9eba984f5c8d8a022c0ec99f844a911687fe (patch) | |
| tree | aa2b5ff554ca2d402ff48874f3fd24fbf0d11557 | |
| parent | 8728e21bd694dbb813c149206c5c89290f9c32f5 (diff) | |
arm64: mte: handle synchronous tag check faults
The Memory Tagging Extension supports both Synchronous and Asynchronous
faults, called Tag Check Faults, which are configurable via
SCTLR_EL1.TCF0 for userspace and SCTLR_EL1.TCF for the kernel.
This commit adds support for handling synchronous tag check faults at
EL0 and EL1, although these are only enabled on a per-process basis in
userspace, kernel space does not enable tag check faults. A TCF in the
kernel will cause a kernel panic like any other virtual memory fault,
and a TCF in userspace will result in a SIGSEGV
Reviewed by: kib
Sponsored by: Arm Ltd
Signed-off-by: Harry Moulton <harry.moulton@arm.com>
Differential Revision: https://reviews.freebsd.org/D55947
| -rw-r--r-- | sys/arm64/arm64/trap.c | 22 | ||||
| -rw-r--r-- | sys/sys/signal.h | 2 |
2 files changed, 24 insertions, 0 deletions
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index ad461aa1bffc..1178817108e5 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -94,6 +94,7 @@ typedef void (abort_handler)(struct thread *, struct trapframe *, uint64_t, static abort_handler align_abort; static abort_handler data_abort; static abort_handler external_abort; +static abort_handler tag_check_abort; static abort_handler *abort_handlers[] = { [ISS_DATA_DFSC_TF_L0] = data_abort, @@ -106,6 +107,7 @@ static abort_handler *abort_handlers[] = { [ISS_DATA_DFSC_PF_L1] = data_abort, [ISS_DATA_DFSC_PF_L2] = data_abort, [ISS_DATA_DFSC_PF_L3] = data_abort, + [ISS_DATA_DFSC_TAG] = tag_check_abort, [ISS_DATA_DFSC_ALIGN] = align_abort, [ISS_DATA_DFSC_EXT] = external_abort, [ISS_DATA_DFSC_EXT_L0] = external_abort, @@ -250,6 +252,26 @@ external_abort(struct thread *td, struct trapframe *frame, uint64_t esr, panic("Unhandled external data abort"); } +static void +tag_check_abort(struct thread *td, struct trapframe *frame, uint64_t esr, + uint64_t far, int lower) +{ + /* + * A Tag Check Fault should be handled as a SIGSEGV if it occurs + * at EL0 and a kernel panic if at EL1. + */ + if (!lower) { + print_registers(frame); + print_gp_register("far", far); + printf(" esr: 0x%.16lx\n", esr); + panic("Tag Check Fault"); + } + + call_trapsignal(td, SIGSEGV, SEGV_MTESERR, (void *)far, + ESR_ELx_EXCEPTION(frame->tf_esr)); + userret(td, frame); +} + /* * It is unsafe to access the stack canary value stored in "td" until * kernel map translation faults are handled, see the pmap_klookup() call below. diff --git a/sys/sys/signal.h b/sys/sys/signal.h index c0b65c0c9ef0..863b981c2b7a 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -307,6 +307,8 @@ struct __siginfo32 { #define SEGV_ACCERR 2 /* Invalid permissions for mapped */ /* object. */ #define SEGV_PKUERR 100 /* x86: PKU violation */ +#define SEGV_MTEAERR 100 /* arm64: Asynchronous Arm MTE error */ +#define SEGV_MTESERR 101 /* arm64: Synchronous Arm MTE error */ /* codes for SIGFPE */ #define FPE_INTOVF 1 /* Integer overflow. */ |
