diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-06-22 18:03:23 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-06-22 18:03:23 +0000 |
commit | 55e2ac58e8d34eca736923047073103b25a13d86 (patch) | |
tree | 2051c405de72415d1e7b0388435607abd6c91be8 | |
parent | 973a8904707e1438a2d6c1090c8b7cfc688e9a5e (diff) |
Handle data storage and data segment interrupts from userland as well.
-rw-r--r-- | sys/arch/powerpc64/include/pmap.h | 5 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/pmap.c | 38 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap.c | 41 |
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) |