summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2022-10-30 10:26:48 +0000
committerriastradh <riastradh@NetBSD.org>2022-10-30 10:26:48 +0000
commit353e533a1f2eb0b29fc29e7655bab00f0084aa14 (patch)
treef390b55d3e5e948d458da890ffc221307eacc4bf /sys/dev
parentd4969906cfffadb4e12d98ec9c12d9ccea3758df (diff)
aarch64/pmap(9): Teach pmap_protect about pmap_kenter_pa mappings.
Pages mapped with pmap_kenter_pa are necessarily unmanaged, so there are no P->V records, and pmap_kenter_pa leaves pp->pp_pv.pv_va zero with no modified/referenced state. However, pmap_protect erroneously examined pp->pp_pv.pv_va to ascertain the modified/referenced state -- and if the page was not marked referenced, pmap_protect would clear the LX_BLKPAG_AF bit (Access Flag), with the effect that subsequent uses of the page fault and require a detour through pmap_fault_fixup. This caused problems for the kernel module loader: - When loading the text section, kobj_load first allocates kva with uvm_km_alloc(UVM_KMF_WIRED|UVM_KMF_EXEC), which creates ptes with pmap_kenter_pa. These ptes are writable, so we can copy the text section into them, and have LX_BLKPAG_AF set so there will be no fault when they are used by the kernel. - But then kobj_affix makes the text section read/execute-only (and nonwritable) with uvm_km_protect(VM_PROT_READ|VM_PROT_EXECUTE), which updates the ptes with pmap_protect. This _should_ leave LX_BLKPAG_AF set, but by inadvertently treating the page as managed when it should be unmanaged, pmap_protect cleared it instead. - Most of the time, clearing LX_BLKPAG_AF caused no problem, because pmap_fault_fixup would silently resolve it. But if a hard interrupt handler tried to use any page in the module's text (or rodata, I suspect) that was not yet fixed up, the CPU would fault and enter pmap_fault_fixup -- which would promptly crash (or hang) by trying to take the pmap lock in interrupt context, which is forbidden. I observed this by loading dtrace.kmod early at boot and trying to dtrace hard interrupt handlers. With this change, pmap_protect now recognizes wired mappings (as created by pmap_kenter_pa) before consulting pp->pp_pv.pv_va, and preserves then LX_BLKPAG_AF bit in that case. ok skrll
Diffstat (limited to 'sys/dev')
0 files changed, 0 insertions, 0 deletions