vm_machdep.c revision 232770
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 232770 2012-03-10 06:54:37Z jmallett $"); 43178172Simp 44232449Sjmallett#include "opt_compat.h" 45202046Simp#include "opt_cputype.h" 46202046Simp#include "opt_ddb.h" 47202046Simp 48178172Simp#include <sys/param.h> 49178172Simp#include <sys/systm.h> 50178172Simp#include <sys/malloc.h> 51178172Simp#include <sys/proc.h> 52199135Skib#include <sys/syscall.h> 53232449Sjmallett#include <sys/sysent.h> 54178172Simp#include <sys/buf.h> 55178172Simp#include <sys/vnode.h> 56178172Simp#include <sys/vmmeter.h> 57178172Simp#include <sys/kernel.h> 58178172Simp#include <sys/sysctl.h> 59178172Simp#include <sys/unistd.h> 60178172Simp 61206714Sjmallett#include <machine/asm.h> 62202046Simp#include <machine/cache.h> 63178172Simp#include <machine/clock.h> 64178172Simp#include <machine/cpu.h> 65178172Simp#include <machine/md_var.h> 66178172Simp#include <machine/pcb.h> 67178172Simp 68178172Simp#include <vm/vm.h> 69206714Sjmallett#include <vm/vm_extern.h> 70206714Sjmallett#include <vm/pmap.h> 71178172Simp#include <vm/vm_kern.h> 72206714Sjmallett#include <vm/vm_map.h> 73178172Simp#include <vm/vm_page.h> 74206714Sjmallett#include <vm/vm_pageout.h> 75206714Sjmallett#include <vm/vm_param.h> 76206714Sjmallett#include <vm/uma.h> 77206714Sjmallett#include <vm/uma_int.h> 78178172Simp 79178172Simp#include <sys/user.h> 80178172Simp#include <sys/mbuf.h> 81178172Simp#include <sys/sf_buf.h> 82178172Simp 83178172Simp#ifndef NSFBUFS 84178172Simp#define NSFBUFS (512 + maxusers * 16) 85178172Simp#endif 86178172Simp 87217944Sjchandra#ifndef __mips_n64 88178172Simpstatic void sf_buf_init(void *arg); 89178172SimpSYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); 90178172Simp 91178172Simp/* 92206714Sjmallett * Expanded sf_freelist head. Really an SLIST_HEAD() in disguise, with the 93206714Sjmallett * sf_freelist head with the sf_lock mutex. 94178172Simp */ 95206714Sjmallettstatic struct { 96206714Sjmallett SLIST_HEAD(, sf_buf) sf_head; 97206714Sjmallett struct mtx sf_lock; 98206714Sjmallett} sf_freelist; 99178172Simp 100178172Simpstatic u_int sf_buf_alloc_want; 101217944Sjchandra#endif 102178172Simp 103178172Simp/* 104178172Simp * Finish a fork operation, with process p2 nearly set up. 105178172Simp * Copy and update the pcb, set up the stack so that the child 106178172Simp * ready to run and return to user mode. 107178172Simp */ 108178172Simpvoid 109178172Simpcpu_fork(register struct thread *td1,register struct proc *p2, 110178172Simp struct thread *td2,int flags) 111178172Simp{ 112178172Simp register struct proc *p1; 113178172Simp struct pcb *pcb2; 114178172Simp 115178172Simp p1 = td1->td_proc; 116178172Simp if ((flags & RFPROC) == 0) 117178172Simp return; 118178172Simp /* It is assumed that the vm_thread_alloc called 119178172Simp * cpu_thread_alloc() before cpu_fork is called. 120178172Simp */ 121178172Simp 122178172Simp /* Point the pcb to the top of the stack */ 123178172Simp pcb2 = td2->td_pcb; 124178172Simp 125178172Simp /* Copy p1's pcb, note that in this case 126178172Simp * our pcb also includes the td_frame being copied 127178172Simp * too. The older mips2 code did an additional copy 128215034Sbrucec * of the td_frame, for us that's not needed any 129215034Sbrucec * longer (this copy does them both) 130178172Simp */ 131178172Simp bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); 132178172Simp 133178172Simp /* Point mdproc and then copy over td1's contents 134178172Simp * md_proc is empty for MIPS 135178172Simp */ 136178172Simp td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED; 137178172Simp 138178172Simp /* 139178172Simp * Set up return-value registers as fork() libc stub expects. 140178172Simp */ 141178172Simp td2->td_frame->v0 = 0; 142178172Simp td2->td_frame->v1 = 1; 143178172Simp td2->td_frame->a3 = 0; 144178172Simp 145178172Simp if (td1 == PCPU_GET(fpcurthread)) 146178172Simp MipsSaveCurFPState(td1); 147178172Simp 148209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 149178172Simp /* Make sp 64-bit aligned */ 150202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb & 151206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 152209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 153209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2; 154209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame; 155210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 156210644Sjchandra (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 157178172Simp /* 158178172Simp * FREEBSD_DEVELOPERS_FIXME: 159178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 160178172Simp * and/or bits in other standard MIPS registers (if CPU-Specific) 161178172Simp * that are needed. 162178172Simp */ 163178172Simp 164202046Simp td2->td_md.md_tls = td1->td_md.md_tls; 165178172Simp td2->td_md.md_saved_intr = MIPS_SR_INT_IE; 166178172Simp td2->td_md.md_spinlock_count = 1; 167210311Sjmallett#ifdef CPU_CNMIPS 168229677Sgonzo if (td1->td_md.md_flags & MDTD_COP2USED) { 169229677Sgonzo if (td1->td_md.md_cop2owner == COP2_OWNER_USERLAND) { 170229677Sgonzo if (td1->td_md.md_ucop2) 171229677Sgonzo octeon_cop2_save(td1->td_md.md_ucop2); 172229677Sgonzo else 173229677Sgonzo panic("cpu_fork: ucop2 is NULL but COP2 is enabled"); 174229677Sgonzo } 175229677Sgonzo else { 176229677Sgonzo if (td1->td_md.md_cop2) 177229677Sgonzo octeon_cop2_save(td1->td_md.md_cop2); 178229677Sgonzo else 179229677Sgonzo panic("cpu_fork: cop2 is NULL but COP2 is enabled"); 180229677Sgonzo } 181229677Sgonzo } 182229677Sgonzo 183229677Sgonzo if (td1->td_md.md_cop2) { 184229677Sgonzo td2->td_md.md_cop2 = octeon_cop2_alloc_ctx(); 185229677Sgonzo memcpy(td2->td_md.md_cop2, td1->td_md.md_cop2, 186229677Sgonzo sizeof(*td1->td_md.md_cop2)); 187229677Sgonzo } 188229677Sgonzo if (td1->td_md.md_ucop2) { 189229677Sgonzo td2->td_md.md_ucop2 = octeon_cop2_alloc_ctx(); 190229677Sgonzo memcpy(td2->td_md.md_ucop2, td1->td_md.md_ucop2, 191229677Sgonzo sizeof(*td1->td_md.md_ucop2)); 192229677Sgonzo } 193229677Sgonzo td2->td_md.md_cop2owner = td1->td_md.md_cop2owner; 194229677Sgonzo pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX; 195229677Sgonzo /* Clear COP2 bits for userland & kernel */ 196229677Sgonzo td2->td_frame->sr &= ~MIPS_SR_COP_2_BIT; 197229677Sgonzo pcb2->pcb_context[PCB_REG_SR] &= ~MIPS_SR_COP_2_BIT; 198178172Simp#endif 199178172Simp} 200178172Simp 201178172Simp/* 202178172Simp * Intercept the return address from a freshly forked process that has NOT 203178172Simp * been scheduled yet. 204178172Simp * 205178172Simp * This is needed to make kernel threads stay in kernel mode. 206178172Simp */ 207178172Simpvoid 208178172Simpcpu_set_fork_handler(struct thread *td, void (*func) __P((void *)), void *arg) 209178172Simp{ 210178172Simp /* 211178172Simp * Note that the trap frame follows the args, so the function 212178172Simp * is really called like this: func(arg, frame); 213178172Simp */ 214209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func; 215209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg; 216178172Simp} 217178172Simp 218178172Simpvoid 219178172Simpcpu_exit(struct thread *td) 220178172Simp{ 221178172Simp} 222178172Simp 223178172Simpvoid 224178172Simpcpu_thread_exit(struct thread *td) 225178172Simp{ 226178172Simp 227178172Simp if (PCPU_GET(fpcurthread) == td) 228178172Simp PCPU_GET(fpcurthread) = (struct thread *)0; 229229677Sgonzo#ifdef CPU_CNMIPS 230229677Sgonzo if (td->td_md.md_cop2) 231229677Sgonzo memset(td->td_md.md_cop2, 0, 232229677Sgonzo sizeof(*td->td_md.md_cop2)); 233229677Sgonzo if (td->td_md.md_ucop2) 234229677Sgonzo memset(td->td_md.md_ucop2, 0, 235229677Sgonzo sizeof(*td->td_md.md_ucop2)); 236229677Sgonzo#endif 237178172Simp} 238178172Simp 239178172Simpvoid 240178172Simpcpu_thread_free(struct thread *td) 241178172Simp{ 242229677Sgonzo#ifdef CPU_CNMIPS 243229677Sgonzo if (td->td_md.md_cop2) 244229677Sgonzo octeon_cop2_free_ctx(td->td_md.md_cop2); 245229677Sgonzo if (td->td_md.md_ucop2) 246229677Sgonzo octeon_cop2_free_ctx(td->td_md.md_ucop2); 247229677Sgonzo td->td_md.md_cop2 = NULL; 248229677Sgonzo td->td_md.md_ucop2 = NULL; 249229677Sgonzo#endif 250178172Simp} 251178172Simp 252178172Simpvoid 253178172Simpcpu_thread_clean(struct thread *td) 254178172Simp{ 255178172Simp} 256178172Simp 257178172Simpvoid 258178172Simpcpu_thread_swapin(struct thread *td) 259178172Simp{ 260178172Simp pt_entry_t *pte; 261178172Simp int i; 262178172Simp 263178172Simp /* 264178172Simp * The kstack may be at a different physical address now. 265178172Simp * Cache the PTEs for the Kernel stack in the machine dependent 266178172Simp * part of the thread struct so cpu_switch() can quickly map in 267178172Simp * the pcb struct and kernel stack. 268178172Simp */ 269206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 270206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 271209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 272178172Simp } 273178172Simp} 274178172Simp 275178172Simpvoid 276178172Simpcpu_thread_swapout(struct thread *td) 277178172Simp{ 278178172Simp} 279178172Simp 280178172Simpvoid 281178172Simpcpu_thread_alloc(struct thread *td) 282178172Simp{ 283178172Simp pt_entry_t *pte; 284178172Simp int i; 285178172Simp 286206819Sjmallett KASSERT((td->td_kstack & (1 << PAGE_SHIFT)) == 0, ("kernel stack must be aligned.")); 287206819Sjmallett td->td_pcb = (struct pcb *)(td->td_kstack + 288206819Sjmallett td->td_kstack_pages * PAGE_SIZE) - 1; 289178172Simp td->td_frame = &td->td_pcb->pcb_regs; 290178172Simp 291206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 292206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 293209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 294178172Simp } 295178172Simp} 296178172Simp 297199135Skibvoid 298199135Skibcpu_set_syscall_retval(struct thread *td, int error) 299199135Skib{ 300199135Skib struct trapframe *locr0 = td->td_frame; 301199135Skib unsigned int code; 302199135Skib int quad_syscall; 303199135Skib 304199135Skib code = locr0->v0; 305199135Skib quad_syscall = 0; 306232449Sjmallett#if defined(__mips_n32) || defined(__mips_n64) 307232449Sjmallett#ifdef COMPAT_FREEBSD32 308232449Sjmallett if (code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) 309232449Sjmallett quad_syscall = 1; 310232449Sjmallett#endif 311232449Sjmallett#else 312209500Sjchandra if (code == SYS___syscall) 313209500Sjchandra quad_syscall = 1; 314209500Sjchandra#endif 315209500Sjchandra 316199135Skib if (code == SYS_syscall) 317199135Skib code = locr0->a0; 318199135Skib else if (code == SYS___syscall) { 319209500Sjchandra if (quad_syscall) 320209500Sjchandra code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0; 321209500Sjchandra else 322209500Sjchandra code = locr0->a0; 323199135Skib } 324199135Skib 325199135Skib switch (error) { 326199135Skib case 0: 327199135Skib if (quad_syscall && code != SYS_lseek) { 328199135Skib /* 329199135Skib * System call invoked through the 330199135Skib * SYS___syscall interface but the 331199135Skib * return value is really just 32 332199135Skib * bits. 333199135Skib */ 334199135Skib locr0->v0 = td->td_retval[0]; 335199135Skib if (_QUAD_LOWWORD) 336199135Skib locr0->v1 = td->td_retval[0]; 337199135Skib locr0->a3 = 0; 338199135Skib } else { 339199135Skib locr0->v0 = td->td_retval[0]; 340199135Skib locr0->v1 = td->td_retval[1]; 341199135Skib locr0->a3 = 0; 342199135Skib } 343199135Skib break; 344199135Skib 345199135Skib case ERESTART: 346199135Skib locr0->pc = td->td_pcb->pcb_tpc; 347199135Skib break; 348199135Skib 349199135Skib case EJUSTRETURN: 350199135Skib break; /* nothing to do */ 351199135Skib 352199135Skib default: 353199135Skib if (quad_syscall && code != SYS_lseek) { 354199135Skib locr0->v0 = error; 355199135Skib if (_QUAD_LOWWORD) 356199135Skib locr0->v1 = error; 357199135Skib locr0->a3 = 1; 358199135Skib } else { 359199135Skib locr0->v0 = error; 360199135Skib locr0->a3 = 1; 361199135Skib } 362199135Skib } 363199135Skib} 364199135Skib 365178172Simp/* 366178172Simp * Initialize machine state (pcb and trap frame) for a new thread about to 367178172Simp * upcall. Put enough state in the new thread's PCB to get it to go back 368178172Simp * userret(), where we can intercept it again to set the return (upcall) 369215034Sbrucec * Address and stack, along with those from upcalls that are from other sources 370178172Simp * such as those generated in thread_userret() itself. 371178172Simp */ 372178172Simpvoid 373178172Simpcpu_set_upcall(struct thread *td, struct thread *td0) 374178172Simp{ 375178172Simp struct pcb *pcb2; 376178172Simp 377178172Simp /* Point the pcb to the top of the stack. */ 378178172Simp pcb2 = td->td_pcb; 379178172Simp 380178172Simp /* 381178172Simp * Copy the upcall pcb. This loads kernel regs. 382178172Simp * Those not loaded individually below get their default 383178172Simp * values here. 384178172Simp * 385178172Simp * XXXKSE It might be a good idea to simply skip this as 386178172Simp * the values of the other registers may be unimportant. 387178172Simp * This would remove any requirement for knowing the KSE 388178172Simp * at this time (see the matching comment below for 389178172Simp * more analysis) (need a good safe default). 390178172Simp * In MIPS, the trapframe is the first element of the PCB 391215034Sbrucec * and gets copied when we copy the PCB. No separate copy 392178172Simp * is needed. 393178172Simp */ 394178172Simp bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 395178172Simp 396178172Simp /* 397178172Simp * Set registers for trampoline to user mode. 398178172Simp */ 399178172Simp 400209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 401178172Simp /* Make sp 64-bit aligned */ 402202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb & 403206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 404209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 405209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td; 406209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame; 407202046Simp /* Dont set IE bit in SR. sched lock release will take care of it */ 408210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 409232770Sjmallett (MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 410178172Simp 411178172Simp /* 412178172Simp * FREEBSD_DEVELOPERS_FIXME: 413178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 414178172Simp * that are needed. 415178172Simp */ 416178172Simp 417178172Simp /* SMP Setup to release sched_lock in fork_exit(). */ 418178172Simp td->td_md.md_spinlock_count = 1; 419178172Simp td->td_md.md_saved_intr = MIPS_SR_INT_IE; 420178172Simp#if 0 421178172Simp /* Maybe we need to fix this? */ 422178172Simp td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) | 423210038Simp (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) | 424178172Simp (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK)); 425178172Simp#endif 426178172Simp} 427178172Simp 428178172Simp/* 429178172Simp * Set that machine state for performing an upcall that has to 430178172Simp * be done in thread_userret() so that those upcalls generated 431178172Simp * in thread_userret() itself can be done as well. 432178172Simp */ 433178172Simpvoid 434178172Simpcpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 435178172Simp stack_t *stack) 436178172Simp{ 437178172Simp struct trapframe *tf; 438202046Simp register_t sp; 439178172Simp 440178172Simp /* 441178172Simp * At the point where a function is called, sp must be 8 442178172Simp * byte aligned[for compatibility with 64-bit CPUs] 443178172Simp * in ``See MIPS Run'' by D. Sweetman, p. 269 444178172Simp * align stack */ 445209500Sjchandra sp = ((register_t)(intptr_t)(stack->ss_sp + stack->ss_size) & ~0x7) - 446206834Sjmallett CALLFRAME_SIZ; 447178172Simp 448178172Simp /* 449178172Simp * Set the trap frame to point at the beginning of the uts 450178172Simp * function. 451178172Simp */ 452178172Simp tf = td->td_frame; 453178172Simp bzero(tf, sizeof(struct trapframe)); 454209500Sjchandra tf->sp = sp; 455209500Sjchandra tf->pc = (register_t)(intptr_t)entry; 456202046Simp /* 457202046Simp * MIPS ABI requires T9 to be the same as PC 458202046Simp * in subroutine entry point 459202046Simp */ 460209500Sjchandra tf->t9 = (register_t)(intptr_t)entry; 461209500Sjchandra tf->a0 = (register_t)(intptr_t)arg; 462178172Simp 463202046Simp /* 464202046Simp * Keep interrupt mask 465202046Simp */ 466210644Sjchandra td->td_frame->sr = MIPS_SR_KSU_USER | MIPS_SR_EXL | MIPS_SR_INT_IE | 467210644Sjchandra (mips_rd_status() & MIPS_SR_INT_MASK); 468210644Sjchandra#if defined(__mips_n32) 469210644Sjchandra td->td_frame->sr |= MIPS_SR_PX; 470210644Sjchandra#elif defined(__mips_n64) 471211218Sjchandra td->td_frame->sr |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX; 472210644Sjchandra#endif 473178172Simp/* tf->sr |= (ALL_INT_MASK & idle_mask) | SR_INT_ENAB; */ 474178172Simp /**XXX the above may now be wrong -- mips2 implements this as panic */ 475178172Simp /* 476178172Simp * FREEBSD_DEVELOPERS_FIXME: 477178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 478178172Simp * that are needed. 479178172Simp */ 480178172Simp} 481178172Simp/* 482178172Simp * Convert kernel VA to physical address 483178172Simp */ 484178172Simpu_long 485178172Simpkvtop(void *addr) 486178172Simp{ 487178172Simp vm_offset_t va; 488178172Simp 489178172Simp va = pmap_kextract((vm_offset_t)addr); 490178172Simp if (va == 0) 491178172Simp panic("kvtop: zero page frame"); 492209500Sjchandra return((intptr_t)va); 493178172Simp} 494178172Simp 495178172Simp/* 496178172Simp * Implement the pre-zeroed page mechanism. 497178172Simp * This routine is called from the idle loop. 498178172Simp */ 499178172Simp 500178172Simp#define ZIDLE_LO(v) ((v) * 2 / 3) 501178172Simp#define ZIDLE_HI(v) ((v) * 4 / 5) 502178172Simp 503178172Simp/* 504178172Simp * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 505178172Simp */ 506217944Sjchandra#ifndef __mips_n64 507178172Simpstatic void 508178172Simpsf_buf_init(void *arg) 509178172Simp{ 510178172Simp struct sf_buf *sf_bufs; 511178172Simp vm_offset_t sf_base; 512178172Simp int i; 513178172Simp 514178172Simp nsfbufs = NSFBUFS; 515178172Simp TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); 516178172Simp 517206714Sjmallett mtx_init(&sf_freelist.sf_lock, "sf_bufs list lock", NULL, MTX_DEF); 518206714Sjmallett SLIST_INIT(&sf_freelist.sf_head); 519178172Simp sf_base = kmem_alloc_nofault(kernel_map, nsfbufs * PAGE_SIZE); 520178172Simp sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, 521178172Simp M_NOWAIT | M_ZERO); 522178172Simp for (i = 0; i < nsfbufs; i++) { 523178172Simp sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 524206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, &sf_bufs[i], free_list); 525178172Simp } 526178172Simp sf_buf_alloc_want = 0; 527178172Simp} 528217944Sjchandra#endif 529178172Simp 530178172Simp/* 531206714Sjmallett * Get an sf_buf from the freelist. Will block if none are available. 532178172Simp */ 533178172Simpstruct sf_buf * 534178172Simpsf_buf_alloc(struct vm_page *m, int flags) 535178172Simp{ 536217944Sjchandra#ifndef __mips_n64 537178172Simp struct sf_buf *sf; 538178172Simp int error; 539178172Simp 540206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 541206714Sjmallett while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) { 542178172Simp if (flags & SFB_NOWAIT) 543206714Sjmallett break; 544178172Simp sf_buf_alloc_want++; 545178172Simp mbstat.sf_allocwait++; 546206714Sjmallett error = msleep(&sf_freelist, &sf_freelist.sf_lock, 547178172Simp (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); 548178172Simp sf_buf_alloc_want--; 549178172Simp 550178172Simp /* 551178172Simp * If we got a signal, don't risk going back to sleep. 552178172Simp */ 553178172Simp if (error) 554206714Sjmallett break; 555178172Simp } 556206714Sjmallett if (sf != NULL) { 557206714Sjmallett SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list); 558206714Sjmallett sf->m = m; 559206714Sjmallett nsfbufsused++; 560206714Sjmallett nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 561206714Sjmallett pmap_qenter(sf->kva, &sf->m, 1); 562206714Sjmallett } 563206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 564178172Simp return (sf); 565217944Sjchandra#else 566217944Sjchandra return ((struct sf_buf *)m); 567217944Sjchandra#endif 568178172Simp} 569178172Simp 570178172Simp/* 571206714Sjmallett * Release resources back to the system. 572178172Simp */ 573178172Simpvoid 574178172Simpsf_buf_free(struct sf_buf *sf) 575178172Simp{ 576217944Sjchandra#ifndef __mips_n64 577206714Sjmallett pmap_qremove(sf->kva, 1); 578206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 579206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); 580206714Sjmallett nsfbufsused--; 581206714Sjmallett if (sf_buf_alloc_want > 0) 582217561Skib wakeup(&sf_freelist); 583206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 584217944Sjchandra#endif 585178172Simp} 586178172Simp 587178172Simp/* 588178172Simp * Software interrupt handler for queued VM system processing. 589178172Simp */ 590178172Simpvoid 591178172Simpswi_vm(void *dummy) 592178172Simp{ 593216317Sjchandra 594216317Sjchandra if (busdma_swi_pending) 595216317Sjchandra busdma_swi(); 596178172Simp} 597178172Simp 598178172Simpint 599178172Simpcpu_set_user_tls(struct thread *td, void *tls_base) 600178172Simp{ 601178172Simp 602232577Sgonzo td->td_md.md_tls = (char*)tls_base; 603232449Sjmallett 604232478Sjmallett return (0); 605178172Simp} 606178172Simp 607202046Simp#ifdef DDB 608202046Simp#include <ddb/ddb.h> 609202046Simp 610202046Simp#define DB_PRINT_REG(ptr, regname) \ 611209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname)) 612202046Simp 613202046Simp#define DB_PRINT_REG_ARRAY(ptr, arrname, regname) \ 614209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname])) 615202046Simp 616202999Sneelstatic void 617202999Sneeldump_trapframe(struct trapframe *trapframe) 618202046Simp{ 619202046Simp 620202999Sneel db_printf("Trapframe at %p\n", trapframe); 621202046Simp 622202046Simp DB_PRINT_REG(trapframe, zero); 623202046Simp DB_PRINT_REG(trapframe, ast); 624202046Simp DB_PRINT_REG(trapframe, v0); 625202046Simp DB_PRINT_REG(trapframe, v1); 626202046Simp DB_PRINT_REG(trapframe, a0); 627202046Simp DB_PRINT_REG(trapframe, a1); 628202046Simp DB_PRINT_REG(trapframe, a2); 629202046Simp DB_PRINT_REG(trapframe, a3); 630202046Simp DB_PRINT_REG(trapframe, t0); 631202046Simp DB_PRINT_REG(trapframe, t1); 632202046Simp DB_PRINT_REG(trapframe, t2); 633202046Simp DB_PRINT_REG(trapframe, t3); 634202046Simp DB_PRINT_REG(trapframe, t4); 635202046Simp DB_PRINT_REG(trapframe, t5); 636202046Simp DB_PRINT_REG(trapframe, t6); 637202046Simp DB_PRINT_REG(trapframe, t7); 638202046Simp DB_PRINT_REG(trapframe, s0); 639202046Simp DB_PRINT_REG(trapframe, s1); 640202046Simp DB_PRINT_REG(trapframe, s2); 641202046Simp DB_PRINT_REG(trapframe, s3); 642202046Simp DB_PRINT_REG(trapframe, s4); 643202046Simp DB_PRINT_REG(trapframe, s5); 644202046Simp DB_PRINT_REG(trapframe, s6); 645202046Simp DB_PRINT_REG(trapframe, s7); 646202046Simp DB_PRINT_REG(trapframe, t8); 647202046Simp DB_PRINT_REG(trapframe, t9); 648202046Simp DB_PRINT_REG(trapframe, k0); 649202046Simp DB_PRINT_REG(trapframe, k1); 650202046Simp DB_PRINT_REG(trapframe, gp); 651202046Simp DB_PRINT_REG(trapframe, sp); 652202046Simp DB_PRINT_REG(trapframe, s8); 653202046Simp DB_PRINT_REG(trapframe, ra); 654202046Simp DB_PRINT_REG(trapframe, sr); 655202046Simp DB_PRINT_REG(trapframe, mullo); 656202046Simp DB_PRINT_REG(trapframe, mulhi); 657202046Simp DB_PRINT_REG(trapframe, badvaddr); 658202046Simp DB_PRINT_REG(trapframe, cause); 659202046Simp DB_PRINT_REG(trapframe, pc); 660202999Sneel} 661202046Simp 662202999SneelDB_SHOW_COMMAND(pcb, ddb_dump_pcb) 663202999Sneel{ 664202999Sneel struct thread *td; 665202999Sneel struct pcb *pcb; 666202999Sneel struct trapframe *trapframe; 667202999Sneel 668202999Sneel /* Determine which thread to examine. */ 669202999Sneel if (have_addr) 670202999Sneel td = db_lookup_thread(addr, TRUE); 671202999Sneel else 672202999Sneel td = curthread; 673202999Sneel 674202999Sneel pcb = td->td_pcb; 675202999Sneel 676202999Sneel db_printf("Thread %d at %p\n", td->td_tid, td); 677202999Sneel 678202999Sneel db_printf("PCB at %p\n", pcb); 679202999Sneel 680202999Sneel trapframe = &pcb->pcb_regs; 681202999Sneel dump_trapframe(trapframe); 682202999Sneel 683202046Simp db_printf("PCB Context:\n"); 684202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S0); 685202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S1); 686202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S2); 687202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S3); 688202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S4); 689202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S5); 690202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S6); 691202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S7); 692202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SP); 693202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S8); 694202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_RA); 695202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SR); 696202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_GP); 697202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_PC); 698202046Simp 699206749Sjmallett db_printf("PCB onfault = %p\n", pcb->pcb_onfault); 700202046Simp db_printf("md_saved_intr = 0x%0lx\n", (long)td->td_md.md_saved_intr); 701202046Simp db_printf("md_spinlock_count = %d\n", td->td_md.md_spinlock_count); 702202046Simp 703202046Simp if (td->td_frame != trapframe) { 704202046Simp db_printf("td->td_frame %p is not the same as pcb_regs %p\n", 705202046Simp td->td_frame, trapframe); 706202046Simp } 707202046Simp} 708202046Simp 709202999Sneel/* 710202999Sneel * Dump the trapframe beginning at address specified by first argument. 711202999Sneel */ 712202999SneelDB_SHOW_COMMAND(trapframe, ddb_dump_trapframe) 713202999Sneel{ 714202999Sneel 715202999Sneel if (!have_addr) 716202999Sneel return; 717202999Sneel 718202999Sneel dump_trapframe((struct trapframe *)addr); 719202999Sneel} 720202999Sneel 721202046Simp#endif /* DDB */ 722