summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2020-06-22 18:03:22 +0000
committerkettenis <kettenis@openbsd.org>2020-06-22 18:03:22 +0000
commitc0e8dfc26859acc5c80a7cd731a9232aad396d94 (patch)
tree06c987bcee62a3a4b6f3a27a0d74ba032a0b2899
parentMake return-to-user and kernel re-entry work. This adds a per-pmap SLB (diff)
downloadwireguard-openbsd-c0e8dfc26859acc5c80a7cd731a9232aad396d94.tar.xz
wireguard-openbsd-c0e8dfc26859acc5c80a7cd731a9232aad396d94.zip
Handle data storage and data segment interrupts from userland as well.
-rw-r--r--sys/arch/powerpc64/include/pmap.h5
-rw-r--r--sys/arch/powerpc64/powerpc64/pmap.c38
-rw-r--r--sys/arch/powerpc64/powerpc64/trap.c41
3 files changed, 66 insertions, 18 deletions
diff --git a/sys/arch/powerpc64/include/pmap.h b/sys/arch/powerpc64/include/pmap.h
index 0c252b06ecf..33fcd24c0e1 100644
--- a/sys/arch/powerpc64/include/pmap.h
+++ b/sys/arch/powerpc64/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.6 2020/06/22 16:58:20 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.7 2020/06/22 18:03:22 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -73,6 +73,9 @@ extern struct pmap kernel_pmap_store;
void pmap_bootstrap(void);
+struct slb_desc *pmap_slbd_lookup(pmap_t, vaddr_t);
+void pmap_slbd_cache(pmap_t, struct slb_desc *);
+
int pmap_set_user_slb(pmap_t, vaddr_t);
void pmap_unset_user_slb(void);
diff --git a/sys/arch/powerpc64/powerpc64/pmap.c b/sys/arch/powerpc64/powerpc64/pmap.c
index 229f9502f17..4b0811c3b14 100644
--- a/sys/arch/powerpc64/powerpc64/pmap.c
+++ b/sys/arch/powerpc64/powerpc64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.15 2020/06/22 16:58:20 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.16 2020/06/22 18:03:22 kettenis Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
@@ -306,6 +306,26 @@ pmap_slbd_lookup(pmap_t pm, vaddr_t va)
return NULL;
}
+void
+pmap_slbd_cache(pmap_t pm, struct slb_desc *slbd)
+{
+ uint64_t slbe, slbv;
+ int idx;
+
+ for (idx = 0; idx < nitems(pm->pm_slb); idx++) {
+ if (pm->pm_slb[idx].slb_slbe == 0)
+ break;
+ }
+ if (idx == nitems(pm->pm_slb))
+ idx = arc4random_uniform(nitems(pm->pm_slb));
+
+ slbe = (slbd->slbd_esid << SLBE_ESID_SHIFT) | SLBE_VALID | idx;
+ slbv = slbd->slbd_vsid << SLBV_VSID_SHIFT;
+
+ pm->pm_slb[idx].slb_slbe = slbe;
+ pm->pm_slb[idx].slb_slbv = slbv;
+}
+
int pmap_vsid = 1;
struct slb_desc *
@@ -313,8 +333,6 @@ pmap_slbd_alloc(pmap_t pm, vaddr_t va)
{
uint64_t esid = va >> ADDR_ESID_SHIFT;
struct slb_desc *slbd;
- uint64_t slbe, slbv;
- int i;
KASSERT(pm != pmap_kernel());
@@ -326,18 +344,8 @@ pmap_slbd_alloc(pmap_t pm, vaddr_t va)
slbd->slbd_vsid = pmap_vsid++;
LIST_INSERT_HEAD(&pm->pm_slbd, slbd, slbd_list);
- slbe = (slbd->slbd_esid << SLBE_ESID_SHIFT) | SLBE_VALID | 31;
- slbv = slbd->slbd_vsid << SLBV_VSID_SHIFT;
-
- for (i = 0; i < nitems(pm->pm_slb); i++) {
- if (pm->pm_slb[i].slb_slbe == 0)
- break;
- }
- if (i == nitems(pm->pm_slb))
- i = arc4random_uniform(nitems(pm->pm_slb));
-
- pm->pm_slb[i].slb_slbe = slbe;
- pm->pm_slb[i].slb_slbv = slbv;
+ /* We're almost certainly going to use it soon. */
+ pmap_slbd_cache(pm, slbd);
return slbd;
}
diff --git a/sys/arch/powerpc64/powerpc64/trap.c b/sys/arch/powerpc64/powerpc64/trap.c
index 313d9b31066..3807aca55de 100644
--- a/sys/arch/powerpc64/powerpc64/trap.c
+++ b/sys/arch/powerpc64/powerpc64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.11 2020/06/22 16:58:20 kettenis Exp $ */
+/* $OpenBSD: trap.c,v 1.12 2020/06/22 18:03:22 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -41,6 +41,8 @@ trap(struct trapframe *frame)
struct proc *p = curproc;
int type = frame->exc;
struct vm_map *map;
+ struct slb_desc *slbd;
+ pmap_t pm;
vaddr_t va;
int ftype;
int error;
@@ -107,12 +109,47 @@ trap(struct trapframe *frame)
printf("dar 0x%lx dsisr 0x%lx\n", frame->dar, frame->dsisr);
goto fatal;
- case EXC_ISI|EXC_USER:
+ case EXC_DSE|EXC_USER:
+ intr_enable();
+ pm = p->p_vmspace->vm_map.pmap;
+ slbd = pmap_slbd_lookup(pm, frame->dar);
+ if (slbd) {
+ pmap_slbd_cache(pm, slbd);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EXC_DSI|EXC_USER:
+ intr_enable();
+ map = &p->p_vmspace->vm_map;
+ va = frame->dar;
+ if (frame->dsisr & DSISR_STORE)
+ ftype = PROT_READ | PROT_WRITE;
+ else
+ ftype = PROT_READ;
+ KERNEL_LOCK();
+ error = uvm_fault(map, trunc_page(va), 0, ftype);
+ KERNEL_UNLOCK();
+ if (error)
+ goto fatal;
+ break;
+
case EXC_ISE|EXC_USER:
intr_enable();
+ pm = p->p_vmspace->vm_map.pmap;
+ slbd = pmap_slbd_lookup(pm, frame->srr0);
+ if (slbd) {
+ pmap_slbd_cache(pm, slbd);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EXC_ISI|EXC_USER:
+ intr_enable();
map = &p->p_vmspace->vm_map;
va = frame->srr0;
ftype = PROT_READ | PROT_EXEC;
+ KERNEL_LOCK();
error = uvm_fault(map, trunc_page(va), 0, ftype);
KERNEL_UNLOCK();
if (error)