1 /* $NetBSD: vm_machdep.c,v 1.46 2002/09/25 22:21:23 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved. 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 62 #include <uvm/uvm_extern.h> 63 64 #include <machine/cpu.h> 65 #include <machine/frame.h> 66 #include <machine/trap.h> 67 #include <machine/bus.h> 68 69 #include <sparc64/sparc64/cache.h> 70 71 /* 72 * Move pages from one kernel virtual address to another. 73 */ 74 void 75 pagemove(from, to, size) 76 register caddr_t from, to; 77 size_t size; 78 { 79 paddr_t pa; 80 81 if (size & PGOFSET || (long)from & PGOFSET || (long)to & PGOFSET) 82 panic("pagemove 1"); 83 84 while (size > 0) { 85 if (pmap_extract(pmap_kernel(), (vaddr_t)from, &pa) == FALSE) 86 panic("pagemove 2"); 87 pmap_kremove((vaddr_t)from, PAGE_SIZE); 88 pmap_kenter_pa((vaddr_t)to, pa, VM_PROT_READ | VM_PROT_WRITE); 89 from += PAGE_SIZE; 90 to += PAGE_SIZE; 91 size -= PAGE_SIZE; 92 } 93 pmap_update(pmap_kernel()); 94 } 95 96 /* 97 * Map a user I/O request into kernel virtual address space. 98 * Note: the pages are already locked by uvm_vslock(), so we 99 * do not need to pass an access_type to pmap_enter(). 100 */ 101 void 102 vmapbuf(bp, len) 103 struct buf *bp; 104 vsize_t len; 105 { 106 struct pmap *upmap, *kpmap; 107 vaddr_t uva; /* User VA (map from) */ 108 vaddr_t kva; /* Kernel VA (new to) */ 109 paddr_t pa; /* physical address */ 110 vsize_t off; 111 112 if ((bp->b_flags & B_PHYS) == 0) 113 panic("vmapbuf"); 114 115 bp->b_saveaddr = bp->b_data; 116 uva = trunc_page((vaddr_t)bp->b_data); 117 off = (vaddr_t)bp->b_data - uva; 118 len = round_page(off + len); 119 kva = uvm_km_valloc_wait(kernel_map, len); 120 bp->b_data = (caddr_t)(kva + off); 121 122 upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); 123 kpmap = vm_map_pmap(kernel_map); 124 do { 125 if (pmap_extract(upmap, uva, &pa) == FALSE) 126 panic("vmapbuf: null page frame"); 127 /* Now map the page into kernel space. */ 128 pmap_kenter_pa(kva, pa, VM_PROT_READ | VM_PROT_WRITE); 129 130 uva += PAGE_SIZE; 131 kva += PAGE_SIZE; 132 len -= PAGE_SIZE; 133 } while (len); 134 pmap_update(pmap_kernel()); 135 } 136 137 /* 138 * Unmap a previously-mapped user I/O request. 139 */ 140 void 141 vunmapbuf(bp, len) 142 struct buf *bp; 143 vsize_t len; 144 { 145 vaddr_t kva; 146 vsize_t off; 147 148 if ((bp->b_flags & B_PHYS) == 0) 149 panic("vunmapbuf"); 150 151 kva = trunc_page((vaddr_t)bp->b_data); 152 off = (vaddr_t)bp->b_data - kva; 153 len = round_page(off + len); 154 pmap_kremove(kva, len); 155 uvm_km_free_wakeup(kernel_map, kva, len); 156 bp->b_data = bp->b_saveaddr; 157 bp->b_saveaddr = NULL; 158 } 159 160 161 /* 162 * The offset of the topmost frame in the kernel stack. 163 */ 164 #ifdef __arch64__ 165 #define TOPFRAMEOFF (USPACE-sizeof(struct trapframe)-CC64FSZ) 166 #define STACK_OFFSET BIAS 167 #else 168 #undef trapframe 169 #define trapframe trapframe64 170 #undef rwindow 171 #define rwindow rwindow32 172 #define TOPFRAMEOFF (USPACE-sizeof(struct trapframe)-CC64FSZ) 173 #define STACK_OFFSET 0 174 #endif 175 176 #ifdef DEBUG 177 char cpu_forkname[] = "cpu_fork()"; 178 #endif 179 180 /* 181 * Finish a fork operation, with process p2 nearly set up. 182 * Copy and update the pcb and trap frame, making the child ready to run. 183 * 184 * Rig the child's kernel stack so that it will start out in 185 * proc_trampoline() and call child_return() with p2 as an 186 * argument. This causes the newly-created child process to go 187 * directly to user level with an apparent return value of 0 from 188 * fork(), while the parent process returns normally. 189 * 190 * p1 is the process being forked; if p1 == &proc0, we are creating 191 * a kernel thread, and the return path and argument are specified with 192 * `func' and `arg'. 193 * 194 * If an alternate user-level stack is requested (with non-zero values 195 * in both the stack and stacksize args), set up the user stack pointer 196 * accordingly. 197 */ 198 void 199 cpu_fork(p1, p2, stack, stacksize, func, arg) 200 register struct proc *p1, *p2; 201 void *stack; 202 size_t stacksize; 203 void (*func) __P((void *)); 204 void *arg; 205 { 206 struct pcb *opcb = &p1->p_addr->u_pcb; 207 struct pcb *npcb = &p2->p_addr->u_pcb; 208 struct trapframe *tf2; 209 struct rwindow *rp; 210 extern struct proc proc0; 211 212 /* 213 * Save all user registers to p1's stack or, in the case of 214 * user registers and invalid stack pointers, to opcb. 215 * We then copy the whole pcb to p2; when switch() selects p2 216 * to run, it will run at the `proc_trampoline' stub, rather 217 * than returning at the copying code below. 218 * 219 * If process p1 has an FPU state, we must copy it. If it is 220 * the FPU user, we must save the FPU state first. 221 */ 222 223 if (p1 == curproc) { 224 write_user_windows(); 225 226 /* 227 * We're in the kernel, so we don't really care about 228 * %ccr or %asi. We do want to duplicate %pstate and %cwp. 229 */ 230 opcb->pcb_pstate = getpstate(); 231 opcb->pcb_cwp = getcwp(); 232 } 233 #ifdef DIAGNOSTIC 234 else if (p1 != &proc0) 235 panic("cpu_fork: curproc"); 236 #endif 237 #ifdef DEBUG 238 /* prevent us from having NULL lastcall */ 239 opcb->lastcall = cpu_forkname; 240 #else 241 opcb->lastcall = NULL; 242 #endif 243 bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb)); 244 if (p1->p_md.md_fpstate) { 245 if (p1 == fpproc) { 246 savefpstate(p1->p_md.md_fpstate); 247 fpproc = NULL; 248 } 249 p2->p_md.md_fpstate = malloc(sizeof(struct fpstate64), 250 M_SUBPROC, M_WAITOK); 251 bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate, 252 sizeof(struct fpstate64)); 253 } else 254 p2->p_md.md_fpstate = NULL; 255 256 if (p1->p_flag & P_32) 257 p2->p_flag |= P_32; 258 259 /* 260 * Setup (kernel) stack frame that will by-pass the child 261 * out of the kernel. (The trap frame invariably resides at 262 * the tippity-top of the u. area.) 263 */ 264 tf2 = p2->p_md.md_tf = (struct trapframe *) 265 ((long)npcb + USPACE - sizeof(*tf2)); 266 267 /* Copy parent's trapframe */ 268 *tf2 = *(struct trapframe *)((long)opcb + USPACE - sizeof(*tf2)); 269 270 /* 271 * If specified, give the child a different stack. 272 */ 273 if (stack != NULL) 274 tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize; 275 276 /* Duplicate efforts of syscall(), but slightly differently */ 277 if (tf2->tf_global[1] & SYSCALL_G7RFLAG) { 278 /* jmp %g2 (or %g7, deprecated) on success */ 279 tf2->tf_npc = tf2->tf_global[7]; 280 } else if (tf2->tf_global[1] & SYSCALL_G2RFLAG) { 281 /* jmp %g2 (or %g7, deprecated) on success */ 282 tf2->tf_npc = tf2->tf_global[2]; 283 } else { 284 /* 285 * old system call convention: clear C on success 286 * note: proc_trampoline() sets a fresh psr when 287 * returning to user mode. 288 */ 289 /*tf2->tf_psr &= ~PSR_C; -* success */ 290 } 291 292 /* Set return values in child mode */ 293 tf2->tf_out[0] = 0; 294 tf2->tf_out[1] = 1; 295 296 /* Construct kernel frame to return to in cpu_switch() */ 297 rp = (struct rwindow *)((u_long)npcb + TOPFRAMEOFF); 298 *rp = *(struct rwindow *)((u_long)opcb + TOPFRAMEOFF); 299 rp->rw_local[0] = (long)func; /* Function to call */ 300 rp->rw_local[1] = (long)arg; /* and its argument */ 301 302 npcb->pcb_pc = (long)proc_trampoline - 8; 303 npcb->pcb_sp = (long)rp - STACK_OFFSET; 304 305 /* Need to create a %tstate if we're forking from proc0 */ 306 if (p1 == &proc0) 307 tf2->tf_tstate = (ASI_PRIMARY_NO_FAULT<<TSTATE_ASI_SHIFT) | 308 ((PSTATE_USER)<<TSTATE_PSTATE_SHIFT); 309 else 310 tf2->tf_tstate &= ~(PSTATE_PEF<<TSTATE_PSTATE_SHIFT); 311 312 #ifdef NOTDEF_DEBUG 313 printf("cpu_fork: Copying over trapframe: otf=%p ntf=%p sp=%p opcb=%p npcb=%p\n", 314 (struct trapframe *)((int)opcb + USPACE - sizeof(*tf2)), tf2, rp, opcb, npcb); 315 printf("cpu_fork: tstate=%x:%x pc=%x:%x npc=%x:%x rsp=%x\n", 316 (long)(tf2->tf_tstate>>32), (long)tf2->tf_tstate, 317 (long)(tf2->tf_pc>>32), (long)tf2->tf_pc, 318 (long)(tf2->tf_npc>>32), (long)tf2->tf_npc, 319 (long)(tf2->tf_out[6])); 320 Debugger(); 321 #endif 322 } 323 324 /* 325 * cpu_exit is called as the last action during exit. 326 * 327 * We clean up a little and then call switchexit() with the old proc 328 * as an argument. switchexit() switches to the idle context, schedules 329 * the old vmspace and stack to be freed, then selects a new process to 330 * run. 331 */ 332 void 333 cpu_exit(p) 334 struct proc *p; 335 { 336 register struct fpstate64 *fs; 337 338 if ((fs = p->p_md.md_fpstate) != NULL) { 339 if (p == fpproc) { 340 savefpstate(fs); 341 fpproc = NULL; 342 } 343 free((void *)fs, M_SUBPROC); 344 } 345 switchexit(p); 346 /* NOTREACHED */ 347 } 348 349 /* 350 * cpu_coredump is called to write a core dump header. 351 * (should this be defined elsewhere? machdep.c?) 352 */ 353 int 354 cpu_coredump(p, vp, cred, chdr) 355 struct proc *p; 356 struct vnode *vp; 357 struct ucred *cred; 358 struct core *chdr; 359 { 360 int error; 361 struct md_coredump md_core; 362 struct coreseg cseg; 363 364 CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); 365 chdr->c_hdrsize = ALIGN(sizeof(*chdr)); 366 chdr->c_seghdrsize = ALIGN(sizeof(cseg)); 367 chdr->c_cpusize = sizeof(md_core); 368 369 /* Copy important fields over. */ 370 md_core.md_tf.tf_tstate = p->p_md.md_tf->tf_tstate; 371 md_core.md_tf.tf_pc = p->p_md.md_tf->tf_pc; 372 md_core.md_tf.tf_npc = p->p_md.md_tf->tf_npc; 373 md_core.md_tf.tf_y = p->p_md.md_tf->tf_y; 374 md_core.md_tf.tf_tt = p->p_md.md_tf->tf_tt; 375 md_core.md_tf.tf_pil = p->p_md.md_tf->tf_pil; 376 md_core.md_tf.tf_oldpil = p->p_md.md_tf->tf_oldpil; 377 378 md_core.md_tf.tf_global[0] = p->p_md.md_tf->tf_global[0]; 379 md_core.md_tf.tf_global[1] = p->p_md.md_tf->tf_global[1]; 380 md_core.md_tf.tf_global[2] = p->p_md.md_tf->tf_global[2]; 381 md_core.md_tf.tf_global[3] = p->p_md.md_tf->tf_global[3]; 382 md_core.md_tf.tf_global[4] = p->p_md.md_tf->tf_global[4]; 383 md_core.md_tf.tf_global[5] = p->p_md.md_tf->tf_global[5]; 384 md_core.md_tf.tf_global[6] = p->p_md.md_tf->tf_global[6]; 385 md_core.md_tf.tf_global[7] = p->p_md.md_tf->tf_global[7]; 386 387 md_core.md_tf.tf_out[0] = p->p_md.md_tf->tf_out[0]; 388 md_core.md_tf.tf_out[1] = p->p_md.md_tf->tf_out[1]; 389 md_core.md_tf.tf_out[2] = p->p_md.md_tf->tf_out[2]; 390 md_core.md_tf.tf_out[3] = p->p_md.md_tf->tf_out[3]; 391 md_core.md_tf.tf_out[4] = p->p_md.md_tf->tf_out[4]; 392 md_core.md_tf.tf_out[5] = p->p_md.md_tf->tf_out[5]; 393 md_core.md_tf.tf_out[6] = p->p_md.md_tf->tf_out[6]; 394 md_core.md_tf.tf_out[7] = p->p_md.md_tf->tf_out[7]; 395 396 #ifdef DEBUG 397 md_core.md_tf.tf_local[0] = p->p_md.md_tf->tf_local[0]; 398 md_core.md_tf.tf_local[1] = p->p_md.md_tf->tf_local[1]; 399 md_core.md_tf.tf_local[2] = p->p_md.md_tf->tf_local[2]; 400 md_core.md_tf.tf_local[3] = p->p_md.md_tf->tf_local[3]; 401 md_core.md_tf.tf_local[4] = p->p_md.md_tf->tf_local[4]; 402 md_core.md_tf.tf_local[5] = p->p_md.md_tf->tf_local[5]; 403 md_core.md_tf.tf_local[6] = p->p_md.md_tf->tf_local[6]; 404 md_core.md_tf.tf_local[7] = p->p_md.md_tf->tf_local[7]; 405 406 md_core.md_tf.tf_in[0] = p->p_md.md_tf->tf_in[0]; 407 md_core.md_tf.tf_in[1] = p->p_md.md_tf->tf_in[1]; 408 md_core.md_tf.tf_in[2] = p->p_md.md_tf->tf_in[2]; 409 md_core.md_tf.tf_in[3] = p->p_md.md_tf->tf_in[3]; 410 md_core.md_tf.tf_in[4] = p->p_md.md_tf->tf_in[4]; 411 md_core.md_tf.tf_in[5] = p->p_md.md_tf->tf_in[5]; 412 md_core.md_tf.tf_in[6] = p->p_md.md_tf->tf_in[6]; 413 md_core.md_tf.tf_in[7] = p->p_md.md_tf->tf_in[7]; 414 #endif 415 if (p->p_md.md_fpstate) { 416 if (p == fpproc) { 417 savefpstate(p->p_md.md_fpstate); 418 fpproc = NULL; 419 } 420 md_core.md_fpstate = *p->p_md.md_fpstate; 421 } else 422 bzero((caddr_t)&md_core.md_fpstate, 423 sizeof(md_core.md_fpstate)); 424 425 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); 426 cseg.c_addr = 0; 427 cseg.c_size = chdr->c_cpusize; 428 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, 429 (off_t)chdr->c_hdrsize, UIO_SYSSPACE, 430 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 431 if (error) 432 return error; 433 434 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core), 435 (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, 436 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 437 if (!error) 438 chdr->c_nseg++; 439 440 return error; 441 } 442 443