vm_machdep.c revision 331722
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 * Copyright (c) 2001 Jake Burkholder. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department, and William Jolitz. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 37 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 38 * from: FreeBSD: src/sys/i386/i386/vm_machdep.c,v 1.167 2001/07/12 39 */ 40 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD: stable/11/sys/sparc64/sparc64/vm_machdep.c 331722 2018-03-29 02:50:57Z eadler $"); 43 44#include "opt_pmap.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/bio.h> 49#include <sys/buf.h> 50#include <sys/kernel.h> 51#include <sys/malloc.h> 52#include <sys/mbuf.h> 53#include <sys/mutex.h> 54#include <sys/proc.h> 55#include <sys/sysent.h> 56#include <sys/sched.h> 57#include <sys/sf_buf.h> 58#include <sys/sysctl.h> 59#include <sys/unistd.h> 60#include <sys/vmmeter.h> 61 62#include <dev/ofw/openfirm.h> 63 64#include <vm/vm.h> 65#include <vm/vm_extern.h> 66#include <vm/pmap.h> 67#include <vm/vm_kern.h> 68#include <vm/vm_map.h> 69#include <vm/vm_page.h> 70#include <vm/vm_pageout.h> 71#include <vm/vm_param.h> 72#include <vm/uma.h> 73#include <vm/uma_int.h> 74 75#include <machine/cache.h> 76#include <machine/cpu.h> 77#include <machine/fp.h> 78#include <machine/frame.h> 79#include <machine/fsr.h> 80#include <machine/md_var.h> 81#include <machine/ofw_machdep.h> 82#include <machine/ofw_mem.h> 83#include <machine/pcb.h> 84#include <machine/tlb.h> 85#include <machine/tstate.h> 86 87PMAP_STATS_VAR(uma_nsmall_alloc); 88PMAP_STATS_VAR(uma_nsmall_alloc_oc); 89PMAP_STATS_VAR(uma_nsmall_free); 90 91void 92cpu_exit(struct thread *td) 93{ 94 struct proc *p; 95 96 p = td->td_proc; 97 p->p_md.md_sigtramp = NULL; 98 if (p->p_md.md_utrap != NULL) { 99 utrap_free(p->p_md.md_utrap); 100 p->p_md.md_utrap = NULL; 101 } 102} 103 104void 105cpu_thread_exit(struct thread *td) 106{ 107 108} 109 110void 111cpu_thread_clean(struct thread *td) 112{ 113 114} 115 116void 117cpu_thread_alloc(struct thread *td) 118{ 119 struct pcb *pcb; 120 121 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 122 sizeof(struct pcb)) & ~0x3fUL); 123 pcb->pcb_nsaved = 0; 124 td->td_frame = (struct trapframe *)pcb - 1; 125 td->td_pcb = pcb; 126} 127 128void 129cpu_thread_free(struct thread *td) 130{ 131 132} 133 134void 135cpu_thread_swapin(struct thread *td) 136{ 137 138} 139 140void 141cpu_thread_swapout(struct thread *td) 142{ 143 144} 145 146void 147cpu_set_syscall_retval(struct thread *td, int error) 148{ 149 150 switch (error) { 151 case 0: 152 td->td_frame->tf_out[0] = td->td_retval[0]; 153 td->td_frame->tf_out[1] = td->td_retval[1]; 154 td->td_frame->tf_tstate &= ~TSTATE_XCC_C; 155 break; 156 157 case ERESTART: 158 /* 159 * Undo the tpc advancement we have done on syscall 160 * enter, we want to reexecute the system call. 161 */ 162 td->td_frame->tf_tpc = td->td_pcb->pcb_tpc; 163 td->td_frame->tf_tnpc -= 4; 164 break; 165 166 case EJUSTRETURN: 167 break; 168 169 default: 170 td->td_frame->tf_out[0] = SV_ABI_ERRNO(td->td_proc, error); 171 td->td_frame->tf_tstate |= TSTATE_XCC_C; 172 break; 173 } 174} 175 176void 177cpu_copy_thread(struct thread *td, struct thread *td0) 178{ 179 struct trapframe *tf; 180 struct frame *fr; 181 struct pcb *pcb; 182 183 bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); 184 185 pcb = td->td_pcb; 186 tf = td->td_frame; 187 fr = (struct frame *)tf - 1; 188 fr->fr_local[0] = (u_long)fork_return; 189 fr->fr_local[1] = (u_long)td; 190 fr->fr_local[2] = (u_long)tf; 191 pcb->pcb_pc = (u_long)fork_trampoline - 8; 192 pcb->pcb_sp = (u_long)fr - SPOFF; 193 194 /* Setup to release the spin count in fork_exit(). */ 195 td->td_md.md_spinlock_count = 1; 196 td->td_md.md_saved_pil = 0; 197} 198 199void 200cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, 201 stack_t *stack) 202{ 203 struct trapframe *tf; 204 uint64_t sp; 205 206 if (td == curthread) 207 flushw(); 208 tf = td->td_frame; 209 sp = (uint64_t)stack->ss_sp + stack->ss_size; 210 tf->tf_out[0] = (uint64_t)arg; 211 tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 212 tf->tf_tpc = (uint64_t)entry; 213 tf->tf_tnpc = tf->tf_tpc + 4; 214 215 td->td_retval[0] = tf->tf_out[0]; 216 td->td_retval[1] = tf->tf_out[1]; 217} 218 219int 220cpu_set_user_tls(struct thread *td, void *tls_base) 221{ 222 223 if (td == curthread) 224 flushw(); 225 td->td_frame->tf_global[7] = (uint64_t)tls_base; 226 return (0); 227} 228 229/* 230 * Finish a fork operation, with process p2 nearly set up. 231 * Copy and update the pcb, set up the stack so that the child 232 * ready to run and return to user mode. 233 */ 234void 235cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) 236{ 237 struct trapframe *tf; 238 struct frame *fp; 239 struct pcb *pcb1; 240 struct pcb *pcb2; 241 vm_offset_t sp; 242 int error; 243 int i; 244 245 KASSERT(td1 == curthread || td1 == &thread0, 246 ("cpu_fork: p1 not curproc and not proc0")); 247 248 if ((flags & RFPROC) == 0) 249 return; 250 251 p2->p_md.md_sigtramp = td1->td_proc->p_md.md_sigtramp; 252 p2->p_md.md_utrap = utrap_hold(td1->td_proc->p_md.md_utrap); 253 254 /* The pcb must be aligned on a 64-byte boundary. */ 255 pcb1 = td1->td_pcb; 256 pcb2 = (struct pcb *)((td2->td_kstack + td2->td_kstack_pages * 257 PAGE_SIZE - sizeof(struct pcb)) & ~0x3fUL); 258 td2->td_pcb = pcb2; 259 260 /* 261 * Ensure that p1's pcb is up to date. 262 */ 263 critical_enter(); 264 if ((td1->td_frame->tf_fprs & FPRS_FEF) != 0) 265 savefpctx(pcb1->pcb_ufp); 266 critical_exit(); 267 /* Make sure the copied windows are spilled. */ 268 flushw(); 269 /* Copy the pcb (this will copy the windows saved in the pcb, too). */ 270 bcopy(pcb1, pcb2, sizeof(*pcb1)); 271 272 /* 273 * If we're creating a new user process and we're sharing the address 274 * space, the parent's top most frame must be saved in the pcb. The 275 * child will pop the frame when it returns to user mode, and may 276 * overwrite it with its own data causing much suffering for the 277 * parent. We check if its already in the pcb, and if not copy it 278 * in. Its unlikely that the copyin will fail, but if so there's not 279 * much we can do. The parent will likely crash soon anyway in that 280 * case. 281 */ 282 if ((flags & RFMEM) != 0 && td1 != &thread0) { 283 sp = td1->td_frame->tf_sp; 284 for (i = 0; i < pcb1->pcb_nsaved; i++) { 285 if (pcb1->pcb_rwsp[i] == sp) 286 break; 287 } 288 if (i == pcb1->pcb_nsaved) { 289 error = copyin((caddr_t)sp + SPOFF, &pcb1->pcb_rw[i], 290 sizeof(struct rwindow)); 291 if (error == 0) { 292 pcb1->pcb_rwsp[i] = sp; 293 pcb1->pcb_nsaved++; 294 } 295 } 296 } 297 298 /* 299 * Create a new fresh stack for the new process. 300 * Copy the trap frame for the return to user mode as if from a 301 * syscall. This copies most of the user mode register values. 302 */ 303 tf = (struct trapframe *)pcb2 - 1; 304 bcopy(td1->td_frame, tf, sizeof(*tf)); 305 306 tf->tf_out[0] = 0; /* Child returns zero */ 307 tf->tf_out[1] = 0; 308 tf->tf_tstate &= ~TSTATE_XCC_C; /* success */ 309 tf->tf_fprs = 0; 310 311 td2->td_frame = tf; 312 fp = (struct frame *)tf - 1; 313 fp->fr_local[0] = (u_long)fork_return; 314 fp->fr_local[1] = (u_long)td2; 315 fp->fr_local[2] = (u_long)tf; 316 /* Terminate stack traces at this frame. */ 317 fp->fr_pc = fp->fr_fp = 0; 318 pcb2->pcb_sp = (u_long)fp - SPOFF; 319 pcb2->pcb_pc = (u_long)fork_trampoline - 8; 320 321 /* Setup to release the spin count in fork_exit(). */ 322 td2->td_md.md_spinlock_count = 1; 323 td2->td_md.md_saved_pil = 0; 324 325 /* 326 * Now, cpu_switch() can schedule the new process. 327 */ 328} 329 330void 331cpu_reset(void) 332{ 333 static char bspec[64] = ""; 334 phandle_t chosen; 335 static struct { 336 cell_t name; 337 cell_t nargs; 338 cell_t nreturns; 339 cell_t bootspec; 340 } args = { 341 (cell_t)"boot", 342 1, 343 0, 344 (cell_t)bspec 345 }; 346 347 if ((chosen = OF_finddevice("/chosen")) != -1) { 348 if (OF_getprop(chosen, "bootpath", bspec, sizeof(bspec)) == -1) 349 bspec[0] = '\0'; 350 bspec[sizeof(bspec) - 1] = '\0'; 351 } 352 353 cpu_shutdown(&args); 354} 355 356/* 357 * Intercept the return address from a freshly forked process that has NOT 358 * been scheduled yet. 359 * 360 * This is needed to make kernel threads stay in kernel mode. 361 */ 362void 363cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg) 364{ 365 struct frame *fp; 366 struct pcb *pcb; 367 368 pcb = td->td_pcb; 369 fp = (struct frame *)(pcb->pcb_sp + SPOFF); 370 fp->fr_local[0] = (u_long)func; 371 fp->fr_local[1] = (u_long)arg; 372} 373 374int 375is_physical_memory(vm_paddr_t addr) 376{ 377 struct ofw_mem_region *mr; 378 379 for (mr = sparc64_memreg; mr < sparc64_memreg + sparc64_nmemreg; mr++) 380 if (addr >= mr->mr_start && addr < mr->mr_start + mr->mr_size) 381 return (1); 382 return (0); 383} 384 385void 386swi_vm(void *v) 387{ 388 389 /* Nothing to do here - busdma bounce buffers are not implemented. */ 390} 391 392void * 393uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait) 394{ 395 vm_paddr_t pa; 396 vm_page_t m; 397 void *va; 398 399 PMAP_STATS_INC(uma_nsmall_alloc); 400 401 *flags = UMA_SLAB_PRIV; 402 403 m = vm_page_alloc(NULL, 0, 404 malloc2vm_flags(wait) | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ); 405 if (m == NULL) 406 return (NULL); 407 408 pa = VM_PAGE_TO_PHYS(m); 409 if (dcache_color_ignore == 0 && m->md.color != DCACHE_COLOR(pa)) { 410 KASSERT(m->md.colors[0] == 0 && m->md.colors[1] == 0, 411 ("uma_small_alloc: free page %p still has mappings!", m)); 412 PMAP_STATS_INC(uma_nsmall_alloc_oc); 413 m->md.color = DCACHE_COLOR(pa); 414 dcache_page_inval(pa); 415 } 416 va = (void *)TLB_PHYS_TO_DIRECT(pa); 417 if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) 418 cpu_block_zero(va, PAGE_SIZE); 419 return (va); 420} 421 422void 423uma_small_free(void *mem, vm_size_t size, u_int8_t flags) 424{ 425 vm_page_t m; 426 427 PMAP_STATS_INC(uma_nsmall_free); 428 m = PHYS_TO_VM_PAGE(TLB_DIRECT_TO_PHYS((vm_offset_t)mem)); 429 m->wire_count--; 430 vm_page_free(m); 431 atomic_subtract_int(&vm_cnt.v_wire_count, 1); 432} 433 434void 435sf_buf_map(struct sf_buf *sf, int flags) 436{ 437 438 pmap_qenter(sf->kva, &sf->m, 1); 439} 440 441int 442sf_buf_unmap(struct sf_buf *sf) 443{ 444 445 pmap_qremove(sf->kva, 1); 446 return (1); 447} 448