Page MenuHomeFreeBSD

D55959.id173929.diff
No OneTemporary

D55959.id173929.diff

diff --git a/sys/arm64/arm64/mte.c b/sys/arm64/arm64/mte.c
--- a/sys/arm64/arm64/mte.c
+++ b/sys/arm64/arm64/mte.c
@@ -246,6 +246,38 @@
dstpage->md.pv_flags |= PV_MTE_TAGGED;
}
+bool
+mte_check_async(struct thread *td, struct trapframe *frame, bool syscall)
+{
+ ksiginfo_t ksi;
+
+ if (!MTE_HAS_TAG_CHECK)
+ return (false);
+
+ if ((mte_flags & MTE_HAS_ASYNC) == 0)
+ return (false);
+
+ if (atomic_testandclear_32(&td->td_md.md_flags,
+ MD_FLAG_MTE_ASYNC_FAULT_SHIFT)) {
+ /*
+ * If we are in a syscall adjust elr so the faulting
+ * instruction is the svc that entered the kernel.
+ */
+ if (syscall)
+ frame->tf_elr -= 4;
+
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGSEGV;
+ ksi.ksi_code = SEGV_MTEAERR;
+ ksi.ksi_addr = 0;
+ ksi.ksi_trapno = ESR_ELx_EXCEPTION(frame->tf_esr);
+ trapsignal(td, &ksi);
+ return (true);
+ }
+
+ return (false);
+}
+
void
mte_fork(struct thread *new_td, struct thread *orig_td)
{
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -88,7 +88,7 @@
u_long cnt_efirt_faults;
int print_efirt_faults;
-typedef void (abort_handler)(struct thread *, struct trapframe *, uint64_t,
+typedef bool (abort_handler)(struct thread *, struct trapframe *, uint64_t,
uint64_t, int);
static abort_handler align_abort;
@@ -198,20 +198,25 @@
static bool
svc_handler(struct thread *td, struct trapframe *frame)
{
+ /* TODO: This could cause issues for sigreturn? */
+ if (mte_check_async(td, frame, true)) {
+ userret(td, frame);
+ return (true);
+ }
if ((frame->tf_esr & ESR_ELx_ISS_MASK) == 0) {
syscallenter(td);
syscallret(td);
/* Skip userret as syscallret already called it */
return (true);
- } else {
- call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr,
- ESR_ELx_EXCEPTION(frame->tf_esr));
- return (false);
}
+
+ call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr,
+ ESR_ELx_EXCEPTION(frame->tf_esr));
+ return (false);
}
-static void
+static bool
align_abort(struct thread *td, struct trapframe *frame, uint64_t esr,
uint64_t far, int lower)
{
@@ -224,17 +229,18 @@
call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr,
ESR_ELx_EXCEPTION(frame->tf_esr));
+ return (true);
}
-static void
+static bool
external_abort(struct thread *td, struct trapframe *frame, uint64_t esr,
uint64_t far, int lower)
{
if (lower) {
call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)far,
ESR_ELx_EXCEPTION(frame->tf_esr));
- return;
+ return (true);
}
/*
@@ -243,7 +249,7 @@
*/
if (test_bs_fault((void *)frame->tf_elr)) {
frame->tf_elr = (uint64_t)generic_bs_fault;
- return;
+ return (false);
}
print_registers(frame);
@@ -252,7 +258,7 @@
panic("Unhandled external data abort");
}
-static void
+static bool
tag_check_abort(struct thread *td, struct trapframe *frame, uint64_t esr,
uint64_t far, int lower)
{
@@ -269,7 +275,7 @@
call_trapsignal(td, SIGSEGV, SEGV_MTESERR, (void *)far,
ESR_ELx_EXCEPTION(frame->tf_esr));
- userret(td, frame);
+ return (true);
}
/*
@@ -278,7 +284,7 @@
* Thus, stack-smashing detection with per-thread canaries must be disabled in
* this function.
*/
-static void NO_PERTHREAD_SSP
+static bool NO_PERTHREAD_SSP
data_abort(struct thread *td, struct trapframe *frame, uint64_t esr,
uint64_t far, int lower)
{
@@ -301,7 +307,7 @@
#ifdef KDB
if (kdb_active) {
kdb_reenter();
- return;
+ return (false);
}
#endif
@@ -334,7 +340,7 @@
case ISS_DATA_DFSC_TF_L2:
case ISS_DATA_DFSC_TF_L3:
if (pmap_klookup(far, NULL))
- return;
+ return (false);
break;
}
}
@@ -365,7 +371,7 @@
*/
if ((lower || map == kernel_map || pcb->pcb_onfault != 0) &&
pmap_fault(map->pmap, esr, fault_va) == KERN_SUCCESS)
- return;
+ return (false);
#ifdef INVARIANTS
if (td->td_md.md_spinlock_count != 0) {
@@ -411,12 +417,13 @@
if (lower) {
call_trapsignal(td, sig, ucode, (void *)far,
ESR_ELx_EXCEPTION(esr));
+ return (true);
} else {
bad_far:
if (td->td_intr_nesting_level == 0 &&
pcb->pcb_onfault != 0) {
frame->tf_elr = pcb->pcb_onfault;
- return;
+ return (false);
}
printf("Fatal data abort:\n");
@@ -431,13 +438,14 @@
frame);
kdb_why = KDB_WHY_UNSET;
if (handled)
- return;
+ return (false);
}
#endif
panic("vm_fault failed: 0x%lx error %d",
frame->tf_elr, error);
}
}
+ return (false);
}
static void
@@ -691,7 +699,7 @@
uint32_t exception;
uint64_t esr, far;
int dfsc;
- bool skip_userret;
+ bool has_sig, skip_userret;
/* Check we have a sane environment when entering from userland */
KASSERT((uintptr_t)get_pcpu() >= VM_MIN_KERNEL_ADDRESS,
@@ -720,6 +728,7 @@
__func__, exception, frame->tf_elr, esr);
skip_userret = false;
+ has_sig = false;
switch (exception) {
case EXCP_FP_SIMD:
#ifdef VFP
@@ -731,52 +740,58 @@
case EXCP_TRAP_FP:
#ifdef VFP
fpe_trap(td, (void *)frame->tf_elr, esr);
+ has_sig = true;
#else
panic("VFP exception in userland");
#endif
break;
case EXCP_SVE:
/* Returns true if this thread can use SVE */
- if (!sve_restore_state(td))
+ if (!sve_restore_state(td)) {
call_trapsignal(td, SIGILL, ILL_ILLTRP,
(void *)frame->tf_elr, exception);
+ has_sig = true;
+ }
break;
case EXCP_SVC32:
case EXCP_SVC64:
skip_userret = svc_handler(td, frame);
+ has_sig = true;
break;
case EXCP_INSN_ABORT_L:
case EXCP_DATA_ABORT_L:
case EXCP_DATA_ABORT:
dfsc = esr & ISS_DATA_DFSC_MASK;
if (dfsc < nitems(abort_handlers) &&
- abort_handlers[dfsc] != NULL)
- abort_handlers[dfsc](td, frame, esr, far, 1);
- else {
- print_registers(frame);
- print_gp_register("far", far);
- printf(" esr: 0x%.16lx\n", esr);
- panic("Unhandled EL0 %s abort: 0x%x",
- exception == EXCP_INSN_ABORT_L ? "instruction" :
- "data", dfsc);
+ abort_handlers[dfsc] != NULL) {
+ has_sig = abort_handlers[dfsc](td, frame, esr, far, 1);
+ } else {
+ call_trapsignal(td, SIGBUS, BUS_OBJERR,
+ (void *)frame->tf_elr, exception);
+ has_sig = true;
}
break;
case EXCP_UNKNOWN:
- if (!undef_insn(frame))
+ if (!undef_insn(frame)) {
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)far,
exception);
+ has_sig = true;
+ }
break;
case EXCP_FPAC:
call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr,
exception);
+ has_sig = true;
break;
case EXCP_SP_ALIGN:
call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp,
exception);
+ has_sig = true;
break;
case EXCP_PC_ALIGN:
call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr,
exception);
+ has_sig = true;
break;
case EXCP_BRKPT_EL0:
case EXCP_BRK:
@@ -785,10 +800,12 @@
#endif /* COMPAT_FREEBSD32 */
call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr,
exception);
+ has_sig = true;
break;
case EXCP_WATCHPT_EL0:
call_trapsignal(td, SIGTRAP, TRAP_TRACE, (void *)far,
exception);
+ has_sig = true;
break;
case EXCP_MSR:
/*
@@ -796,9 +813,11 @@
* instruction to access a special register userspace doesn't
* have access to.
*/
- if (!undef_insn(frame))
+ if (!undef_insn(frame)) {
call_trapsignal(td, SIGILL, ILL_PRVOPC,
(void *)frame->tf_elr, exception);
+ has_sig = true;
+ }
break;
case EXCP_SOFTSTP_EL0:
PROC_LOCK(td->td_proc);
@@ -811,10 +830,12 @@
PROC_UNLOCK(td->td_proc);
call_trapsignal(td, SIGTRAP, TRAP_TRACE,
(void *)frame->tf_elr, exception);
+ has_sig = true;
break;
case EXCP_BTI:
call_trapsignal(td, SIGILL, ILL_ILLOPC, (void *)frame->tf_elr,
exception);
+ has_sig = true;
break;
case EXCP_MOE:
handle_moe(td, frame, esr);
@@ -822,9 +843,12 @@
default:
call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)frame->tf_elr,
exception);
+ has_sig = true;
break;
}
+ if (!has_sig)
+ mte_check_async(td, frame, false);
if (!skip_userret)
userret(td, frame);
KASSERT(
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -292,6 +292,7 @@
void mte_save_tags(vm_page_t, void *);
void mte_load_tags(vm_page_t, const void *);
void mte_copy_tags(vm_page_t, vm_page_t, vm_offset_t, vm_offset_t);
+bool mte_check_async(struct thread *, struct trapframe *, bool);
int mte_sysarch_ctrl(struct thread *, uint64_t);

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 5, 2:25 AM (10 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40221992
Default Alt Text
D55959.id173929.diff (8 KB)

Event Timeline