diff options
author | kettenis <kettenis@openbsd.org> | 2020-06-21 13:23:59 +0000 |
---|---|---|
committer | kettenis <kettenis@openbsd.org> | 2020-06-21 13:23:59 +0000 |
commit | 45dd89a788b71518ee353421475f4387cece6926 (patch) | |
tree | 611e4b1f1fff076097625d016f1ed547ea95314e | |
parent | add a commented out entry for wg(4). (diff) | |
download | wireguard-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.h | 5 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/pcb.h | 7 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/pmap.h | 5 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/trap.h | 6 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/genassym.cf | 3 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/locore.S | 3 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/machdep.c | 86 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/pmap.c | 87 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap.c | 36 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap_subr.S | 10 |
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: |