summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2021-09-14 16:14:51 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2021-09-14 16:14:51 +0000
commit8424a88248eed2f5dee42c941ed8cf29287fbab6 (patch)
treeb771e29899a3d70b5c69d9817862216dab452039
parent09f0bb0a15040539fad2b07927b9fddd2b686d82 (diff)
Make pmap_extract() mpsafe by grabbing the kernel lock for userland pmaps
while walking the page tables. ok mpi@, deraadt@
-rw-r--r--sys/arch/amd64/amd64/pmap.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index d74061e45a5..4773d35121d 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.147 2021/09/06 12:59:59 mpi Exp $ */
+/* $OpenBSD: pmap.c,v 1.148 2021/09/14 16:14:50 kettenis Exp $ */
/* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
/*
@@ -1504,7 +1504,7 @@ pmap_pdes_valid(vaddr_t va, pd_entry_t *lastpde)
int
pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap)
{
- pt_entry_t *ptes;
+ pt_entry_t *ptes, pte;
int level, offs;
if (pmap == pmap_kernel() && va >= PMAP_DIRECT_BASE &&
@@ -1513,16 +1513,23 @@ pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap)
return 1;
}
+ if (pmap != pmap_kernel())
+ mtx_enter(&pmap->pm_mtx);
+
level = pmap_find_pte_direct(pmap, va, &ptes, &offs);
+ pte = ptes[offs];
- if (__predict_true(level == 0 && pmap_valid_entry(ptes[offs]))) {
+ if (pmap != pmap_kernel())
+ mtx_leave(&pmap->pm_mtx);
+
+ if (__predict_true(level == 0 && pmap_valid_entry(pte))) {
if (pap != NULL)
- *pap = (ptes[offs] & PG_FRAME) | (va & PAGE_MASK);
+ *pap = (pte & PG_FRAME) | (va & PAGE_MASK);
return 1;
}
- if (level == 1 && (ptes[offs] & (PG_PS|PG_V)) == (PG_PS|PG_V)) {
+ if (level == 1 && (pte & (PG_PS|PG_V)) == (PG_PS|PG_V)) {
if (pap != NULL)
- *pap = (ptes[offs] & PG_LGFRAME) | (va & PAGE_MASK_L2);
+ *pap = (pte & PG_LGFRAME) | (va & PAGE_MASK_L2);
return 1;
}