Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/arm64/trap.c
Show First 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | else { | ||||
} else { | } else { | ||||
map = &p->p_vmspace->vm_map; | map = &p->p_vmspace->vm_map; | ||||
if (map == NULL) | if (map == NULL) | ||||
map = kernel_map; | map = kernel_map; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* The call to pmap_fault can be dangerous when coming from the | * Try to handle translation, access flag, and permission faults. | ||||
* kernel as it may be not be able to lock the pmap to check if | * Translation faults may occur as a result of the required | ||||
* the address is now valid. Because of this we filter the cases | * break-before-make sequence used when promoting or demoting | ||||
* when we are not going to see superpage activity. | * superpages. Such faults must not occur while holding the pmap lock, | ||||
* or pmap_fault() will recurse on that lock. | |||||
*/ | */ | ||||
if (!lower) { | if ((lower || map == kernel_map || pcb->pcb_onfault != 0) && | ||||
/* | pmap_fault(map->pmap, esr, far) == KERN_SUCCESS) | ||||
* We may fault in a DMAP region due to a superpage being | |||||
* unmapped when the access took place. | |||||
*/ | |||||
if (map == kernel_map && !VIRT_IN_DMAP(far)) | |||||
goto no_pmap_fault; | |||||
/* | |||||
* We can also fault in the userspace handling functions, | |||||
* e.g. copyin. In these cases we will have set a fault | |||||
* handler so we can check if this is set before calling | |||||
* pmap_fault. | |||||
*/ | |||||
if (map != kernel_map && pcb->pcb_onfault == 0) | |||||
goto no_pmap_fault; | |||||
} | |||||
if (pmap_fault(map->pmap, esr, far) == KERN_SUCCESS) | |||||
return; | return; | ||||
no_pmap_fault: | |||||
KASSERT(td->td_md.md_spinlock_count == 0, | KASSERT(td->td_md.md_spinlock_count == 0, | ||||
("data abort with spinlock held")); | ("data abort with spinlock held")); | ||||
if (td->td_critnest != 0 || WITNESS_CHECK(WARN_SLEEPOK | | if (td->td_critnest != 0 || WITNESS_CHECK(WARN_SLEEPOK | | ||||
WARN_GIANTOK, NULL, "Kernel page fault") != 0) { | WARN_GIANTOK, NULL, "Kernel page fault") != 0) { | ||||
print_registers(frame); | print_registers(frame); | ||||
printf(" far: %16lx\n", far); | printf(" far: %16lx\n", far); | ||||
printf(" esr: %.8lx\n", esr); | printf(" esr: %.8lx\n", esr); | ||||
panic("data abort in critical section or under mutex"); | panic("data abort in critical section or under mutex"); | ||||
} | } | ||||
va = trunc_page(far); | va = trunc_page(far); | ||||
ftype = ((esr >> 6) & 1) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ; | |||||
if (exec) | if (exec) | ||||
ftype |= VM_PROT_EXECUTE; | ftype = VM_PROT_EXECUTE; | ||||
else | |||||
ftype = (esr & ISS_DATA_WnR) == 0 ? VM_PROT_READ : | |||||
VM_PROT_READ | VM_PROT_WRITE; | |||||
/* Fault in the page. */ | /* Fault in the page. */ | ||||
error = vm_fault(map, va, ftype, VM_FAULT_NORMAL); | error = vm_fault(map, va, ftype, VM_FAULT_NORMAL); | ||||
if (error != KERN_SUCCESS) { | if (error != KERN_SUCCESS) { | ||||
if (lower) { | if (lower) { | ||||
sig = SIGSEGV; | sig = SIGSEGV; | ||||
if (error == KERN_PROTECTION_FAILURE) | if (error == KERN_PROTECTION_FAILURE) | ||||
ucode = SEGV_ACCERR; | ucode = SEGV_ACCERR; | ||||
▲ Show 20 Lines • Show All 273 Lines • Show Last 20 Lines |