summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arch/powerpc64/include/pcb.h3
-rw-r--r--sys/arch/powerpc64/include/pmap.h4
-rw-r--r--sys/arch/powerpc64/include/pte.h7
-rw-r--r--sys/arch/powerpc64/powerpc64/machdep.c22
-rw-r--r--sys/arch/powerpc64/powerpc64/pmap.c18
-rw-r--r--sys/arch/powerpc64/powerpc64/trap.c14
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;
}