summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-07-23 15:09:10 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-07-23 15:09:10 +0000
commit972a91a7c771fd6abb5e1ccdfa45e666e90537a3 (patch)
tree2152dacc7831bcd9cc9c75b6a93b5accaaabaf85
parentb0e995058df18d12c799569b0d4751cf81ed05de (diff)
Use per-pmap lock to protect userland SLB handling.
-rw-r--r--sys/arch/powerpc64/include/pmap.h6
-rw-r--r--sys/arch/powerpc64/powerpc64/pmap.c36
-rw-r--r--sys/arch/powerpc64/powerpc64/trap.c21
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: