1 /* $OpenBSD: vm_machdep.c,v 1.29 2013/01/16 19:04:43 miod Exp $ */ 2 /* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */ 3 4 /* 5 * Copyright (c) 1996 6 * The President and Fellows of Harvard College. All rights reserved. 7 * Copyright (c) 1992, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This software was developed by the Computer Systems Engineering group 11 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 12 * contributed to Berkeley. 13 * 14 * All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Lawrence Berkeley Laboratory. 18 * This product includes software developed by Harvard University. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. All advertising materials mentioning features or use of this software 29 * must display the following acknowledgement: 30 * This product includes software developed by Harvard University. 31 * This product includes software developed by the University of 32 * California, Berkeley and its contributors. 33 * 4. Neither the name of the University nor the names of its contributors 34 * may be used to endorse or promote products derived from this software 35 * without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * 49 * @(#)vm_machdep.c 8.2 (Berkeley) 9/23/93 50 */ 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/proc.h> 55 #include <sys/user.h> 56 #include <sys/core.h> 57 #include <sys/malloc.h> 58 #include <sys/buf.h> 59 #include <sys/exec.h> 60 #include <sys/vnode.h> 61 #include <sys/signalvar.h> 62 63 #include <uvm/uvm_extern.h> 64 65 #include <machine/cpu.h> 66 #include <machine/frame.h> 67 #include <machine/trap.h> 68 #include <machine/bus.h> 69 70 #include <sparc64/sparc64/cache.h> 71 72 /* 73 * Map a user I/O request into kernel virtual address space. 74 * Note: the pages are already locked by uvm_vslock(), so we 75 * do not need to pass an access_type to pmap_enter(). 76 */ 77 void 78 vmapbuf(bp, len) 79 struct buf *bp; 80 vsize_t len; 81 { 82 struct pmap *upmap, *kpmap; 83 vaddr_t uva; /* User VA (map from) */ 84 vaddr_t kva; /* Kernel VA (new to) */ 85 paddr_t pa; /* physical address */ 86 vsize_t off; 87 88 if ((bp->b_flags & B_PHYS) == 0) 89 panic("vmapbuf"); 90 91 /* 92 * XXX: It might be better to round/trunc to a 93 * segment boundary to avoid VAC problems! 94 */ 95 bp->b_saveaddr = bp->b_data; 96 uva = trunc_page((vaddr_t)bp->b_data); 97 off = (vaddr_t)bp->b_data - uva; 98 len = round_page(off + len); 99 kva = uvm_km_valloc_prefer_wait(kernel_map, len, uva); 100 bp->b_data = (caddr_t)(kva + off); 101 102 upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); 103 kpmap = vm_map_pmap(kernel_map); 104 do { 105 if (pmap_extract(upmap, uva, &pa) == FALSE) 106 panic("vmapbuf: null page frame"); 107 /* Now map the page into kernel space. */ 108 pmap_enter(pmap_kernel(), kva, 109 pa /* | PMAP_NC */, 110 VM_PROT_READ|VM_PROT_WRITE, 111 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 112 113 uva += PAGE_SIZE; 114 kva += PAGE_SIZE; 115 len -= PAGE_SIZE; 116 } while (len); 117 pmap_update(pmap_kernel()); 118 } 119 120 /* 121 * Unmap a previously-mapped user I/O request. 122 */ 123 void 124 vunmapbuf(bp, len) 125 struct buf *bp; 126 vsize_t len; 127 { 128 vaddr_t kva; 129 vsize_t off; 130 131 if ((bp->b_flags & B_PHYS) == 0) 132 panic("vunmapbuf"); 133 134 kva = trunc_page((vaddr_t)bp->b_data); 135 off = (vaddr_t)bp->b_data - kva; 136 len = round_page(off + len); 137 138 pmap_remove(pmap_kernel(), kva, kva + len); 139 pmap_update(pmap_kernel()); 140 uvm_km_free_wakeup(kernel_map, kva, len); 141 bp->b_data = bp->b_saveaddr; 142 bp->b_saveaddr = NULL; 143 } 144 145 146 /* 147 * The offset of the topmost frame in the kernel stack. 148 */ 149 #define TOPFRAMEOFF (USPACE-sizeof(struct trapframe)-CC64FSZ) 150 #define STACK_OFFSET BIAS 151 152 #ifdef DEBUG 153 char cpu_forkname[] = "cpu_fork()"; 154 #endif 155 156 /* 157 * Finish a fork operation, with process p2 nearly set up. 158 * Copy and update the pcb and trap frame, making the child ready to run. 159 * 160 * Rig the child's kernel stack so that it will start out in 161 * proc_trampoline() and call child_return() with p2 as an 162 * argument. This causes the newly-created child process to go 163 * directly to user level with an apparent return value of 0 from 164 * fork(), while the parent process returns normally. 165 * 166 * p1 is the process being forked; if p1 == &proc0, we are creating 167 * a kernel thread, and the return path and argument are specified with 168 * `func' and `arg'. 169 * 170 * If an alternate user-level stack is requested (with non-zero values 171 * in both the stack and stacksize args), set up the user stack pointer 172 * accordingly. 173 */ 174 void 175 cpu_fork(p1, p2, stack, stacksize, func, arg) 176 struct proc *p1, *p2; 177 void *stack; 178 size_t stacksize; 179 void (*func)(void *); 180 void *arg; 181 { 182 struct pcb *opcb = &p1->p_addr->u_pcb; 183 struct pcb *npcb = &p2->p_addr->u_pcb; 184 struct trapframe *tf2; 185 struct rwindow *rp; 186 extern struct proc proc0; 187 188 /* 189 * Save all user registers to p1's stack or, in the case of 190 * user registers and invalid stack pointers, to opcb. 191 * We then copy the whole pcb to p2; when switch() selects p2 192 * to run, it will run at the `proc_trampoline' stub, rather 193 * than returning at the copying code below. 194 * 195 * If process p1 has an FPU state, we must copy it. If it is 196 * the FPU user, we must save the FPU state first. 197 */ 198 199 #ifdef NOTDEF_DEBUG 200 printf("cpu_fork()\n"); 201 #endif 202 if (p1 == curproc) { 203 write_user_windows(); 204 205 /* 206 * We're in the kernel, so we don't really care about 207 * %ccr or %asi. We do want to duplicate %pstate and %cwp. 208 */ 209 opcb->pcb_pstate = getpstate(); 210 opcb->pcb_cwp = getcwp(); 211 } 212 #ifdef DIAGNOSTIC 213 else if (p1 != &proc0) 214 panic("cpu_fork: curproc"); 215 #endif 216 #ifdef DEBUG 217 /* prevent us from having NULL lastcall */ 218 opcb->lastcall = cpu_forkname; 219 #else 220 opcb->lastcall = NULL; 221 #endif 222 bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb)); 223 if (p1->p_md.md_fpstate) { 224 fpusave_proc(p1, 1); 225 p2->p_md.md_fpstate = malloc(sizeof(struct fpstate64), 226 M_SUBPROC, M_WAITOK); 227 bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate, 228 sizeof(struct fpstate64)); 229 } else 230 p2->p_md.md_fpstate = NULL; 231 232 /* 233 * Setup (kernel) stack frame that will by-pass the child 234 * out of the kernel. (The trap frame invariably resides at 235 * the tippity-top of the u. area.) 236 */ 237 tf2 = p2->p_md.md_tf = (struct trapframe *) 238 ((long)npcb + USPACE - sizeof(*tf2)); 239 240 /* Copy parent's trapframe */ 241 *tf2 = *(struct trapframe *)((long)opcb + USPACE - sizeof(*tf2)); 242 243 /* 244 * If specified, give the child a different stack, offset and 245 * with space reserved for the frame, and zero the frame pointer. 246 */ 247 if (stack != NULL) { 248 tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize 249 - (BIAS + CC64FSZ); 250 tf2->tf_in[6] = 0; 251 } 252 253 /* Duplicate efforts of syscall(), but slightly differently */ 254 if (tf2->tf_global[1] & SYSCALL_G2RFLAG) { 255 /* jmp %g2 (or %g7, deprecated) on success */ 256 tf2->tf_npc = tf2->tf_global[2]; 257 } else { 258 /* 259 * old system call convention: clear C on success 260 * note: proc_trampoline() sets a fresh psr when 261 * returning to user mode. 262 */ 263 /*tf2->tf_psr &= ~PSR_C; -* success */ 264 } 265 266 /* Set return values in child mode */ 267 tf2->tf_out[0] = 0; 268 tf2->tf_out[1] = 1; 269 270 /* Skip trap instruction. */ 271 tf2->tf_pc = tf2->tf_npc; 272 tf2->tf_npc += 4; 273 274 /* Construct kernel frame to return to in cpu_switch() */ 275 rp = (struct rwindow *)((u_long)npcb + TOPFRAMEOFF); 276 *rp = *(struct rwindow *)((u_long)opcb + TOPFRAMEOFF); 277 rp->rw_local[0] = (long)func; /* Function to call */ 278 rp->rw_local[1] = (long)arg; /* and its argument */ 279 280 npcb->pcb_pc = (long)proc_trampoline - 8; 281 npcb->pcb_sp = (long)rp - STACK_OFFSET; 282 283 /* Need to create a %tstate if we're forking from proc0. */ 284 if (p1 == &proc0) 285 tf2->tf_tstate = 286 ((u_int64_t)ASI_PRIMARY_NO_FAULT << TSTATE_ASI_SHIFT) | 287 ((PSTATE_USER) << TSTATE_PSTATE_SHIFT); 288 else 289 /* Clear condition codes and disable FPU. */ 290 tf2->tf_tstate &= 291 ~((PSTATE_PEF << TSTATE_PSTATE_SHIFT) | TSTATE_CCR); 292 293 #ifdef NOTDEF_DEBUG 294 printf("cpu_fork: Copying over trapframe: otf=%p ntf=%p sp=%p opcb=%p npcb=%p\n", 295 (struct trapframe *)((char *)opcb + USPACE - sizeof(*tf2)), tf2, rp, opcb, npcb); 296 printf("cpu_fork: tstate=%lx pc=%lx npc=%lx rsp=%lx\n", 297 (long)tf2->tf_tstate, (long)tf2->tf_pc, (long)tf2->tf_npc, 298 (long)(tf2->tf_out[6])); 299 Debugger(); 300 #endif 301 } 302 303 /* 304 * These are the "function" entry points in locore.s to handle IPI's. 305 */ 306 void ipi_save_fpstate(void); 307 void ipi_drop_fpstate(void); 308 309 void 310 fpusave_cpu(struct cpu_info *ci, int save) 311 { 312 struct proc *p; 313 314 KDASSERT(ci == curcpu()); 315 316 p = ci->ci_fpproc; 317 if (p == NULL) 318 return; 319 320 if (save) 321 savefpstate(p->p_md.md_fpstate); 322 else 323 clearfpstate(); 324 325 ci->ci_fpproc = NULL; 326 } 327 328 void 329 fpusave_proc(struct proc *p, int save) 330 { 331 struct cpu_info *ci = curcpu(); 332 333 #ifdef MULTIPROCESSOR 334 if (p == ci->ci_fpproc) { 335 u_int64_t s = intr_disable(); 336 fpusave_cpu(ci, save); 337 intr_restore(s); 338 return; 339 } 340 341 for (ci = cpus; ci != NULL; ci = ci->ci_next) { 342 if (ci == curcpu()) 343 continue; 344 if (ci->ci_fpproc != p) 345 continue; 346 sparc64_send_ipi(ci->ci_itid, 347 save ? ipi_save_fpstate : ipi_drop_fpstate, (vaddr_t)p, 0); 348 while(ci->ci_fpproc == p) 349 sparc_membar(Sync); 350 break; 351 } 352 #else 353 if (p == ci->ci_fpproc) 354 fpusave_cpu(ci, save); 355 #endif 356 } 357 358 /* 359 * cpu_exit is called as the last action during exit. 360 * 361 * We clean up a little and then call sched_exit() with the old proc 362 * as an argument. sched_exit() schedules the old vmspace and stack 363 * to be freed, then selects a new process to run. 364 */ 365 void 366 cpu_exit(struct proc *p) 367 { 368 if (p->p_md.md_fpstate != NULL) { 369 fpusave_proc(p, 0); 370 free(p->p_md.md_fpstate, M_SUBPROC); 371 } 372 373 pmap_deactivate(p); 374 sched_exit(p); 375 } 376 377 /* 378 * cpu_coredump is called to write a core dump header. 379 * (should this be defined elsewhere? machdep.c?) 380 */ 381 int 382 cpu_coredump(p, vp, cred, chdr) 383 struct proc *p; 384 struct vnode *vp; 385 struct ucred *cred; 386 struct core *chdr; 387 { 388 int error; 389 struct md_coredump md_core; 390 struct coreseg cseg; 391 392 CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); 393 chdr->c_hdrsize = ALIGN(sizeof(*chdr)); 394 chdr->c_seghdrsize = ALIGN(sizeof(cseg)); 395 chdr->c_cpusize = sizeof(md_core); 396 397 md_core.md_tf = *p->p_md.md_tf; 398 md_core.md_wcookie = p->p_addr->u_pcb.pcb_wcookie; 399 if (p->p_md.md_fpstate) { 400 fpusave_proc(p, 1); 401 md_core.md_fpstate = *p->p_md.md_fpstate; 402 } else 403 bzero((caddr_t)&md_core.md_fpstate, 404 sizeof(md_core.md_fpstate)); 405 406 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); 407 cseg.c_addr = 0; 408 cseg.c_size = chdr->c_cpusize; 409 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, 410 (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_UNIT, cred, NULL, p); 411 if (error) 412 return error; 413 414 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core), 415 (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, 416 IO_UNIT, cred, NULL, p); 417 if (!error) 418 chdr->c_nseg++; 419 420 return error; 421 } 422 423