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