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