vm_machdep.c revision 210644
1178172Simp/*- 2178172Simp * Copyright (c) 1982, 1986 The Regents of the University of California. 3178172Simp * Copyright (c) 1989, 1990 William Jolitz 4178172Simp * Copyright (c) 1994 John Dyson 5178172Simp * All rights reserved. 6178172Simp * 7178172Simp * This code is derived from software contributed to Berkeley by 8178172Simp * the Systems Programming Group of the University of Utah Computer 9178172Simp * Science Department, and William Jolitz. 10178172Simp * 11178172Simp * Redistribution and use in source and binary forms, with or without 12178172Simp * modification, are permitted provided that the following conditions 13178172Simp * are met: 14178172Simp * 1. Redistributions of source code must retain the above copyright 15178172Simp * notice, this list of conditions and the following disclaimer. 16178172Simp * 2. Redistributions in binary form must reproduce the above copyright 17178172Simp * notice, this list of conditions and the following disclaimer in the 18178172Simp * documentation and/or other materials provided with the distribution. 19178172Simp * 4. Neither the name of the University nor the names of its contributors 20178172Simp * may be used to endorse or promote products derived from this software 21178172Simp * without specific prior written permission. 22178172Simp * 23178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33178172Simp * SUCH DAMAGE. 34178172Simp * 35178172Simp * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 36178172Simp * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 37178172Simp * from: src/sys/i386/i386/vm_machdep.c,v 1.132.2.2 2000/08/26 04:19:26 yokota 38178172Simp * JNPR: vm_machdep.c,v 1.8.2.2 2007/08/16 15:59:17 girish 39178172Simp */ 40178172Simp 41178172Simp#include <sys/cdefs.h> 42178172Simp__FBSDID("$FreeBSD: head/sys/mips/mips/vm_machdep.c 210644 2010-07-30 12:45:00Z jchandra $"); 43178172Simp 44202046Simp#include "opt_cputype.h" 45202046Simp#include "opt_ddb.h" 46202046Simp 47178172Simp#include <sys/param.h> 48178172Simp#include <sys/systm.h> 49178172Simp#include <sys/malloc.h> 50178172Simp#include <sys/proc.h> 51199135Skib#include <sys/syscall.h> 52178172Simp#include <sys/buf.h> 53178172Simp#include <sys/vnode.h> 54178172Simp#include <sys/vmmeter.h> 55178172Simp#include <sys/kernel.h> 56178172Simp#include <sys/sysctl.h> 57178172Simp#include <sys/unistd.h> 58178172Simp 59206714Sjmallett#include <machine/asm.h> 60202046Simp#include <machine/cache.h> 61178172Simp#include <machine/clock.h> 62178172Simp#include <machine/cpu.h> 63178172Simp#include <machine/md_var.h> 64178172Simp#include <machine/pcb.h> 65178172Simp 66178172Simp#include <vm/vm.h> 67206714Sjmallett#include <vm/vm_extern.h> 68206714Sjmallett#include <vm/pmap.h> 69178172Simp#include <vm/vm_kern.h> 70206714Sjmallett#include <vm/vm_map.h> 71178172Simp#include <vm/vm_page.h> 72206714Sjmallett#include <vm/vm_pageout.h> 73206714Sjmallett#include <vm/vm_param.h> 74206714Sjmallett#include <vm/uma.h> 75206714Sjmallett#include <vm/uma_int.h> 76178172Simp 77178172Simp#include <sys/user.h> 78178172Simp#include <sys/mbuf.h> 79178172Simp#include <sys/sf_buf.h> 80178172Simp 81178172Simp#ifndef NSFBUFS 82178172Simp#define NSFBUFS (512 + maxusers * 16) 83178172Simp#endif 84178172Simp 85178172Simpstatic void sf_buf_init(void *arg); 86178172SimpSYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); 87178172Simp 88178172Simp/* 89206714Sjmallett * Expanded sf_freelist head. Really an SLIST_HEAD() in disguise, with the 90206714Sjmallett * sf_freelist head with the sf_lock mutex. 91178172Simp */ 92206714Sjmallettstatic struct { 93206714Sjmallett SLIST_HEAD(, sf_buf) sf_head; 94206714Sjmallett struct mtx sf_lock; 95206714Sjmallett} sf_freelist; 96178172Simp 97178172Simpstatic u_int sf_buf_alloc_want; 98178172Simp 99178172Simp/* 100178172Simp * Finish a fork operation, with process p2 nearly set up. 101178172Simp * Copy and update the pcb, set up the stack so that the child 102178172Simp * ready to run and return to user mode. 103178172Simp */ 104178172Simpvoid 105178172Simpcpu_fork(register struct thread *td1,register struct proc *p2, 106178172Simp struct thread *td2,int flags) 107178172Simp{ 108178172Simp register struct proc *p1; 109178172Simp struct pcb *pcb2; 110178172Simp 111178172Simp p1 = td1->td_proc; 112178172Simp if ((flags & RFPROC) == 0) 113178172Simp return; 114178172Simp /* It is assumed that the vm_thread_alloc called 115178172Simp * cpu_thread_alloc() before cpu_fork is called. 116178172Simp */ 117178172Simp 118178172Simp /* Point the pcb to the top of the stack */ 119178172Simp pcb2 = td2->td_pcb; 120178172Simp 121178172Simp /* Copy p1's pcb, note that in this case 122178172Simp * our pcb also includes the td_frame being copied 123178172Simp * too. The older mips2 code did an additional copy 124178172Simp * of the td_frame, for us thats not needed any 125178172Simp * longer (this copy does them both 126178172Simp */ 127178172Simp bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); 128178172Simp 129178172Simp /* Point mdproc and then copy over td1's contents 130178172Simp * md_proc is empty for MIPS 131178172Simp */ 132178172Simp td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED; 133178172Simp 134178172Simp /* 135178172Simp * Set up return-value registers as fork() libc stub expects. 136178172Simp */ 137178172Simp td2->td_frame->v0 = 0; 138178172Simp td2->td_frame->v1 = 1; 139178172Simp td2->td_frame->a3 = 0; 140178172Simp 141178172Simp if (td1 == PCPU_GET(fpcurthread)) 142178172Simp MipsSaveCurFPState(td1); 143178172Simp 144209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 145178172Simp /* Make sp 64-bit aligned */ 146202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb & 147206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 148209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 149209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2; 150209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame; 151210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 152210644Sjchandra (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 153178172Simp /* 154178172Simp * FREEBSD_DEVELOPERS_FIXME: 155178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 156178172Simp * and/or bits in other standard MIPS registers (if CPU-Specific) 157178172Simp * that are needed. 158178172Simp */ 159178172Simp 160202046Simp td2->td_md.md_tls = td1->td_md.md_tls; 161178172Simp td2->td_md.md_saved_intr = MIPS_SR_INT_IE; 162178172Simp td2->td_md.md_spinlock_count = 1; 163210311Sjmallett#ifdef CPU_CNMIPS 164210038Simp pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_COP_2_BIT | MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX; 165178172Simp#endif 166178172Simp} 167178172Simp 168178172Simp/* 169178172Simp * Intercept the return address from a freshly forked process that has NOT 170178172Simp * been scheduled yet. 171178172Simp * 172178172Simp * This is needed to make kernel threads stay in kernel mode. 173178172Simp */ 174178172Simpvoid 175178172Simpcpu_set_fork_handler(struct thread *td, void (*func) __P((void *)), void *arg) 176178172Simp{ 177178172Simp /* 178178172Simp * Note that the trap frame follows the args, so the function 179178172Simp * is really called like this: func(arg, frame); 180178172Simp */ 181209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func; 182209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg; 183178172Simp} 184178172Simp 185178172Simpvoid 186178172Simpcpu_exit(struct thread *td) 187178172Simp{ 188178172Simp} 189178172Simp 190178172Simpvoid 191178172Simpcpu_thread_exit(struct thread *td) 192178172Simp{ 193178172Simp 194178172Simp if (PCPU_GET(fpcurthread) == td) 195178172Simp PCPU_GET(fpcurthread) = (struct thread *)0; 196178172Simp} 197178172Simp 198178172Simpvoid 199178172Simpcpu_thread_free(struct thread *td) 200178172Simp{ 201178172Simp} 202178172Simp 203178172Simpvoid 204178172Simpcpu_thread_clean(struct thread *td) 205178172Simp{ 206178172Simp} 207178172Simp 208178172Simpvoid 209178172Simpcpu_thread_swapin(struct thread *td) 210178172Simp{ 211178172Simp pt_entry_t *pte; 212178172Simp int i; 213178172Simp 214178172Simp /* 215178172Simp * The kstack may be at a different physical address now. 216178172Simp * Cache the PTEs for the Kernel stack in the machine dependent 217178172Simp * part of the thread struct so cpu_switch() can quickly map in 218178172Simp * the pcb struct and kernel stack. 219178172Simp */ 220206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 221206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 222209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 223178172Simp } 224178172Simp} 225178172Simp 226178172Simpvoid 227178172Simpcpu_thread_swapout(struct thread *td) 228178172Simp{ 229178172Simp} 230178172Simp 231178172Simpvoid 232178172Simpcpu_thread_alloc(struct thread *td) 233178172Simp{ 234178172Simp pt_entry_t *pte; 235178172Simp int i; 236178172Simp 237206819Sjmallett KASSERT((td->td_kstack & (1 << PAGE_SHIFT)) == 0, ("kernel stack must be aligned.")); 238206819Sjmallett td->td_pcb = (struct pcb *)(td->td_kstack + 239206819Sjmallett td->td_kstack_pages * PAGE_SIZE) - 1; 240178172Simp td->td_frame = &td->td_pcb->pcb_regs; 241178172Simp 242206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 243206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 244209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 245178172Simp } 246178172Simp} 247178172Simp 248199135Skibvoid 249199135Skibcpu_set_syscall_retval(struct thread *td, int error) 250199135Skib{ 251199135Skib struct trapframe *locr0 = td->td_frame; 252199135Skib unsigned int code; 253199135Skib int quad_syscall; 254199135Skib 255199135Skib code = locr0->v0; 256199135Skib quad_syscall = 0; 257209500Sjchandra#if defined(__mips_o32) 258209500Sjchandra if (code == SYS___syscall) 259209500Sjchandra quad_syscall = 1; 260209500Sjchandra#endif 261209500Sjchandra 262199135Skib if (code == SYS_syscall) 263199135Skib code = locr0->a0; 264199135Skib else if (code == SYS___syscall) { 265209500Sjchandra if (quad_syscall) 266209500Sjchandra code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0; 267209500Sjchandra else 268209500Sjchandra code = locr0->a0; 269199135Skib } 270199135Skib 271199135Skib switch (error) { 272199135Skib case 0: 273199135Skib if (quad_syscall && code != SYS_lseek) { 274199135Skib /* 275199135Skib * System call invoked through the 276199135Skib * SYS___syscall interface but the 277199135Skib * return value is really just 32 278199135Skib * bits. 279199135Skib */ 280199135Skib locr0->v0 = td->td_retval[0]; 281199135Skib if (_QUAD_LOWWORD) 282199135Skib locr0->v1 = td->td_retval[0]; 283199135Skib locr0->a3 = 0; 284199135Skib } else { 285199135Skib locr0->v0 = td->td_retval[0]; 286199135Skib locr0->v1 = td->td_retval[1]; 287199135Skib locr0->a3 = 0; 288199135Skib } 289199135Skib break; 290199135Skib 291199135Skib case ERESTART: 292199135Skib locr0->pc = td->td_pcb->pcb_tpc; 293199135Skib break; 294199135Skib 295199135Skib case EJUSTRETURN: 296199135Skib break; /* nothing to do */ 297199135Skib 298199135Skib default: 299199135Skib if (quad_syscall && code != SYS_lseek) { 300199135Skib locr0->v0 = error; 301199135Skib if (_QUAD_LOWWORD) 302199135Skib locr0->v1 = error; 303199135Skib locr0->a3 = 1; 304199135Skib } else { 305199135Skib locr0->v0 = error; 306199135Skib locr0->a3 = 1; 307199135Skib } 308199135Skib } 309199135Skib} 310199135Skib 311178172Simp/* 312178172Simp * Initialize machine state (pcb and trap frame) for a new thread about to 313178172Simp * upcall. Put enough state in the new thread's PCB to get it to go back 314178172Simp * userret(), where we can intercept it again to set the return (upcall) 315178172Simp * Address and stack, along with those from upcals that are from other sources 316178172Simp * such as those generated in thread_userret() itself. 317178172Simp */ 318178172Simpvoid 319178172Simpcpu_set_upcall(struct thread *td, struct thread *td0) 320178172Simp{ 321178172Simp struct pcb *pcb2; 322178172Simp 323178172Simp /* Point the pcb to the top of the stack. */ 324178172Simp pcb2 = td->td_pcb; 325178172Simp 326178172Simp /* 327178172Simp * Copy the upcall pcb. This loads kernel regs. 328178172Simp * Those not loaded individually below get their default 329178172Simp * values here. 330178172Simp * 331178172Simp * XXXKSE It might be a good idea to simply skip this as 332178172Simp * the values of the other registers may be unimportant. 333178172Simp * This would remove any requirement for knowing the KSE 334178172Simp * at this time (see the matching comment below for 335178172Simp * more analysis) (need a good safe default). 336178172Simp * In MIPS, the trapframe is the first element of the PCB 337178172Simp * and gets copied when we copy the PCB. No seperate copy 338178172Simp * is needed. 339178172Simp */ 340178172Simp bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 341178172Simp 342178172Simp /* 343178172Simp * Set registers for trampoline to user mode. 344178172Simp */ 345178172Simp 346209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 347178172Simp /* Make sp 64-bit aligned */ 348202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb & 349206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 350209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 351209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td; 352209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame; 353202046Simp /* Dont set IE bit in SR. sched lock release will take care of it */ 354210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 355210644Sjchandra (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 356178172Simp 357210311Sjmallett#ifdef CPU_CNMIPS 358202046Simp pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT | 359210038Simp MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX; 360178172Simp#endif 361178172Simp 362178172Simp /* 363178172Simp * FREEBSD_DEVELOPERS_FIXME: 364178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 365178172Simp * that are needed. 366178172Simp */ 367178172Simp 368178172Simp /* SMP Setup to release sched_lock in fork_exit(). */ 369178172Simp td->td_md.md_spinlock_count = 1; 370178172Simp td->td_md.md_saved_intr = MIPS_SR_INT_IE; 371178172Simp#if 0 372178172Simp /* Maybe we need to fix this? */ 373178172Simp td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) | 374210038Simp (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) | 375178172Simp (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK)); 376178172Simp#endif 377178172Simp} 378178172Simp 379178172Simp/* 380178172Simp * Set that machine state for performing an upcall that has to 381178172Simp * be done in thread_userret() so that those upcalls generated 382178172Simp * in thread_userret() itself can be done as well. 383178172Simp */ 384178172Simpvoid 385178172Simpcpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 386178172Simp stack_t *stack) 387178172Simp{ 388178172Simp struct trapframe *tf; 389202046Simp register_t sp; 390178172Simp 391178172Simp /* 392178172Simp * At the point where a function is called, sp must be 8 393178172Simp * byte aligned[for compatibility with 64-bit CPUs] 394178172Simp * in ``See MIPS Run'' by D. Sweetman, p. 269 395178172Simp * align stack */ 396209500Sjchandra sp = ((register_t)(intptr_t)(stack->ss_sp + stack->ss_size) & ~0x7) - 397206834Sjmallett CALLFRAME_SIZ; 398178172Simp 399178172Simp /* 400178172Simp * Set the trap frame to point at the beginning of the uts 401178172Simp * function. 402178172Simp */ 403178172Simp tf = td->td_frame; 404178172Simp bzero(tf, sizeof(struct trapframe)); 405209500Sjchandra tf->sp = sp; 406209500Sjchandra tf->pc = (register_t)(intptr_t)entry; 407202046Simp /* 408202046Simp * MIPS ABI requires T9 to be the same as PC 409202046Simp * in subroutine entry point 410202046Simp */ 411209500Sjchandra tf->t9 = (register_t)(intptr_t)entry; 412209500Sjchandra tf->a0 = (register_t)(intptr_t)arg; 413178172Simp 414202046Simp /* 415202046Simp * Keep interrupt mask 416202046Simp */ 417210644Sjchandra td->td_frame->sr = MIPS_SR_KSU_USER | MIPS_SR_EXL | MIPS_SR_INT_IE | 418210644Sjchandra (mips_rd_status() & MIPS_SR_INT_MASK); 419210644Sjchandra#if defined(__mips_n32) 420210644Sjchandra td->td_frame->sr |= MIPS_SR_PX; 421210644Sjchandra#elif defined(__mips_n64) 422210644Sjchandra td->td_frame->sr |= MIPS_SR_PX | MIPS_SR_UX; 423210644Sjchandra#endif 424210311Sjmallett#ifdef CPU_CNMIPS 425210038Simp tf->sr |= MIPS_SR_INT_IE | MIPS_SR_COP_0_BIT | MIPS_SR_PX | MIPS_SR_UX | 426178172Simp MIPS_SR_KX; 427178172Simp#endif 428178172Simp/* tf->sr |= (ALL_INT_MASK & idle_mask) | SR_INT_ENAB; */ 429178172Simp /**XXX the above may now be wrong -- mips2 implements this as panic */ 430178172Simp /* 431178172Simp * FREEBSD_DEVELOPERS_FIXME: 432178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 433178172Simp * that are needed. 434178172Simp */ 435178172Simp} 436178172Simp/* 437178172Simp * Convert kernel VA to physical address 438178172Simp */ 439178172Simpu_long 440178172Simpkvtop(void *addr) 441178172Simp{ 442178172Simp vm_offset_t va; 443178172Simp 444178172Simp va = pmap_kextract((vm_offset_t)addr); 445178172Simp if (va == 0) 446178172Simp panic("kvtop: zero page frame"); 447209500Sjchandra return((intptr_t)va); 448178172Simp} 449178172Simp 450178172Simp/* 451178172Simp * Implement the pre-zeroed page mechanism. 452178172Simp * This routine is called from the idle loop. 453178172Simp */ 454178172Simp 455178172Simp#define ZIDLE_LO(v) ((v) * 2 / 3) 456178172Simp#define ZIDLE_HI(v) ((v) * 4 / 5) 457178172Simp 458178172Simp/* 459178172Simp * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 460178172Simp */ 461178172Simpstatic void 462178172Simpsf_buf_init(void *arg) 463178172Simp{ 464178172Simp struct sf_buf *sf_bufs; 465178172Simp vm_offset_t sf_base; 466178172Simp int i; 467178172Simp 468178172Simp nsfbufs = NSFBUFS; 469178172Simp TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); 470178172Simp 471206714Sjmallett mtx_init(&sf_freelist.sf_lock, "sf_bufs list lock", NULL, MTX_DEF); 472206714Sjmallett SLIST_INIT(&sf_freelist.sf_head); 473178172Simp sf_base = kmem_alloc_nofault(kernel_map, nsfbufs * PAGE_SIZE); 474178172Simp sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, 475178172Simp M_NOWAIT | M_ZERO); 476178172Simp for (i = 0; i < nsfbufs; i++) { 477178172Simp sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 478206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, &sf_bufs[i], free_list); 479178172Simp } 480178172Simp sf_buf_alloc_want = 0; 481178172Simp} 482178172Simp 483178172Simp/* 484206714Sjmallett * Get an sf_buf from the freelist. Will block if none are available. 485178172Simp */ 486178172Simpstruct sf_buf * 487178172Simpsf_buf_alloc(struct vm_page *m, int flags) 488178172Simp{ 489178172Simp struct sf_buf *sf; 490178172Simp int error; 491178172Simp 492206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 493206714Sjmallett while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) { 494178172Simp if (flags & SFB_NOWAIT) 495206714Sjmallett break; 496178172Simp sf_buf_alloc_want++; 497178172Simp mbstat.sf_allocwait++; 498206714Sjmallett error = msleep(&sf_freelist, &sf_freelist.sf_lock, 499178172Simp (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); 500178172Simp sf_buf_alloc_want--; 501178172Simp 502178172Simp /* 503178172Simp * If we got a signal, don't risk going back to sleep. 504178172Simp */ 505178172Simp if (error) 506206714Sjmallett break; 507178172Simp } 508206714Sjmallett if (sf != NULL) { 509206714Sjmallett SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list); 510206714Sjmallett sf->m = m; 511206714Sjmallett nsfbufsused++; 512206714Sjmallett nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 513206714Sjmallett pmap_qenter(sf->kva, &sf->m, 1); 514206714Sjmallett } 515206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 516178172Simp return (sf); 517178172Simp} 518178172Simp 519178172Simp/* 520206714Sjmallett * Release resources back to the system. 521178172Simp */ 522178172Simpvoid 523178172Simpsf_buf_free(struct sf_buf *sf) 524178172Simp{ 525206714Sjmallett 526206714Sjmallett pmap_qremove(sf->kva, 1); 527206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 528206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); 529206714Sjmallett nsfbufsused--; 530206714Sjmallett if (sf_buf_alloc_want > 0) 531206714Sjmallett wakeup_one(&sf_freelist); 532206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 533178172Simp} 534178172Simp 535178172Simp/* 536178172Simp * Software interrupt handler for queued VM system processing. 537178172Simp */ 538178172Simpvoid 539178172Simpswi_vm(void *dummy) 540178172Simp{ 541178172Simp} 542178172Simp 543178172Simpint 544178172Simpcpu_set_user_tls(struct thread *td, void *tls_base) 545178172Simp{ 546178172Simp 547202046Simp td->td_md.md_tls = tls_base; 548178172Simp return (0); 549178172Simp} 550178172Simp 551202046Simp#ifdef DDB 552202046Simp#include <ddb/ddb.h> 553202046Simp 554202046Simp#define DB_PRINT_REG(ptr, regname) \ 555209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname)) 556202046Simp 557202046Simp#define DB_PRINT_REG_ARRAY(ptr, arrname, regname) \ 558209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname])) 559202046Simp 560202999Sneelstatic void 561202999Sneeldump_trapframe(struct trapframe *trapframe) 562202046Simp{ 563202046Simp 564202999Sneel db_printf("Trapframe at %p\n", trapframe); 565202046Simp 566202046Simp DB_PRINT_REG(trapframe, zero); 567202046Simp DB_PRINT_REG(trapframe, ast); 568202046Simp DB_PRINT_REG(trapframe, v0); 569202046Simp DB_PRINT_REG(trapframe, v1); 570202046Simp DB_PRINT_REG(trapframe, a0); 571202046Simp DB_PRINT_REG(trapframe, a1); 572202046Simp DB_PRINT_REG(trapframe, a2); 573202046Simp DB_PRINT_REG(trapframe, a3); 574202046Simp DB_PRINT_REG(trapframe, t0); 575202046Simp DB_PRINT_REG(trapframe, t1); 576202046Simp DB_PRINT_REG(trapframe, t2); 577202046Simp DB_PRINT_REG(trapframe, t3); 578202046Simp DB_PRINT_REG(trapframe, t4); 579202046Simp DB_PRINT_REG(trapframe, t5); 580202046Simp DB_PRINT_REG(trapframe, t6); 581202046Simp DB_PRINT_REG(trapframe, t7); 582202046Simp DB_PRINT_REG(trapframe, s0); 583202046Simp DB_PRINT_REG(trapframe, s1); 584202046Simp DB_PRINT_REG(trapframe, s2); 585202046Simp DB_PRINT_REG(trapframe, s3); 586202046Simp DB_PRINT_REG(trapframe, s4); 587202046Simp DB_PRINT_REG(trapframe, s5); 588202046Simp DB_PRINT_REG(trapframe, s6); 589202046Simp DB_PRINT_REG(trapframe, s7); 590202046Simp DB_PRINT_REG(trapframe, t8); 591202046Simp DB_PRINT_REG(trapframe, t9); 592202046Simp DB_PRINT_REG(trapframe, k0); 593202046Simp DB_PRINT_REG(trapframe, k1); 594202046Simp DB_PRINT_REG(trapframe, gp); 595202046Simp DB_PRINT_REG(trapframe, sp); 596202046Simp DB_PRINT_REG(trapframe, s8); 597202046Simp DB_PRINT_REG(trapframe, ra); 598202046Simp DB_PRINT_REG(trapframe, sr); 599202046Simp DB_PRINT_REG(trapframe, mullo); 600202046Simp DB_PRINT_REG(trapframe, mulhi); 601202046Simp DB_PRINT_REG(trapframe, badvaddr); 602202046Simp DB_PRINT_REG(trapframe, cause); 603202046Simp DB_PRINT_REG(trapframe, pc); 604202999Sneel} 605202046Simp 606202999SneelDB_SHOW_COMMAND(pcb, ddb_dump_pcb) 607202999Sneel{ 608202999Sneel struct thread *td; 609202999Sneel struct pcb *pcb; 610202999Sneel struct trapframe *trapframe; 611202999Sneel 612202999Sneel /* Determine which thread to examine. */ 613202999Sneel if (have_addr) 614202999Sneel td = db_lookup_thread(addr, TRUE); 615202999Sneel else 616202999Sneel td = curthread; 617202999Sneel 618202999Sneel pcb = td->td_pcb; 619202999Sneel 620202999Sneel db_printf("Thread %d at %p\n", td->td_tid, td); 621202999Sneel 622202999Sneel db_printf("PCB at %p\n", pcb); 623202999Sneel 624202999Sneel trapframe = &pcb->pcb_regs; 625202999Sneel dump_trapframe(trapframe); 626202999Sneel 627202046Simp db_printf("PCB Context:\n"); 628202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S0); 629202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S1); 630202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S2); 631202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S3); 632202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S4); 633202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S5); 634202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S6); 635202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S7); 636202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SP); 637202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S8); 638202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_RA); 639202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SR); 640202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_GP); 641202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_PC); 642202046Simp 643206749Sjmallett db_printf("PCB onfault = %p\n", pcb->pcb_onfault); 644202046Simp db_printf("md_saved_intr = 0x%0lx\n", (long)td->td_md.md_saved_intr); 645202046Simp db_printf("md_spinlock_count = %d\n", td->td_md.md_spinlock_count); 646202046Simp 647202046Simp if (td->td_frame != trapframe) { 648202046Simp db_printf("td->td_frame %p is not the same as pcb_regs %p\n", 649202046Simp td->td_frame, trapframe); 650202046Simp } 651202046Simp} 652202046Simp 653202999Sneel/* 654202999Sneel * Dump the trapframe beginning at address specified by first argument. 655202999Sneel */ 656202999SneelDB_SHOW_COMMAND(trapframe, ddb_dump_trapframe) 657202999Sneel{ 658202999Sneel 659202999Sneel if (!have_addr) 660202999Sneel return; 661202999Sneel 662202999Sneel dump_trapframe((struct trapframe *)addr); 663202999Sneel} 664202999Sneel 665202046Simp#endif /* DDB */ 666