vm_machdep.c revision 90361
1/*- 2 * Copyright (c) 1982, 1986 The Regents of the University of California. 3 * Copyright (c) 1989, 1990 William Jolitz 4 * Copyright (c) 1994 John Dyson 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department, and William Jolitz. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 40 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 41 * $FreeBSD: head/sys/ia64/ia64/vm_machdep.c 90361 2002-02-07 20:58:47Z julian $ 42 */ 43/* 44 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 45 * All rights reserved. 46 * 47 * Author: Chris G. Demetriou 48 * 49 * Permission to use, copy, modify and distribute this software and 50 * its documentation is hereby granted, provided that both the copyright 51 * notice and this permission notice appear in all copies of the 52 * software, derivative works or modified versions, and any portions 53 * thereof, and that both notices appear in supporting documentation. 54 * 55 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 56 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 57 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 58 * 59 * Carnegie Mellon requests users of this software to return to 60 * 61 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 62 * School of Computer Science 63 * Carnegie Mellon University 64 * Pittsburgh PA 15213-3890 65 * 66 * any improvements or extensions that they make and grant Carnegie the 67 * rights to redistribute these changes. 68 */ 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/proc.h> 73#include <sys/malloc.h> 74#include <sys/bio.h> 75#include <sys/buf.h> 76#include <sys/vnode.h> 77#include <sys/vmmeter.h> 78#include <sys/kernel.h> 79#include <sys/sysctl.h> 80#include <sys/unistd.h> 81 82#include <machine/clock.h> 83#include <machine/cpu.h> 84#include <machine/fpu.h> 85#include <machine/md_var.h> 86 87#include <vm/vm.h> 88#include <vm/vm_param.h> 89#include <sys/lock.h> 90#include <vm/vm_kern.h> 91#include <vm/vm_page.h> 92#include <vm/vm_map.h> 93#include <vm/vm_extern.h> 94 95#include <sys/user.h> 96 97/* 98 * quick version of vm_fault 99 */ 100int 101vm_fault_quick(v, prot) 102 caddr_t v; 103 int prot; 104{ 105 int r; 106 if (prot & VM_PROT_WRITE) 107 r = subyte(v, fubyte(v)); 108 else 109 r = fubyte(v); 110 return(r); 111} 112 113struct ia64_fdesc { 114 u_int64_t func; 115 u_int64_t gp; 116}; 117 118#define FDESC_FUNC(fn) (((struct ia64_fdesc *) fn)->func) 119#define FDESC_GP(fn) (((struct ia64_fdesc *) fn)->gp) 120 121/* 122 * Finish a fork operation, with process p2 nearly set up. 123 * Copy and update the pcb, set up the stack so that the child 124 * ready to run and return to user mode. 125 */ 126void 127cpu_fork(td1, p2, td2, flags) 128 register struct thread *td1; 129 register struct proc *p2; 130 register struct thread *td2; 131 int flags; 132{ 133 struct proc *p1; 134 struct trapframe *p2tf; 135 u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat; 136 137 if ((flags & RFPROC) == 0) 138 return; 139 140 p1 = td1->td_proc; 141 td2->td_pcb = (struct pcb *) 142 (td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 143 td2->td_md.md_flags = td1->td_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK); 144 145 /* 146 * Copy floating point state from the FP chip to the PCB 147 * if this process has state stored there. 148 */ 149 ia64_fpstate_save(td1, 0); 150 151 /* 152 * Copy pcb and stack from proc p1 to p2. We do this as 153 * cheaply as possible, copying only the active part of the 154 * stack. The stack and pcb need to agree. Make sure that the 155 * new process has FEN disabled. 156 */ 157 bcopy(td1->td_pcb, td2->td_pcb, sizeof(struct pcb)); 158 159 /* 160 * Set the floating point state. 161 */ 162#if 0 163 if ((td2->td_pcb->pcb_fp_control & IEEE_INHERIT) == 0) { 164 td2->td_pcb->pcb_fp_control = 0; 165 td2->td_pcb->pcb_fp.fpr_cr = (FPCR_DYN_NORMAL 166 | FPCR_INVD | FPCR_DZED 167 | FPCR_OVFD | FPCR_INED 168 | FPCR_UNFD); 169 } 170#endif 171 172 /* 173 * Arrange for a non-local goto when the new process 174 * is started, to resume here, returning nonzero from setjmp. 175 */ 176#ifdef DIAGNOSTIC 177 if (td1 != curthread) 178 panic("cpu_fork: curproc"); 179 ia64_fpstate_check(td1); 180#endif 181 182 /* 183 * create the child's kernel stack, from scratch. 184 * 185 * Pick a stack pointer, leaving room for a trapframe; 186 * copy trapframe from parent so return to user mode 187 * will be to right address, with correct registers. 188 */ 189 td2->td_frame = (struct trapframe *)td2->td_pcb - 1; 190 bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); 191 192 /* 193 * Set up return-value registers as fork() libc stub expects. 194 */ 195 p2tf = td2->td_frame; 196 p2tf->tf_r[FRAME_R8] = 0; /* child's pid (linux) */ 197 p2tf->tf_r[FRAME_R9] = 1; /* is child (FreeBSD) */ 198 p2tf->tf_r[FRAME_R10] = 0; /* no error */ 199 200 /* 201 * Turn off RSE for a moment and work out our current 202 * ar.bspstore. This assumes that td1==curthread. Also 203 * flush dirty regs to ensure that the user's stacked 204 * regs are written out to backing store. 205 * 206 * We could cope with td1!=curthread by digging values 207 * out of its PCB but I don't see the point since 208 * current usage never allows it. 209 */ 210 __asm __volatile("mov ar.rsc=0;;"); 211 __asm __volatile("flushrs;;" ::: "memory"); 212 __asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore)); 213 214 p1bs = (u_int64_t *)td1->td_kstack; 215 p2bs = (u_int64_t *)td2->td_kstack; 216 217 /* 218 * Copy enough of td1's backing store to include all 219 * the user's stacked regs. 220 */ 221 bcopy(p1bs, p2bs, td1->td_frame->tf_ndirty); 222 /* 223 * To calculate the ar.rnat for td2, we need to decide 224 * if td1's ar.bspstore has advanced past the place 225 * where the last ar.rnat which covers the user's 226 * saved registers would be placed. If so, we read 227 * that one from memory, otherwise we take td1's 228 * current ar.rnat. 229 */ 230 rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty; 231 rnatloc |= 0x1f8; 232 if (bspstore > rnatloc) 233 rnat = *(u_int64_t *) rnatloc; 234 else 235 __asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat)); 236 237 /* 238 * Switch the RSE back on. 239 */ 240 __asm __volatile("mov ar.rsc=3;;"); 241 242 /* 243 * Setup the child's pcb so that its ar.bspstore 244 * starts just above the region which we copied. This 245 * should work since the child will normally return 246 * straight into exception_restore. 247 */ 248 td2->td_pcb->pcb_bspstore = (u_int64_t)p2bs + td1->td_frame->tf_ndirty; 249 td2->td_pcb->pcb_rnat = rnat; 250 td2->td_pcb->pcb_pfs = 0; 251 252 /* 253 * Arrange for continuation at fork_return(), which 254 * will return to exception_restore(). Note that the 255 * child process doesn't stay in the kernel for long! 256 * 257 * The extra 16 bytes subtracted from sp is part of the ia64 258 * ABI - a function can assume that the 16 bytes above sp are 259 * available as scratch space. 260 */ 261 td2->td_pcb->pcb_sp = (u_int64_t)p2tf - 16; 262 td2->td_pcb->pcb_r4 = (u_int64_t)fork_return; 263 td2->td_pcb->pcb_r5 = FDESC_FUNC(exception_restore); 264 td2->td_pcb->pcb_r6 = (u_int64_t)td2; 265 td2->td_pcb->pcb_b0 = FDESC_FUNC(fork_trampoline); 266} 267 268/* 269 * Intercept the return address from a freshly forked process that has NOT 270 * been scheduled yet. 271 * 272 * This is needed to make kernel threads stay in kernel mode. 273 */ 274void 275cpu_set_fork_handler(td, func, arg) 276 struct thread *td; 277 void (*func) __P((void *)); 278 void *arg; 279{ 280 td->td_pcb->pcb_r4 = (u_int64_t) func; 281 td->td_pcb->pcb_r6 = (u_int64_t) arg; 282} 283 284/* 285 * cpu_exit is called as the last action during exit. 286 * We drop the fp state (if we have it) and switch to a live one. 287 * When the proc is reaped, cpu_wait() will gc the VM state. 288 */ 289void 290cpu_exit(td) 291 register struct thread *td; 292{ 293 294 ia64_fpstate_drop(td); 295} 296 297void 298cpu_wait(p) 299 struct proc *p; 300{ 301} 302 303/* Temporary helper */ 304void 305cpu_throw(void) 306{ 307 308 cpu_switch(); 309 panic("cpu_throw() didn't"); 310} 311 312/* 313 * Dump the machine specific header information at the start of a core dump. 314 */ 315int 316cpu_coredump(td, vp, cred) 317 struct thread *td; 318 struct vnode *vp; 319 struct ucred *cred; 320{ 321 int error; 322 323 error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_proc->p_uarea, 324 ctob(UAREA_PAGES), (off_t)0, 325 UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, td); 326 if (error) 327 return error; 328 error = vn_rdwr(UIO_WRITE, vp, (caddr_t) td->td_kstack, 329 ctob(KSTACK_PAGES), (off_t)0, 330 UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, td); 331 return error; 332} 333 334/* 335 * Map an IO request into kernel virtual address space. 336 * 337 * All requests are (re)mapped into kernel VA space. 338 * Notice that we use b_bufsize for the size of the buffer 339 * to be mapped. b_bcount might be modified by the driver. 340 */ 341void 342vmapbuf(bp) 343 register struct buf *bp; 344{ 345 register caddr_t addr, v, kva; 346 vm_offset_t pa; 347 348 GIANT_REQUIRED; 349 350 if ((bp->b_flags & B_PHYS) == 0) 351 panic("vmapbuf"); 352 353 for (v = bp->b_saveaddr, addr = (caddr_t)trunc_page(bp->b_data); 354 addr < bp->b_data + bp->b_bufsize; 355 addr += PAGE_SIZE, v += PAGE_SIZE) { 356 /* 357 * Do the vm_fault if needed; do the copy-on-write thing 358 * when reading stuff off device into memory. 359 */ 360 vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data, 361 (bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); 362 pa = trunc_page(pmap_kextract((vm_offset_t) addr)); 363 if (pa == 0) 364 panic("vmapbuf: page not present"); 365 vm_page_hold(PHYS_TO_VM_PAGE(pa)); 366 pmap_kenter((vm_offset_t) v, pa); 367 } 368 369 kva = bp->b_saveaddr; 370 bp->b_saveaddr = bp->b_data; 371 bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); 372} 373 374/* 375 * Free the io map PTEs associated with this IO operation. 376 * We also invalidate the TLB entries and restore the original b_addr. 377 */ 378void 379vunmapbuf(bp) 380 register struct buf *bp; 381{ 382 register caddr_t addr; 383 vm_offset_t pa; 384 385 GIANT_REQUIRED; 386 387 if ((bp->b_flags & B_PHYS) == 0) 388 panic("vunmapbuf"); 389 390 for (addr = (caddr_t)trunc_page(bp->b_data); 391 addr < bp->b_data + bp->b_bufsize; 392 addr += PAGE_SIZE) { 393 pa = trunc_page(pmap_kextract((vm_offset_t) addr)); 394 pmap_kremove((vm_offset_t) addr); 395 vm_page_unhold(PHYS_TO_VM_PAGE(pa)); 396 } 397 398 bp->b_data = bp->b_saveaddr; 399} 400 401/* 402 * Force reset the processor by invalidating the entire address space! 403 */ 404void 405cpu_reset() 406{ 407 408 cpu_boot(0); 409} 410 411int 412grow_stack(p, sp) 413 struct proc *p; 414 size_t sp; 415{ 416 int rv; 417 418 rv = vm_map_growstack (p, sp); 419 if (rv != KERN_SUCCESS) 420 return (0); 421 422 return (1); 423} 424 425/* 426 * Software interrupt handler for queued VM system processing. 427 */ 428void 429swi_vm(void *dummy) 430{ 431#if 0 432 if (busdma_swi_pending != 0) 433 busdma_swi(); 434#endif 435} 436 437/* 438 * Tell whether this address is in some physical memory region. 439 * Currently used by the kernel coredump code in order to avoid 440 * dumping the ``ISA memory hole'' which could cause indefinite hangs, 441 * or other unpredictable behaviour. 442 */ 443 444 445int 446is_physical_memory(addr) 447 vm_offset_t addr; 448{ 449 /* 450 * stuff other tests for known memory-mapped devices (PCI?) 451 * here 452 */ 453 454 return 1; 455} 456