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 @@ -247,7 +247,6 @@ uint64_t far, int lower) { struct vm_map *map; - struct proc *p; struct pcb *pcb; vm_prot_t ftype; int error, sig, ucode; @@ -269,28 +268,40 @@ } #endif - pcb = td->td_pcb; - p = td->td_proc; - if (lower) - map = &p->p_vmspace->vm_map; - else { - intr_enable(); - + if (lower) { + map = &td->td_proc->p_vmspace->vm_map; + } else if (!ADDR_IS_CANONICAL(far)) { /* We received a TBI/PAC/etc. fault from the kernel */ - if (!ADDR_IS_CANONICAL(far)) { - error = KERN_INVALID_ADDRESS; - goto bad_far; + error = KERN_INVALID_ADDRESS; + goto bad_far; + } else if (ADDR_IS_KERNEL(far)) { + /* + * Handle a special case: the data abort was caused by accessing + * a thread structure while its mapping was being promoted or + * demoted, as a consequence of the break-before-make rule. It + * is not safe to enable interrupts or dereference "td" before + * this case is handled. + */ + map = kernel_map; + if (ESR_ELx_EXCEPTION(esr) == EXCP_DATA_ABORT) { + switch (esr & ISS_DATA_DFSC_MASK) { + case ISS_DATA_DFSC_TF_L0: + case ISS_DATA_DFSC_TF_L1: + case ISS_DATA_DFSC_TF_L2: + case ISS_DATA_DFSC_TF_L3: + if (pmap_klookup(far, NULL)) + return; + break; + } } - - /* The top bit tells us which range to use */ - if (ADDR_IS_KERNEL(far)) { + intr_enable(); + } else { + map = &td->td_proc->p_vmspace->vm_map; + if (map == NULL) map = kernel_map; - } else { - map = &p->p_vmspace->vm_map; - if (map == NULL) - map = kernel_map; - } + intr_enable(); } + pcb = td->td_pcb; /* * Try to handle translation, access flag, and permission faults. @@ -335,11 +346,11 @@ /* Fault in the page. */ error = vm_fault_trap(map, far, ftype, VM_FAULT_NORMAL, &sig, &ucode); if (error != KERN_SUCCESS) { -bad_far: if (lower) { call_trapsignal(td, sig, ucode, (void *)far, ESR_ELx_EXCEPTION(esr)); } else { +bad_far: if (td->td_intr_nesting_level == 0 && pcb->pcb_onfault != 0) { frame->tf_x[0] = error; diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -503,7 +503,6 @@ { u_long i; lwpid_t tid0; - uint32_t flags; /* * Place an upper limit on threads which can be allocated. @@ -531,20 +530,9 @@ if (tid0 != THREAD0_TID) panic("tid0 %d != %d\n", tid0, THREAD0_TID); - flags = UMA_ZONE_NOFREE; -#ifdef __aarch64__ - /* - * Force thread structures to be allocated from the direct map. - * Otherwise, superpage promotions and demotions may temporarily - * invalidate thread structure mappings. For most dynamically allocated - * structures this is not a problem, but translation faults cannot be - * handled without accessing curthread. - */ - flags |= UMA_ZONE_CONTIG; -#endif thread_zone = uma_zcreate("THREAD", sched_sizeof_thread(), thread_ctor, thread_dtor, thread_init, thread_fini, - 32 - 1, flags); + 32 - 1, UMA_ZONE_NOFREE); tidhashtbl = hashinit(maxproc / 2, M_TIDHASH, &tidhash); tidhashlock = (tidhash + 1) / 64; if (tidhashlock > 0)