diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-07-23 15:09:10 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-07-23 15:09:10 +0000 |
commit | 972a91a7c771fd6abb5e1ccdfa45e666e90537a3 (patch) | |
tree | 2152dacc7831bcd9cc9c75b6a93b5accaaabaf85 | |
parent | b0e995058df18d12c799569b0d4751cf81ed05de (diff) |
Use per-pmap lock to protect userland SLB handling.
-rw-r--r-- | sys/arch/powerpc64/include/pmap.h | 6 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/pmap.c | 36 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap.c | 21 |
3 files changed, 40 insertions, 23 deletions
diff --git a/sys/arch/powerpc64/include/pmap.h b/sys/arch/powerpc64/include/pmap.h index aea50f9562a..50ff0464e9c 100644 --- a/sys/arch/powerpc64/include/pmap.h +++ b/sys/arch/powerpc64/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.12 2020/07/21 21:01:34 kettenis Exp $ */ +/* $OpenBSD: pmap.h,v 1.13 2020/07/23 15:09:09 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -68,9 +68,7 @@ extern struct pmap kernel_pmap_store; void pmap_bootstrap(void); void pmap_bootstrap_cpu(void); -struct slb_desc *pmap_slbd_lookup(pmap_t, vaddr_t); -void pmap_slbd_cache(pmap_t, struct slb_desc *); - +int pmap_slbd_fault(pmap_t, vaddr_t); int pmap_set_user_slb(pmap_t, vaddr_t, vaddr_t *, vsize_t *); void pmap_unset_user_slb(void); diff --git a/sys/arch/powerpc64/powerpc64/pmap.c b/sys/arch/powerpc64/powerpc64/pmap.c index 8c167f1f3cf..9a588def095 100644 --- a/sys/arch/powerpc64/powerpc64/pmap.c +++ b/sys/arch/powerpc64/powerpc64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.35 2020/07/22 20:39:02 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.36 2020/07/23 15:09:09 kettenis Exp $ */ /* * Copyright (c) 2015 Martin Pieuchot @@ -320,6 +320,8 @@ pmap_slbd_lookup(pmap_t pm, vaddr_t va) uint64_t esid = va >> ADDR_ESID_SHIFT; struct slb_desc *slbd; + PMAP_VP_ASSERT_LOCKED(pm); + LIST_FOREACH(slbd, &pm->pm_slbd, slbd_list) { if (slbd->slbd_esid == esid) return slbd; @@ -334,6 +336,8 @@ pmap_slbd_cache(pmap_t pm, struct slb_desc *slbd) uint64_t slbe, slbv; int idx; + PMAP_VP_ASSERT_LOCKED(pm); + for (idx = 0; idx < nitems(pm->pm_slb); idx++) { if (pm->pm_slb[idx].slb_slbe == 0) break; @@ -348,6 +352,23 @@ pmap_slbd_cache(pmap_t pm, struct slb_desc *slbd) pm->pm_slb[idx].slb_slbv = slbv; } +int +pmap_slbd_fault(pmap_t pm, vaddr_t va) +{ + struct slb_desc *slbd; + + PMAP_VP_LOCK(pm); + slbd = pmap_slbd_lookup(pm, va); + if (slbd) { + pmap_slbd_cache(pm, slbd); + PMAP_VP_UNLOCK(pm); + return 0; + } + PMAP_VP_UNLOCK(pm); + + return EFAULT; +} + u_int pmap_vsid; struct slb_desc * @@ -357,6 +378,7 @@ pmap_slbd_alloc(pmap_t pm, vaddr_t va) struct slb_desc *slbd; KASSERT(pm != pmap_kernel()); + PMAP_VP_ASSERT_LOCKED(pm); slbd = pool_get(&pmap_slbd_pool, PR_NOWAIT | PR_ZERO); if (slbd == NULL) @@ -379,15 +401,21 @@ pmap_set_user_slb(pmap_t pm, vaddr_t va, vaddr_t *kva, vsize_t *len) struct cpu_info *ci = curcpu(); struct slb_desc *slbd; uint64_t slbe, slbv; + uint64_t vsid; KASSERT(pm != pmap_kernel()); + PMAP_VP_LOCK(pm); slbd = pmap_slbd_lookup(pm, va); if (slbd == NULL) { slbd = pmap_slbd_alloc(pm, va); - if (slbd == NULL) + if (slbd == NULL) { + PMAP_VP_UNLOCK(pm); return EFAULT; + } } + vsid = slbd->slbd_vsid; + PMAP_VP_UNLOCK(pm); /* * We might get here while another process is sleeping while @@ -401,7 +429,7 @@ pmap_set_user_slb(pmap_t pm, vaddr_t va, vaddr_t *kva, vsize_t *len) } slbe = (USER_ESID << SLBE_ESID_SHIFT) | SLBE_VALID | 31; - slbv = slbd->slbd_vsid << SLBV_VSID_SHIFT; + slbv = vsid << SLBV_VSID_SHIFT; ci->ci_kernel_slb[31].slb_slbe = slbe; ci->ci_kernel_slb[31].slb_slbv = slbv; @@ -1313,7 +1341,9 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pa) return 1; } + PMAP_VP_LOCK(pm); vsid = pmap_va2vsid(pm, va); + PMAP_VP_UNLOCK(pm); if (vsid == 0) return 0; diff --git a/sys/arch/powerpc64/powerpc64/trap.c b/sys/arch/powerpc64/powerpc64/trap.c index ae540fd2281..4cda5ae9b2e 100644 --- a/sys/arch/powerpc64/powerpc64/trap.c +++ b/sys/arch/powerpc64/powerpc64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.32 2020/07/23 09:49:33 kettenis Exp $ */ +/* $OpenBSD: trap.c,v 1.33 2020/07/23 15:09:09 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -48,7 +48,6 @@ trap(struct trapframe *frame) int type = frame->exc; union sigval sv; struct vm_map *map; - struct slb_desc *slbd; pmap_t pm; vaddr_t va; int ftype; @@ -168,14 +167,9 @@ trap(struct trapframe *frame) case EXC_DSE|EXC_USER: pm = p->p_vmspace->vm_map.pmap; - KERNEL_LOCK(); - slbd = pmap_slbd_lookup(pm, frame->dar); - if (slbd) { - pmap_slbd_cache(pm, slbd); - KERNEL_UNLOCK(); + error = pmap_slbd_fault(pm, frame->dar); + if (error == 0) break; - } - KERNEL_UNLOCK(); frame->dsisr = 0; /* FALLTHROUGH */ @@ -218,14 +212,9 @@ trap(struct trapframe *frame) case EXC_ISE|EXC_USER: pm = p->p_vmspace->vm_map.pmap; - KERNEL_LOCK(); - slbd = pmap_slbd_lookup(pm, frame->srr0); - if (slbd) { - pmap_slbd_cache(pm, slbd); - KERNEL_UNLOCK(); + error = pmap_slbd_fault(pm, frame->srr0); + if (error == 0) break; - } - KERNEL_UNLOCK(); /* FALLTHROUGH */ case EXC_ISI|EXC_USER: |