vm_machdep.c revision 111028
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 111028 2003-02-17 05:14:26Z jeff $ 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#include <i386/include/psl.h> 98 99void 100cpu_thread_exit(struct thread *td) 101{ 102} 103 104void 105cpu_thread_clean(struct thread *td) 106{ 107} 108 109void 110cpu_thread_setup(struct thread *td) 111{ 112} 113 114void 115cpu_set_upcall(struct thread *td, void *pcb) 116{ 117} 118 119void 120cpu_set_upcall_kse(struct thread *td, struct kse_upcall *ku) 121{ 122} 123 124/* 125 * Finish a fork operation, with process p2 nearly set up. 126 * Copy and update the pcb, set up the stack so that the child 127 * ready to run and return to user mode. 128 */ 129void 130cpu_fork(td1, p2, td2, flags) 131 register struct thread *td1; 132 register struct proc *p2; 133 register struct thread *td2; 134 int flags; 135{ 136 struct proc *p1; 137 struct trapframe *p2tf; 138 u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat; 139 140 KASSERT(td1 == curthread || td1 == &thread0, 141 ("cpu_fork: p1 not curproc and not proc0")); 142 143 if ((flags & RFPROC) == 0) 144 return; 145 146 p1 = td1->td_proc; 147 td2->td_pcb = (struct pcb *) 148 (td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 149 td2->td_md.md_flags = td1->td_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK); 150 151 /* 152 * Copy floating point state from the FP chip to the PCB 153 * if this process has state stored there. 154 */ 155 ia64_fpstate_save(td1, 0); 156 157 /* 158 * Copy pcb and stack from proc p1 to p2. We do this as 159 * cheaply as possible, copying only the active part of the 160 * stack. The stack and pcb need to agree. Make sure that the 161 * new process has FEN disabled. 162 */ 163 bcopy(td1->td_pcb, td2->td_pcb, sizeof(struct pcb)); 164 165 /* 166 * Set the floating point state. 167 */ 168#if 0 169 if ((td2->td_pcb->pcb_fp_control & IEEE_INHERIT) == 0) { 170 td2->td_pcb->pcb_fp_control = 0; 171 td2->td_pcb->pcb_fp.fpr_cr = (FPCR_DYN_NORMAL 172 | FPCR_INVD | FPCR_DZED 173 | FPCR_OVFD | FPCR_INED 174 | FPCR_UNFD); 175 } 176#endif 177 178 /* 179 * Arrange for a non-local goto when the new process 180 * is started, to resume here, returning nonzero from setjmp. 181 */ 182#ifdef DIAGNOSTIC 183 if (td1 == curthread) 184 ia64_fpstate_check(td1); 185#endif 186 187 /* 188 * create the child's kernel stack, from scratch. 189 * 190 * Pick a stack pointer, leaving room for a trapframe; 191 * copy trapframe from parent so return to user mode 192 * will be to right address, with correct registers. Clear the 193 * high-fp enable for the new process so that it is forced to 194 * load its state from the pcb. 195 */ 196 td2->td_frame = (struct trapframe *)td2->td_pcb - 1; 197 bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); 198 td2->td_frame->tf_cr_ipsr |= IA64_PSR_DFH; 199 200 /* 201 * Set up return-value registers as fork() libc stub expects. 202 */ 203 p2tf = td2->td_frame; 204 if (p2tf->tf_cr_ipsr & IA64_PSR_IS) { 205 p2tf->tf_r[FRAME_R8] = 0; /* child returns zero (eax) */ 206 p2tf->tf_r[FRAME_R10] = 1; /* is child (edx) */ 207 td2->td_pcb->pcb_ar_eflag &= ~PSL_C; /* no error */ 208 } else { 209 p2tf->tf_r[FRAME_R8] = 0; /* child's pid (linux) */ 210 p2tf->tf_r[FRAME_R9] = 1; /* is child (FreeBSD) */ 211 p2tf->tf_r[FRAME_R10] = 0; /* no error */ 212 } 213 214 /* 215 * Turn off RSE for a moment and work out our current 216 * ar.bspstore. This assumes that td1==curthread. Also 217 * flush dirty regs to ensure that the user's stacked 218 * regs are written out to backing store. 219 * 220 * We could cope with td1!=curthread by digging values 221 * out of its PCB but I don't see the point since 222 * current usage only allows &thread0 when creating kernel 223 * threads and &thread0 doesn't have any dirty regs. 224 */ 225 226 p1bs = (u_int64_t *)td1->td_kstack; 227 p2bs = (u_int64_t *)td2->td_kstack; 228 229 if (td1 == curthread) { 230 __asm __volatile("mov ar.rsc=0;;"); 231 __asm __volatile("flushrs;;" ::: "memory"); 232 __asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore)); 233 } else { 234 bspstore = (u_int64_t) p1bs; 235 } 236 237 /* 238 * Copy enough of td1's backing store to include all 239 * the user's stacked regs. 240 */ 241 bcopy(p1bs, p2bs, td1->td_frame->tf_ndirty); 242 /* 243 * To calculate the ar.rnat for td2, we need to decide 244 * if td1's ar.bspstore has advanced past the place 245 * where the last ar.rnat which covers the user's 246 * saved registers would be placed. If so, we read 247 * that one from memory, otherwise we take td1's 248 * current ar.rnat. If we are simply spawning a new kthread 249 * from &thread0 we don't care about ar.rnat. 250 */ 251 if (td1 == curthread) { 252 rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty; 253 rnatloc |= 0x1f8; 254 if (bspstore > rnatloc) 255 rnat = *(u_int64_t *) rnatloc; 256 else 257 __asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat)); 258 259 /* 260 * Switch the RSE back on. 261 */ 262 __asm __volatile("mov ar.rsc=3;;"); 263 } else { 264 rnat = 0; 265 } 266 267 /* 268 * Setup the child's pcb so that its ar.bspstore 269 * starts just above the region which we copied. This 270 * should work since the child will normally return 271 * straight into exception_restore. Also initialise its 272 * pmap to the containing proc's vmspace. 273 */ 274 td2->td_pcb->pcb_ar_bsp = (u_int64_t)p2bs + td1->td_frame->tf_ndirty; 275 td2->td_pcb->pcb_ar_rnat = rnat; 276 td2->td_pcb->pcb_ar_pfs = 0; 277 td2->td_pcb->pcb_current_pmap = (u_int64_t) 278 vmspace_pmap(td2->td_proc->p_vmspace); 279 280 /* 281 * Arrange for continuation at fork_return(), which 282 * will return to exception_restore(). Note that the 283 * child process doesn't stay in the kernel for long! 284 * 285 * The extra 16 bytes subtracted from sp is part of the ia64 286 * ABI - a function can assume that the 16 bytes above sp are 287 * available as scratch space. 288 */ 289 td2->td_pcb->pcb_sp = (u_int64_t)p2tf - 16; 290 td2->td_pcb->pcb_r[PCB_R4] = (u_int64_t)fork_return; 291 td2->td_pcb->pcb_r[PCB_R5] = FDESC_FUNC(exception_restore); 292 td2->td_pcb->pcb_r[PCB_R6] = (u_int64_t)td2; 293 td2->td_pcb->pcb_rp = FDESC_FUNC(fork_trampoline); 294} 295 296/* 297 * Intercept the return address from a freshly forked process that has NOT 298 * been scheduled yet. 299 * 300 * This is needed to make kernel threads stay in kernel mode. 301 */ 302void 303cpu_set_fork_handler(td, func, arg) 304 struct thread *td; 305 void (*func)(void *); 306 void *arg; 307{ 308 td->td_pcb->pcb_r[PCB_R4] = (u_int64_t) func; 309 td->td_pcb->pcb_r[PCB_R6] = (u_int64_t) arg; 310} 311 312/* 313 * cpu_exit is called as the last action during exit. 314 * We drop the fp state (if we have it) and switch to a live one. 315 * When the proc is reaped, cpu_wait() will gc the VM state. 316 */ 317void 318cpu_exit(td) 319 register struct thread *td; 320{ 321 322 ia64_fpstate_drop(td); 323} 324 325void 326cpu_sched_exit(td) 327 register struct thread *td; 328{ 329} 330 331void 332cpu_wait(p) 333 struct proc *p; 334{ 335} 336 337/* 338 * Force reset the processor by invalidating the entire address space! 339 */ 340void 341cpu_reset() 342{ 343 344 cpu_boot(0); 345} 346 347/* 348 * Software interrupt handler for queued VM system processing. 349 */ 350void 351swi_vm(void *dummy) 352{ 353#if 0 354 if (busdma_swi_pending != 0) 355 busdma_swi(); 356#endif 357} 358 359/* 360 * Tell whether this address is in some physical memory region. 361 * Currently used by the kernel coredump code in order to avoid 362 * dumping the ``ISA memory hole'' which could cause indefinite hangs, 363 * or other unpredictable behaviour. 364 */ 365 366 367int 368is_physical_memory(addr) 369 vm_offset_t addr; 370{ 371 /* 372 * stuff other tests for known memory-mapped devices (PCI?) 373 * here 374 */ 375 376 return 1; 377} 378