diff options
-rw-r--r-- | sys/arch/powerpc64/include/pcb.h | 3 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/pmap.h | 4 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/pte.h | 7 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/machdep.c | 22 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/pmap.c | 18 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap.c | 14 |
6 files changed, 47 insertions, 21 deletions
diff --git a/sys/arch/powerpc64/include/pcb.h b/sys/arch/powerpc64/include/pcb.h index c10fe5dcca5..349707f4eac 100644 --- a/sys/arch/powerpc64/include/pcb.h +++ b/sys/arch/powerpc64/include/pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcb.h,v 1.5 2020/06/28 00:07:22 kettenis Exp $ */ +/* $OpenBSD: pcb.h,v 1.6 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -28,6 +28,7 @@ struct pcb { #define PCB_VEC 0x000000002 #define PCB_VSX 0x000000004 vaddr_t pcb_onfault; + vaddr_t pcb_userva; struct fpreg pcb_fpstate; }; diff --git a/sys/arch/powerpc64/include/pmap.h b/sys/arch/powerpc64/include/pmap.h index cb042fd89fc..daa1a356429 100644 --- a/sys/arch/powerpc64/include/pmap.h +++ b/sys/arch/powerpc64/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.8 2020/06/25 17:36:08 kettenis Exp $ */ +/* $OpenBSD: pmap.h,v 1.9 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -78,7 +78,7 @@ 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); +int pmap_set_user_slb(pmap_t, vaddr_t, vsize_t, vaddr_t *); void pmap_unset_user_slb(void); #ifdef DDB diff --git a/sys/arch/powerpc64/include/pte.h b/sys/arch/powerpc64/include/pte.h index 3438fb3f9bf..71e941aca3f 100644 --- a/sys/arch/powerpc64/include/pte.h +++ b/sys/arch/powerpc64/include/pte.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pte.h,v 1.3 2020/06/18 21:52:57 kettenis Exp $ */ +/* $OpenBSD: pte.h,v 1.4 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -69,4 +69,9 @@ struct slb { uint64_t slb_slbv; }; +#define USER_ADDR 0xcfffffff00000000ULL +#define USER_ESID (USER_ADDR >> ADDR_ESID_SHIFT) +#define SEGMENT_SIZE (256 * 1024 * 1024) +#define SEGMENT_MASK (SEGMENT_SIZE - 1) + #endif /* _MACHINE_PTE_H_ */ diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c index 4103b282d1e..d05c5232f50 100644 --- a/sys/arch/powerpc64/powerpc64/machdep.c +++ b/sys/arch/powerpc64/powerpc64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.38 2020/06/30 20:09:37 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.39 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -415,12 +415,13 @@ int copyin(const void *uaddr, void *kaddr, size_t len) { pmap_t pm = curproc->p_vmspace->vm_map.pmap; + vaddr_t kva; int error; - error = pmap_set_user_slb(pm, (vaddr_t)uaddr); + error = pmap_set_user_slb(pm, (vaddr_t)uaddr, len, &kva); if (error) return error; - error = kcopy(uaddr, kaddr, len); + error = kcopy((const void *)kva, kaddr, len); pmap_unset_user_slb(); return error; } @@ -429,12 +430,13 @@ int copyout(const void *kaddr, void *uaddr, size_t len) { pmap_t pm = curproc->p_vmspace->vm_map.pmap; + vaddr_t kva; int error; - error = pmap_set_user_slb(pm, (vaddr_t)uaddr); + error = pmap_set_user_slb(pm, (vaddr_t)uaddr, len, &kva); if (error) return error; - error = kcopy(kaddr, uaddr, len); + error = kcopy(kaddr, (void *)kva, len); pmap_unset_user_slb(); return error; } @@ -443,12 +445,13 @@ int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) { pmap_t pm = curproc->p_vmspace->vm_map.pmap; + vaddr_t kva; int error; - error = pmap_set_user_slb(pm, (vaddr_t)uaddr); + error = pmap_set_user_slb(pm, (vaddr_t)uaddr, len, &kva); if (error) return error; - error = copystr(uaddr, kaddr, len, done); + error = copystr((const void *)kva, kaddr, len, done); pmap_unset_user_slb(); return error; } @@ -457,12 +460,13 @@ int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) { pmap_t pm = curproc->p_vmspace->vm_map.pmap; + vaddr_t kva; int error; - error = pmap_set_user_slb(pm, (vaddr_t)uaddr); + error = pmap_set_user_slb(pm, (vaddr_t)uaddr, len, &kva); if (error) return error; - error = copystr(kaddr, uaddr, len, done); + error = copystr(kaddr, (void *)kva, len, done); pmap_unset_user_slb(); return error; } diff --git a/sys/arch/powerpc64/powerpc64/pmap.c b/sys/arch/powerpc64/powerpc64/pmap.c index e085c182863..f0d551bdb5e 100644 --- a/sys/arch/powerpc64/powerpc64/pmap.c +++ b/sys/arch/powerpc64/powerpc64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.21 2020/06/30 20:35:53 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.22 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2015 Martin Pieuchot @@ -54,6 +54,7 @@ #include <uvm/uvm_extern.h> #include <machine/cpufunc.h> +#include <machine/pcb.h> #include <machine/pmap.h> #include <machine/pte.h> @@ -357,7 +358,7 @@ pmap_slbd_alloc(pmap_t pm, vaddr_t va) } int -pmap_set_user_slb(pmap_t pm, vaddr_t va) +pmap_set_user_slb(pmap_t pm, vaddr_t va, vsize_t len, vaddr_t *kva) { struct cpu_info *ci = curcpu(); struct slb_desc *slbd; @@ -365,13 +366,15 @@ pmap_set_user_slb(pmap_t pm, vaddr_t va) KASSERT(pm != pmap_kernel()); + if (len > SEGMENT_SIZE) + return EFAULT; + slbd = pmap_slbd_lookup(pm, va); if (slbd == NULL) { slbd = pmap_slbd_alloc(pm, va); if (slbd == NULL) return EFAULT; } - KASSERT(slbd->slbd_esid != 0); /* * We might get here while another process is sleeping while @@ -384,7 +387,7 @@ pmap_set_user_slb(pmap_t pm, vaddr_t va) isync(); } - slbe = (slbd->slbd_esid << SLBE_ESID_SHIFT) | SLBE_VALID | 31; + slbe = (USER_ESID << SLBE_ESID_SHIFT) | SLBE_VALID | 31; slbv = slbd->slbd_vsid << SLBV_VSID_SHIFT; ci->ci_kernel_slb[31].slb_slbe = slbe; @@ -394,6 +397,11 @@ pmap_set_user_slb(pmap_t pm, vaddr_t va) slbmte(slbv, slbe); isync(); + curpcb->pcb_userva = (va & ~SEGMENT_MASK); + + if (kva) + *kva = USER_ADDR | (va & SEGMENT_MASK); + return 0; } @@ -402,6 +410,8 @@ pmap_unset_user_slb(void) { struct cpu_info *ci = curcpu(); + curpcb->pcb_userva = 0; + isync(); slbie(ci->ci_kernel_slb[31].slb_slbe); isync(); diff --git a/sys/arch/powerpc64/powerpc64/trap.c b/sys/arch/powerpc64/powerpc64/trap.c index f05af0e3917..226f25f782f 100644 --- a/sys/arch/powerpc64/powerpc64/trap.c +++ b/sys/arch/powerpc64/powerpc64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.19 2020/06/30 20:35:53 kettenis Exp $ */ +/* $OpenBSD: trap.c,v 1.20 2020/07/01 16:05:48 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -27,6 +27,7 @@ #include <uvm/uvm_extern.h> #include <machine/fpu.h> +#include <machine/pte.h> #include <machine/trap.h> #ifdef DDB @@ -94,8 +95,11 @@ trap(struct trapframe *frame) case EXC_DSI: map = kernel_map; va = frame->dar; - if (curpcb->pcb_onfault && va < VM_MAXUSER_ADDRESS) + if (curpcb->pcb_onfault && + (va >> ADDR_ESID_SHIFT) == USER_ESID) { map = &p->p_vmspace->vm_map; + va = curpcb->pcb_userva | (va & SEGMENT_MASK); + } if (frame->dsisr & DSISR_STORE) ftype = PROT_READ | PROT_WRITE; else @@ -121,9 +125,11 @@ trap(struct trapframe *frame) * SLB entry. Enter it again. */ va = frame->dar; - if (curpcb->pcb_onfault && va < VM_MAXUSER_ADDRESS) { + if (curpcb->pcb_onfault && + (va >> ADDR_ESID_SHIFT) == USER_ESID) { map = &p->p_vmspace->vm_map; - if (pmap_set_user_slb(map->pmap, va) == 0) + va = curpcb->pcb_userva | (va & SEGMENT_MASK); + if (pmap_set_user_slb(map->pmap, va, 0, NULL) == 0) return; } |