1 /* $NetBSD: vm_machdep.c,v 1.12 2011/02/05 13:47:57 yamt Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986 The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 36 */ 37 38 /*- 39 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 40 * Copyright (c) 1989, 1990 William Jolitz 41 * All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * the Systems Programming Group of the University of Utah Computer 45 * Science Department, and William Jolitz. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Berkeley and its contributors. 59 * 4. Neither the name of the University nor the names of its contributors 60 * may be used to endorse or promote products derived from this software 61 * without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 76 */ 77 78 /* 79 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 80 */ 81 82 #include <sys/cdefs.h> 83 __KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.12 2011/02/05 13:47:57 yamt Exp $"); 84 85 #include "opt_mtrr.h" 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/proc.h> 90 #include <sys/vnode.h> 91 #include <sys/buf.h> 92 #include <sys/core.h> 93 #include <sys/exec.h> 94 #include <sys/ptrace.h> 95 96 #include <uvm/uvm_extern.h> 97 98 #include <machine/cpu.h> 99 #include <machine/gdt.h> 100 #include <machine/reg.h> 101 #include <machine/specialreg.h> 102 #ifdef MTRR 103 #include <machine/mtrr.h> 104 #endif 105 106 #ifdef __x86_64__ 107 #include <machine/fpu.h> 108 #else 109 #include "npx.h" 110 #if NNPX > 0 111 #define fpusave_lwp(x, y) npxsave_lwp(x, y) 112 #else 113 #define fpusave_lwp(x, y) 114 #endif 115 #endif 116 117 void 118 cpu_proc_fork(struct proc *p1, struct proc *p2) 119 { 120 121 p2->p_md.md_flags = p1->p_md.md_flags; 122 } 123 124 /* 125 * cpu_lwp_fork: finish a new LWP (l2) operation. 126 * 127 * First LWP (l1) is the process being forked. If it is &lwp0, then we 128 * are creating a kthread, where return path and argument are specified 129 * with `func' and `arg'. 130 * 131 * If an alternate user-level stack is requested (with non-zero values 132 * in both the stack and stacksize arguments), then set up the user stack 133 * pointer accordingly. 134 */ 135 void 136 cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, 137 void (*func)(void *), void *arg) 138 { 139 struct pcb *pcb1, *pcb2; 140 struct trapframe *tf; 141 vaddr_t uv; 142 143 pcb1 = lwp_getpcb(l1); 144 pcb2 = lwp_getpcb(l2); 145 146 /* 147 * If parent LWP was using FPU, then we have to save the FPU h/w 148 * state to PCB so that we can copy it. 149 */ 150 if (pcb1->pcb_fpcpu != NULL) { 151 fpusave_lwp(l1, true); 152 } 153 154 /* 155 * Sync the PCB before we copy it. 156 */ 157 if (l1 == curlwp) { 158 KASSERT(pcb1 == curpcb); 159 savectx(pcb1); 160 } else { 161 KASSERT(l1 == &lwp0); 162 } 163 164 /* Copy the PCB from parent. */ 165 memcpy(pcb2, pcb1, sizeof(struct pcb)); 166 167 #if defined(XEN) 168 pcb2->pcb_iopl = SEL_KPL; 169 #endif 170 171 /* 172 * Set the kernel stack address (from the address to uarea) and 173 * trapframe address for child. 174 * 175 * Rig kernel stack so that it would start out in lwp_trampoline() 176 * and call child_return() with l2 as an argument. This causes the 177 * newly-created child process to go directly to user level with a 178 * parent return value of 0 from fork(), while the parent process 179 * returns normally. 180 */ 181 uv = uvm_lwp_getuarea(l2); 182 183 #ifdef __x86_64__ 184 pcb2->pcb_rsp0 = (uv + KSTACK_SIZE - 16) & ~0xf; 185 tf = (struct trapframe *)pcb2->pcb_rsp0 - 1; 186 #else 187 pcb2->pcb_esp0 = (uv + KSTACK_SIZE - 16); 188 tf = (struct trapframe *)pcb2->pcb_esp0 - 1; 189 190 pcb2->pcb_iomap = NULL; 191 #endif 192 l2->l_md.md_regs = tf; 193 194 /* 195 * Copy the trapframe from parent, so that return to userspace 196 * will be to right address, with correct registers. 197 */ 198 memcpy(tf, l1->l_md.md_regs, sizeof(struct trapframe)); 199 200 /* Child LWP might get aston() before returning to userspace. */ 201 tf->tf_trapno = T_ASTFLT; 202 203 #if 0 /* DIAGNOSTIC */ 204 /* Set a red zone in the kernel stack after the uarea. */ 205 pmap_kremove(uv, PAGE_SIZE); 206 pmap_update(pmap_kernel()); 207 #endif 208 209 /* If specified, set a different user stack for a child. */ 210 if (stack != NULL) { 211 #ifdef __x86_64__ 212 tf->tf_rsp = (uint64_t)stack + stacksize; 213 #else 214 tf->tf_esp = (uint32_t)stack + stacksize; 215 #endif 216 } 217 218 l2->l_md.md_flags = l1->l_md.md_flags; 219 l2->l_md.md_astpending = 0; 220 221 cpu_setfunc(l2, func, arg); 222 } 223 224 void 225 cpu_setfunc(struct lwp *l, void (*func)(void *), void *arg) 226 { 227 struct pcb *pcb = lwp_getpcb(l); 228 struct trapframe *tf = l->l_md.md_regs; 229 struct switchframe *sf = (struct switchframe *)tf - 1; 230 231 #ifdef __x86_64__ 232 sf->sf_r12 = (uint64_t)func; 233 sf->sf_r13 = (uint64_t)arg; 234 if (func == child_return && !(l->l_proc->p_flag & PK_32)) 235 sf->sf_rip = (uint64_t)child_trampoline; 236 else 237 sf->sf_rip = (uint64_t)lwp_trampoline; 238 pcb->pcb_rsp = (uint64_t)sf; 239 pcb->pcb_rbp = (uint64_t)l; 240 #else 241 sf->sf_esi = (int)func; 242 sf->sf_ebx = (int)arg; 243 sf->sf_eip = (int)lwp_trampoline; 244 pcb->pcb_esp = (int)sf; 245 pcb->pcb_ebp = (int)l; 246 #endif 247 } 248 249 /* 250 * cpu_lwp_free is called from exit() to let machine-dependent 251 * code free machine-dependent resources. Note that this routine 252 * must not block. 253 */ 254 void 255 cpu_lwp_free(struct lwp *l, int proc) 256 { 257 struct pcb *pcb = lwp_getpcb(l); 258 259 /* If we were using the FPU, forget about it. */ 260 if (pcb->pcb_fpcpu != NULL) { 261 fpusave_lwp(l, false); 262 } 263 264 #ifdef MTRR 265 if (proc && l->l_proc->p_md.md_flags & MDP_USEDMTRR) 266 mtrr_clean(l->l_proc); 267 #endif 268 } 269 270 /* 271 * cpu_lwp_free2 is called when an LWP is being reaped. 272 * This routine may block. 273 */ 274 void 275 cpu_lwp_free2(struct lwp *l) 276 { 277 278 KASSERT(l->l_md.md_gc_ptp == NULL); 279 KASSERT(l->l_md.md_gc_pmap == NULL); 280 } 281 282 /* 283 * Convert kernel VA to physical address 284 */ 285 paddr_t 286 kvtop(void *addr) 287 { 288 paddr_t pa; 289 bool ret; 290 291 ret = pmap_extract(pmap_kernel(), (vaddr_t)addr, &pa); 292 KASSERT(ret == true); 293 return pa; 294 } 295 296 /* 297 * Map a user I/O request into kernel virtual address space. 298 * Note: the pages are already locked by uvm_vslock(), so we 299 * do not need to pass an access_type to pmap_enter(). 300 */ 301 void 302 vmapbuf(struct buf *bp, vsize_t len) 303 { 304 vaddr_t faddr, taddr, off; 305 paddr_t fpa; 306 307 KASSERT((bp->b_flags & B_PHYS) != 0); 308 309 bp->b_saveaddr = bp->b_data; 310 faddr = trunc_page((vaddr_t)bp->b_data); 311 off = (vaddr_t)bp->b_data - faddr; 312 len = round_page(off + len); 313 taddr = uvm_km_alloc(phys_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); 314 bp->b_data = (void *)(taddr + off); 315 /* 316 * The region is locked, so we expect that pmap_pte() will return 317 * non-NULL. 318 * XXX: unwise to expect this in a multithreaded environment. 319 * anything can happen to a pmap between the time we lock a 320 * region, release the pmap lock, and then relock it for 321 * the pmap_extract(). 322 * 323 * no need to flush TLB since we expect nothing to be mapped 324 * where we we just allocated (TLB will be flushed when our 325 * mapping is removed). 326 */ 327 while (len) { 328 (void) pmap_extract(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), 329 faddr, &fpa); 330 pmap_kenter_pa(taddr, fpa, VM_PROT_READ|VM_PROT_WRITE, 0); 331 faddr += PAGE_SIZE; 332 taddr += PAGE_SIZE; 333 len -= PAGE_SIZE; 334 } 335 pmap_update(pmap_kernel()); 336 } 337 338 /* 339 * Unmap a previously-mapped user I/O request. 340 */ 341 void 342 vunmapbuf(struct buf *bp, vsize_t len) 343 { 344 vaddr_t addr, off; 345 346 KASSERT((bp->b_flags & B_PHYS) != 0); 347 348 addr = trunc_page((vaddr_t)bp->b_data); 349 off = (vaddr_t)bp->b_data - addr; 350 len = round_page(off + len); 351 pmap_kremove(addr, len); 352 pmap_update(pmap_kernel()); 353 uvm_km_free(phys_map, addr, len, UVM_KMF_VAONLY); 354 bp->b_data = bp->b_saveaddr; 355 bp->b_saveaddr = 0; 356 } 357