summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2020-06-21 13:23:59 +0000
committerkettenis <kettenis@openbsd.org>2020-06-21 13:23:59 +0000
commit45dd89a788b71518ee353421475f4387cece6926 (patch)
tree611e4b1f1fff076097625d016f1ed547ea95314e
parentadd a commented out entry for wg(4). (diff)
downloadwireguard-openbsd-45dd89a788b71518ee353421475f4387cece6926.tar.xz
wireguard-openbsd-45dd89a788b71518ee353421475f4387cece6926.zip
Implement copyin(9), copyout(9), copyinstr(9) and copyoutstr(9).
-rw-r--r--sys/arch/powerpc64/include/cpu.h5
-rw-r--r--sys/arch/powerpc64/include/pcb.h7
-rw-r--r--sys/arch/powerpc64/include/pmap.h5
-rw-r--r--sys/arch/powerpc64/include/trap.h6
-rw-r--r--sys/arch/powerpc64/powerpc64/genassym.cf3
-rw-r--r--sys/arch/powerpc64/powerpc64/locore.S3
-rw-r--r--sys/arch/powerpc64/powerpc64/machdep.c86
-rw-r--r--sys/arch/powerpc64/powerpc64/pmap.c87
-rw-r--r--sys/arch/powerpc64/powerpc64/trap.c36
-rw-r--r--sys/arch/powerpc64/powerpc64/trap_subr.S10
10 files changed, 212 insertions, 36 deletions
diff --git a/sys/arch/powerpc64/include/cpu.h b/sys/arch/powerpc64/include/cpu.h
index 75f78d02714..36b350366e4 100644
--- a/sys/arch/powerpc64/include/cpu.h
+++ b/sys/arch/powerpc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.13 2020/06/18 21:52:57 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.14 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -46,6 +46,7 @@ struct cpu_info {
struct schedstate_percpu ci_schedstate;
struct proc *ci_curproc;
+ struct pcb *ci_curpcb;
struct slb ci_kernel_slb[32];
@@ -93,6 +94,8 @@ register struct cpu_info *__curcpu asm("r13");
#define CPU_BUSY_CYCLE() do {} while (0)
#define signotify(p) setsoftast()
+#define curpcb curcpu()->ci_curpcb
+
static inline unsigned int
cpu_rnd_messybits(void)
{
diff --git a/sys/arch/powerpc64/include/pcb.h b/sys/arch/powerpc64/include/pcb.h
index a40e0ee8b50..6565b705f91 100644
--- a/sys/arch/powerpc64/include/pcb.h
+++ b/sys/arch/powerpc64/include/pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcb.h,v 1.2 2020/06/14 17:56:54 kettenis Exp $ */
+/* $OpenBSD: pcb.h,v 1.3 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -20,8 +20,9 @@
#define _MACHINE_PCB_H_
struct pcb {
- register_t pcb_sp;
- u_int pcb_flags;
+ register_t pcb_sp;
+ u_int pcb_flags;
+ caddr_t pcb_onfault;
};
#endif /* _MACHINE_PCB_H_ */
diff --git a/sys/arch/powerpc64/include/pmap.h b/sys/arch/powerpc64/include/pmap.h
index f0cb2688100..f0721592a6d 100644
--- a/sys/arch/powerpc64/include/pmap.h
+++ b/sys/arch/powerpc64/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.4 2020/06/17 18:58:55 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.5 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -72,6 +72,9 @@ extern struct pmap kernel_pmap_store;
void pmap_bootstrap(void);
+int pmap_set_user_slb(pmap_t, vaddr_t);
+void pmap_unset_user_slb(void);
+
#ifdef DDB
struct pte;
struct pte *pmap_get_kernel_pte(vaddr_t);
diff --git a/sys/arch/powerpc64/include/trap.h b/sys/arch/powerpc64/include/trap.h
index a9e18d3617e..6fd3b25d377 100644
--- a/sys/arch/powerpc64/include/trap.h
+++ b/sys/arch/powerpc64/include/trap.h
@@ -142,6 +142,12 @@
#define EXC_PGM_PRIV (1UL << 18)
#define EXC_PGM_TRAP (1UL << 17)
+/*
+ * DSISR bits.
+ */
+
+#define DSISR_STORE (1UL << 25)
+
/* Magic pointer to store trap handler entry point */
#define TRAP_ENTRY 0x1f8
#define TRAP_HVENTRY 0x1f0
diff --git a/sys/arch/powerpc64/powerpc64/genassym.cf b/sys/arch/powerpc64/powerpc64/genassym.cf
index 2a2456dbd61..a8013121bd9 100644
--- a/sys/arch/powerpc64/powerpc64/genassym.cf
+++ b/sys/arch/powerpc64/powerpc64/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.6 2020/06/18 22:51:38 kettenis Exp $
+# $OpenBSD: genassym.cf,v 1.7 2020/06/21 13:23:59 kettenis Exp $
#
# Copyright (c) 1982, 1990 The Regents of the University of California.
# All rights reserved.
@@ -37,6 +37,7 @@ include <machine/intr.h>
include <machine/pcb.h>
struct cpu_info
+member ci_curpcb
member ci_curproc
member ci_tempsave
member ci_kernel_slb
diff --git a/sys/arch/powerpc64/powerpc64/locore.S b/sys/arch/powerpc64/powerpc64/locore.S
index 66f1490d2f2..c31da77f9cd 100644
--- a/sys/arch/powerpc64/powerpc64/locore.S
+++ b/sys/arch/powerpc64/powerpc64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.13 2020/06/14 17:56:54 kettenis Exp $ */
+/* $OpenBSD: locore.S,v 1.14 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -89,6 +89,7 @@ cpu_switchto:
std %r4, CI_CURPROC(%r13)
ld %r31, P_ADDR(%r4)
+ std %r31, CI_CURPCB(%r13)
ld %r1, PCB_SP(%r31)
ld %r31, SF_R31(%r1)
diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c
index 124ad7c4e9a..b394557be79 100644
--- a/sys/arch/powerpc64/powerpc64/machdep.c
+++ b/sys/arch/powerpc64/powerpc64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.25 2020/06/19 22:09:49 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.26 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -24,9 +24,11 @@
#include <sys/msgbuf.h>
#include <sys/proc.h>
#include <sys/reboot.h>
+#include <sys/user.h>
#include <machine/cpufunc.h>
#include <machine/opal.h>
+#include <machine/pcb.h>
#include <machine/psl.h>
#include <machine/trap.h>
@@ -226,6 +228,8 @@ init_powernv(void *fdt, void *tocbase)
initmsgbuf((caddr_t)uvm_pageboot_alloc(MSGBUFSIZE), MSGBUFSIZE);
proc0paddr = (struct user *)initstack;
+ proc0.p_addr = proc0paddr;
+ curpcb = &proc0.p_addr->u_pcb;
uspace = (register_t)proc0paddr + USPACE - FRAMELEN;
proc0.p_md.md_regs = (struct trapframe *)uspace;
}
@@ -397,17 +401,46 @@ struct consdev opal_consdev = {
struct consdev *cn_tab = &opal_consdev;
int
-copyin(const void *src, void *dst, size_t size)
+kcopy(const void *kfaddr, void *kdaddr, size_t len)
{
- printf("%s\n", __func__);
- return EFAULT;
+ memcpy(kdaddr, kfaddr, len);
+ return 0;
}
int
-copyout(const void *src, void *dst, size_t size)
+copyin(const void *uaddr, void *kaddr, size_t len)
{
- printf("%s\n", __func__);
- return EFAULT;
+ pmap_t pm = curproc->p_p->ps_vmspace->vm_map.pmap;
+ int error;
+
+ error = pmap_set_user_slb(pm, (vaddr_t)uaddr);
+ if (error)
+ return error;
+
+ curpcb->pcb_onfault = (caddr_t)1;
+ error = kcopy(uaddr, kaddr, len);
+ curpcb->pcb_onfault = NULL;
+
+ pmap_unset_user_slb();
+ return error;
+}
+
+int
+copyout(const void *kaddr, void *uaddr, size_t len)
+{
+ pmap_t pm = curproc->p_p->ps_vmspace->vm_map.pmap;
+ int error;
+
+ error = pmap_set_user_slb(pm, (vaddr_t)uaddr);
+ if (error)
+ return error;
+
+ curpcb->pcb_onfault = (caddr_t)1;
+ error = kcopy(kaddr, uaddr, len);
+ curpcb->pcb_onfault = NULL;
+
+ pmap_unset_user_slb();
+ return error;
}
int
@@ -431,24 +464,39 @@ copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
}
int
-copyinstr(const void *src, void *dst, size_t size, size_t *lenp)
+copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
{
- printf("%s\n", __func__);
- return EFAULT;
-}
+ pmap_t pm = curproc->p_p->ps_vmspace->vm_map.pmap;
+ int error;
-int
-copyoutstr(const void *src, void *dst, size_t size, size_t *lenp)
-{
- printf("%s\n", __func__);
- return EFAULT;
+ error = pmap_set_user_slb(pm, (vaddr_t)uaddr);
+ if (error)
+ return error;
+
+ curpcb->pcb_onfault = (caddr_t)1;
+ error = copystr(uaddr, kaddr, len, done);
+ curpcb->pcb_onfault = NULL;
+
+ pmap_unset_user_slb();
+ return error;
}
int
-kcopy(const void *kfaddr, void *kdaddr, size_t len)
+copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
{
- memcpy(kdaddr, kfaddr, len);
- return 0;
+ pmap_t pm = curproc->p_p->ps_vmspace->vm_map.pmap;
+ int error;
+
+ error = pmap_set_user_slb(pm, (vaddr_t)uaddr);
+ if (error)
+ return error;
+
+ curpcb->pcb_onfault = (caddr_t)1;
+ error = copystr(kaddr, uaddr, len, done);
+ curpcb->pcb_onfault = NULL;
+
+ pmap_unset_user_slb();
+ return error;
}
void
diff --git a/sys/arch/powerpc64/powerpc64/pmap.c b/sys/arch/powerpc64/powerpc64/pmap.c
index 676df74cc67..ffc1f4e4bd4 100644
--- a/sys/arch/powerpc64/powerpc64/pmap.c
+++ b/sys/arch/powerpc64/powerpc64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.10 2020/06/18 21:52:57 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.11 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
@@ -108,6 +108,8 @@ struct slb_desc {
struct slb_desc kernel_slb_desc[32];
+struct slb_desc *pmap_slbd_lookup(pmap_t, vaddr_t);
+
struct pmapvp1 {
struct pmapvp2 *vp[VP_IDX1_CNT];
};
@@ -234,10 +236,16 @@ static inline uint64_t
pmap_va2vsid(pmap_t pm, vaddr_t va)
{
uint64_t esid = va >> ADDR_ESID_SHIFT;
+ struct slb_desc *slbd;
if (pm == pmap_kernel())
return pmap_kernel_vsid(esid);
- panic("userland");
+
+ slbd = pmap_slbd_lookup(pm, va);
+ if (slbd)
+ return slbd->slbd_vsid;
+
+ return 0;
}
void
@@ -285,8 +293,8 @@ pmap_ptedinhash(struct pte_desc *pted)
struct slb_desc *
pmap_slbd_lookup(pmap_t pm, vaddr_t va)
{
- struct slb_desc *slbd;
uint64_t esid = va >> ADDR_ESID_SHIFT;
+ struct slb_desc *slbd;
LIST_FOREACH(slbd, &pm->pm_slbd, slbd_list) {
if (slbd->slbd_esid == esid)
@@ -296,6 +304,68 @@ pmap_slbd_lookup(pmap_t pm, vaddr_t va)
return NULL;
}
+int pmap_vsid = 1;
+
+struct slb_desc *
+pmap_slbd_alloc(pmap_t pm, vaddr_t va)
+{
+ uint64_t esid = va >> ADDR_ESID_SHIFT;
+ struct slb_desc *slbd;
+
+ KASSERT(pm != pmap_kernel());
+
+ slbd = pool_get(&pmap_slbd_pool, PR_NOWAIT | PR_ZERO);
+ if (slbd == NULL)
+ return NULL;
+
+ slbd->slbd_esid = esid;
+ slbd->slbd_vsid = pmap_vsid++;
+ LIST_INSERT_HEAD(&pm->pm_slbd, slbd, slbd_list);
+ return slbd;
+}
+
+int
+pmap_set_user_slb(pmap_t pm, vaddr_t va)
+{
+ struct cpu_info *ci = curcpu();
+ struct slb_desc *slbd;
+ uint64_t slbe, slbv;
+
+ KASSERT(pm != pmap_kernel());
+
+ slbd = pmap_slbd_lookup(pm, va);
+ if (slbd == NULL) {
+ slbd = pmap_slbd_alloc(pm, va);
+ if (slbd == NULL)
+ return EFAULT;
+ }
+
+ slbe = (slbd->slbd_esid << SLBE_ESID_SHIFT) | SLBE_VALID | 31;
+ slbv = slbd->slbd_vsid << SLBV_VSID_SHIFT;
+
+ ci->ci_kernel_slb[31].slb_slbe = slbe;
+ ci->ci_kernel_slb[31].slb_slbv = slbv;
+
+ isync();
+ slbmte(slbv, slbe);
+ isync();
+
+ return 0;
+}
+
+void
+pmap_unset_user_slb(void)
+{
+ struct cpu_info *ci = curcpu();
+
+ isync();
+ slbie(ci->ci_kernel_slb[31].slb_slbe);
+ isync();
+
+ ci->ci_kernel_slb[31].slb_slbe = 0;
+ ci->ci_kernel_slb[31].slb_slbv = 0;
+}
+
/*
* VP routines, virtual to physical translation information.
* These data structures are based off of the pmap, per process.
@@ -809,7 +879,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
struct pte_desc *pted;
struct vm_page *pg;
int cache = PMAP_CACHE_WB;
- int error;
+ int error = 0;
if (pa & PMAP_NOCACHE)
cache = PMAP_CACHE_CI;
@@ -847,8 +917,9 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
if (pg != NULL)
pmap_enter_pv(pted, pg); /* only managed mem */
- KASSERT(pm == pmap_kernel());
- pmap_kenter_pa(va, pa, prot);
+ pte_insert(pted);
+
+ /* XXX PROT_EXEC */
out:
PMAP_VP_UNLOCK(pm);
@@ -1105,6 +1176,8 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pa)
}
vsid = pmap_va2vsid(pm, va);
+ if (vsid == 0)
+ return 0;
PMAP_HASH_LOCK(s);
pte = pte_lookup(vsid, va);
@@ -1172,7 +1245,7 @@ pmap_set_kernel_slb(int idx, vaddr_t va)
{
struct cpu_info *ci = curcpu();
uint64_t esid, slbe, slbv;
-
+
esid = va >> ADDR_ESID_SHIFT;
kernel_slb_desc[idx].slbd_esid = esid;
slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID | idx;
diff --git a/sys/arch/powerpc64/powerpc64/trap.c b/sys/arch/powerpc64/powerpc64/trap.c
index 9f14d6262f6..ef25cf43dc1 100644
--- a/sys/arch/powerpc64/powerpc64/trap.c
+++ b/sys/arch/powerpc64/powerpc64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.9 2020/06/19 21:24:01 kettenis Exp $ */
+/* $OpenBSD: trap.c,v 1.10 2020/06/21 13:23:59 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -40,6 +40,9 @@ trap(struct trapframe *frame)
struct cpu_info *ci = curcpu();
struct proc *p = curproc;
int type = frame->exc;
+ struct vm_map *map;
+ vaddr_t va;
+ int ftype;
switch (type) {
case EXC_DECR:
@@ -73,6 +76,36 @@ trap(struct trapframe *frame)
return;
#endif
+ case EXC_DSI:
+ map = kernel_map;
+ va = frame->dar;
+ if (curpcb->pcb_onfault && va < VM_MAXUSER_ADDRESS) {
+ map = &p->p_vmspace->vm_map;
+ }
+ if (frame->dsisr & DSISR_STORE)
+ ftype = PROT_READ | PROT_WRITE;
+ else
+ ftype = PROT_READ;
+ KERNEL_LOCK();
+ if (uvm_fault(map, trunc_page(va), 0, ftype) == 0) {
+ KERNEL_UNLOCK();
+ return;
+ }
+ KERNEL_UNLOCK();
+
+ if (curpcb->pcb_onfault)
+ printf("DSI onfault\n");
+
+ printf("dar 0x%lx dsisr 0x%lx\n", frame->dar, frame->dsisr);
+ goto fatal;
+
+ case EXC_DSE:
+ if (curpcb->pcb_onfault)
+ printf("DSE onfault\n");
+
+ printf("dar 0x%lx dsisr 0x%lx\n", frame->dar, frame->dsisr);
+ goto fatal;
+
case EXC_SC|EXC_USER:
intr_enable();
syscall(frame);
@@ -86,6 +119,7 @@ trap(struct trapframe *frame)
break;
default:
+ fatal:
panic("trap type %lx srr1 %lx at %lx lr %lx",
frame->exc, frame->srr1, frame->srr0, frame->lr);
}
diff --git a/sys/arch/powerpc64/powerpc64/trap_subr.S b/sys/arch/powerpc64/powerpc64/trap_subr.S
index b0aa85464f3..2520c982dd2 100644
--- a/sys/arch/powerpc64/powerpc64/trap_subr.S
+++ b/sys/arch/powerpc64/powerpc64/trap_subr.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap_subr.S,v 1.10 2020/06/19 17:29:33 kettenis Exp $ */
+/* $OpenBSD: trap_subr.S,v 1.11 2020/06/21 13:23:59 kettenis Exp $ */
/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */
/*-
@@ -309,13 +309,19 @@ generictrap:
and %r30, %r30, %r31
mtsprg3 %r30
- /* XXX skip this unless we come for userland */
+ /* Test whether we already had PR set */
+ mfsrr1 %r31
+ mtcr %r31
+ bf 17, k_trap /* branch if PSL_PR is false */
+
+u_trap:
mr %r27, %r28
mtsprg2 %r29
bl restore_kernsrs /* enable kernel mapping */
mfsprg2 %r29
mr %r28, %r27
+k_trap:
FRAME_SETUP(CI_TEMPSAVE)
GET_TOCBASE(%r2)
trapagain: