1/* $OpenBSD: vm_machdep.c,v 1.18 2023/10/24 13:20:10 claudio Exp $ */ 2/* $NetBSD: vm_machdep.c,v 1.53 2006/08/31 16:49:21 matt Exp $ */ 3 4/* 5 * Copyright (c) 2007 Miodrag Vallat. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice, this permission notice, and the disclaimer below 10 * appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20/*- 21 * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. 22 * Copyright (c) 1982, 1986 The Regents of the University of California. 23 * All rights reserved. 24 * 25 * This code is derived from software contributed to Berkeley by 26 * the Systems Programming Group of the University of Utah Computer 27 * Science Department, and William Jolitz. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 54 */ 55/*- 56 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 57 * Copyright (c) 1989, 1990 William Jolitz 58 * All rights reserved. 59 * 60 * This code is derived from software contributed to Berkeley by 61 * the Systems Programming Group of the University of Utah Computer 62 * Science Department, and William Jolitz. 63 * 64 * Redistribution and use in source and binary forms, with or without 65 * modification, are permitted provided that the following conditions 66 * are met: 67 * 1. Redistributions of source code must retain the above copyright 68 * notice, this list of conditions and the following disclaimer. 69 * 2. Redistributions in binary form must reproduce the above copyright 70 * notice, this list of conditions and the following disclaimer in the 71 * documentation and/or other materials provided with the distribution. 72 * 3. All advertising materials mentioning features or use of this software 73 * must display the following acknowledgement: 74 * This product includes software developed by the University of 75 * California, Berkeley and its contributors. 76 * 4. Neither the name of the University nor the names of its contributors 77 * may be used to endorse or promote products derived from this software 78 * without specific prior written permission. 79 * 80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90 * SUCH DAMAGE. 91 * 92 * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 93 */ 94 95/* 96 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 97 */ 98 99#include <sys/param.h> 100#include <sys/systm.h> 101#include <sys/proc.h> 102#include <sys/malloc.h> 103#include <sys/vnode.h> 104#include <sys/buf.h> 105#include <sys/user.h> 106#include <sys/exec.h> 107#include <sys/ptrace.h> 108#include <sys/signalvar.h> 109 110#include <uvm/uvm_extern.h> 111 112#include <sh/locore.h> 113#include <sh/cpu.h> 114#include <sh/reg.h> 115#include <sh/mmu.h> 116#include <sh/cache.h> 117 118extern void proc_trampoline(void); 119 120/* 121 * Finish a fork operation, with process p2 nearly set up. 122 * Copy and update the pcb and trap frame, making the child ready to run. 123 * 124 * Rig the child's kernel stack so that it will start out in 125 * proc_trampoline() and call 'func' with 'arg' as an argument. 126 * For normal processes this is child_return(), which causes the 127 * child to go directly to user level with an apparent return value 128 * of 0 from fork(), while the parent process returns normally. 129 * For kernel threads this will be a function that never returns. 130 * 131 * An alternate user-level stack or TCB can be requested by passing 132 * a non-NULL value; these are poked into the PCB so they're in 133 * effect at the initial return to userspace. 134 */ 135void 136cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, 137 void (*func)(void *), void *arg) 138{ 139 struct pcb *pcb; 140 struct trapframe *tf; 141 struct switchframe *sf; 142 vaddr_t spbase, fptop; 143#define P1ADDR(x) (SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN)) 144 145 KDASSERT(p1 == curproc || p1 == &proc0); 146 147 bzero(&p2->p_md, sizeof(p2->p_md)); 148 149 /* Copy flags */ 150 p2->p_md.md_flags = p1->p_md.md_flags; 151 152 pcb = NULL; /* XXXGCC: -Wuninitialized */ 153#ifdef SH3 154 /* 155 * Convert frame pointer top to P1. because SH3 can't make 156 * wired TLB entry, context store space accessing must not cause 157 * exception. For SH3, we are 4K page, P3/P1 conversion don't 158 * cause virtual-aliasing. 159 */ 160 if (CPU_IS_SH3) 161 pcb = (struct pcb *)P1ADDR((vaddr_t)&p2->p_addr->u_pcb); 162#endif /* SH3 */ 163#ifdef SH4 164 /* SH4 can make wired entry, no need to convert to P1. */ 165 if (CPU_IS_SH4) 166 pcb = &p2->p_addr->u_pcb; 167#endif /* SH4 */ 168 169 p2->p_md.md_pcb = pcb; 170 fptop = (vaddr_t)pcb + PAGE_SIZE; 171 172 /* set up the kernel stack pointer */ 173 spbase = (vaddr_t)p2->p_addr + PAGE_SIZE; 174#ifdef P1_STACK 175 /* Convert to P1 from P3 */ 176 /* 177 * wbinv u-area to avoid cache-aliasing, since kernel stack 178 * is accessed from P1 instead of P3. 179 */ 180 if (SH_HAS_VIRTUAL_ALIAS) 181 sh_dcache_wbinv_range((vaddr_t)p2->p_addr, USPACE); 182 spbase = P1ADDR(spbase); 183#else /* !P1_STACK */ 184 /* Prepare u-area PTEs */ 185#ifdef SH3 186 if (CPU_IS_SH3) 187 sh3_switch_setup(p2); 188#endif 189#ifdef SH4 190 if (CPU_IS_SH4) 191 sh4_switch_setup(p2); 192#endif 193#endif /* !P1_STACK */ 194 195#ifdef KSTACK_DEBUG 196 /* Fill magic number for tracking */ 197 memset((char *)fptop - PAGE_SIZE + sizeof(struct user), 0x5a, 198 PAGE_SIZE - sizeof(struct user)); 199 memset((char *)spbase, 0xa5, (USPACE - PAGE_SIZE)); 200 memset(&pcb->pcb_sf, 0xb4, sizeof(struct switchframe)); 201#endif /* KSTACK_DEBUG */ 202 203 /* 204 * Copy the user context. 205 */ 206 p2->p_md.md_regs = tf = (struct trapframe *)fptop - 1; 207 memcpy(tf, p1->p_md.md_regs, sizeof(struct trapframe)); 208 209 /* 210 * If specified, give the child a different stack. 211 */ 212 if (stack != NULL) 213 tf->tf_r15 = (int)stack; 214 if (tcb != NULL) 215 tf->tf_gbr = (int)tcb; 216 217 /* Setup switch frame */ 218 sf = &pcb->pcb_sf; 219 sf->sf_r11 = (int)arg; /* proc_trampoline hook func's arg */ 220 sf->sf_r12 = (int)func; /* proc_trampoline hook func */ 221 sf->sf_r15 = spbase + USPACE - PAGE_SIZE;/* current stack pointer */ 222 sf->sf_r7_bank = sf->sf_r15; /* stack top */ 223 sf->sf_r6_bank = (vaddr_t)tf; /* current frame pointer */ 224 /* when switch to me, jump to proc_trampoline */ 225 sf->sf_pr = (int)proc_trampoline; 226 /* 227 * Enable interrupt when switch frame is restored, since 228 * kernel thread begin to run without restoring trapframe. 229 */ 230 sf->sf_sr = PSL_MD | /* kernel mode, interrupt enable */ 231 (IPL_SCHED << 4); 232 233#ifdef SH4 234 if (CPU_IS_SH4) { 235 /* 236 * Propagate floating point registers to the new process 237 * (they are not in the trapframe). 238 */ 239 if (p1 == curproc) 240 fpu_save(&p1->p_md.md_pcb->pcb_fp); 241 bcopy(&p1->p_md.md_pcb->pcb_fp, &pcb->pcb_fp, 242 sizeof(struct fpreg)); 243 } 244#endif 245} 246 247struct kmem_va_mode kv_physwait = { 248 .kv_map = &phys_map, 249 .kv_wait = 1, 250}; 251 252/* 253 * Map an IO request into kernel virtual address space. 254 */ 255void 256vmapbuf(struct buf *bp, vsize_t len) 257{ 258 struct kmem_dyn_mode kd_prefer = { .kd_waitok = 1 }; 259 struct pmap *pm = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); 260 vaddr_t kva, uva; 261 vsize_t size, off; 262 263#ifdef DIAGNOSTIC 264 if ((bp->b_flags & B_PHYS) == 0) 265 panic("vmapbuf"); 266#endif 267 bp->b_saveaddr = bp->b_data; 268 uva = trunc_page((vaddr_t)bp->b_data); 269 off = (vaddr_t)bp->b_data - uva; 270 size = round_page(off + len); 271 272 kd_prefer.kd_prefer = uva; 273 kva = (vaddr_t)km_alloc(size, &kv_physwait, &kp_none, &kd_prefer); 274 bp->b_data = (caddr_t)(kva + off); 275 while (size > 0) { 276 paddr_t pa; 277 278 if (pmap_extract(pm, uva, &pa) == FALSE) 279 panic("vmapbuf: null page frame"); 280 else 281 pmap_kenter_pa(kva, pa, PROT_READ | PROT_WRITE); 282 uva += PAGE_SIZE; 283 kva += PAGE_SIZE; 284 size -= PAGE_SIZE; 285 } 286 pmap_update(pmap_kernel()); 287} 288 289/* 290 * Unmap IO request from the kernel virtual address space. 291 */ 292void 293vunmapbuf(struct buf *bp, vsize_t len) 294{ 295 vaddr_t addr, off; 296 297#ifdef DIAGNOSTIC 298 if ((bp->b_flags & B_PHYS) == 0) 299 panic("vunmapbuf"); 300#endif 301 addr = trunc_page((vaddr_t)bp->b_data); 302 off = (vaddr_t)bp->b_data - addr; 303 len = round_page(off + len); 304 pmap_kremove(addr, len); 305 pmap_update(pmap_kernel()); 306 km_free((void *)addr, len, &kv_physwait, &kp_none); 307 bp->b_data = bp->b_saveaddr; 308 bp->b_saveaddr = NULL; 309} 310