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$"); 43178172Simp 44232449Sjmallett#include "opt_compat.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> 52232449Sjmallett#include <sys/sysent.h> 53178172Simp#include <sys/buf.h> 54178172Simp#include <sys/vnode.h> 55178172Simp#include <sys/vmmeter.h> 56178172Simp#include <sys/kernel.h> 57178172Simp#include <sys/sysctl.h> 58178172Simp#include <sys/unistd.h> 59178172Simp 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> 79255289Sglebius#ifndef __mips_n64 80178172Simp#include <sys/sf_buf.h> 81255289Sglebius#endif 82178172Simp 83250137Simp/* Duplicated from asm.h */ 84250137Simp#if defined(__mips_o32) 85250137Simp#define SZREG 4 86250137Simp#else 87250137Simp#define SZREG 8 88250137Simp#endif 89250137Simp#if defined(__mips_o32) || defined(__mips_o64) 90250137Simp#define CALLFRAME_SIZ (SZREG * (4 + 2)) 91250137Simp#elif defined(__mips_n32) || defined(__mips_n64) 92250137Simp#define CALLFRAME_SIZ (SZREG * 4) 93250137Simp#endif 94250137Simp 95217944Sjchandra#ifndef __mips_n64 96255786Sglebius 97255786Sglebius#ifndef NSFBUFS 98255786Sglebius#define NSFBUFS (512 + maxusers * 16) 99255786Sglebius#endif 100255786Sglebius 101255786Sglebiusstatic int nsfbufs; 102255786Sglebiusstatic int nsfbufspeak; 103255786Sglebiusstatic int nsfbufsused; 104255786Sglebius 105255786SglebiusSYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0, 106255786Sglebius "Maximum number of sendfile(2) sf_bufs available"); 107255786SglebiusSYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0, 108255786Sglebius "Number of sendfile(2) sf_bufs at peak usage"); 109255786SglebiusSYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0, 110255786Sglebius "Number of sendfile(2) sf_bufs in use"); 111255786Sglebius 112178172Simpstatic void sf_buf_init(void *arg); 113178172SimpSYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); 114178172Simp 115178172Simp/* 116206714Sjmallett * Expanded sf_freelist head. Really an SLIST_HEAD() in disguise, with the 117206714Sjmallett * sf_freelist head with the sf_lock mutex. 118178172Simp */ 119206714Sjmallettstatic struct { 120206714Sjmallett SLIST_HEAD(, sf_buf) sf_head; 121206714Sjmallett struct mtx sf_lock; 122206714Sjmallett} sf_freelist; 123178172Simp 124178172Simpstatic u_int sf_buf_alloc_want; 125255786Sglebius#endif /* !__mips_n64 */ 126178172Simp 127178172Simp/* 128178172Simp * Finish a fork operation, with process p2 nearly set up. 129178172Simp * Copy and update the pcb, set up the stack so that the child 130178172Simp * ready to run and return to user mode. 131178172Simp */ 132178172Simpvoid 133178172Simpcpu_fork(register struct thread *td1,register struct proc *p2, 134178172Simp struct thread *td2,int flags) 135178172Simp{ 136178172Simp register struct proc *p1; 137178172Simp struct pcb *pcb2; 138178172Simp 139178172Simp p1 = td1->td_proc; 140178172Simp if ((flags & RFPROC) == 0) 141178172Simp return; 142178172Simp /* It is assumed that the vm_thread_alloc called 143178172Simp * cpu_thread_alloc() before cpu_fork is called. 144178172Simp */ 145178172Simp 146178172Simp /* Point the pcb to the top of the stack */ 147178172Simp pcb2 = td2->td_pcb; 148178172Simp 149178172Simp /* Copy p1's pcb, note that in this case 150178172Simp * our pcb also includes the td_frame being copied 151178172Simp * too. The older mips2 code did an additional copy 152215034Sbrucec * of the td_frame, for us that's not needed any 153215034Sbrucec * longer (this copy does them both) 154178172Simp */ 155178172Simp bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); 156178172Simp 157178172Simp /* Point mdproc and then copy over td1's contents 158178172Simp * md_proc is empty for MIPS 159178172Simp */ 160178172Simp td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED; 161178172Simp 162178172Simp /* 163178172Simp * Set up return-value registers as fork() libc stub expects. 164178172Simp */ 165178172Simp td2->td_frame->v0 = 0; 166178172Simp td2->td_frame->v1 = 1; 167178172Simp td2->td_frame->a3 = 0; 168178172Simp 169178172Simp if (td1 == PCPU_GET(fpcurthread)) 170178172Simp MipsSaveCurFPState(td1); 171178172Simp 172209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 173178172Simp /* Make sp 64-bit aligned */ 174202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb & 175206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 176209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 177209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2; 178209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame; 179210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 180210644Sjchandra (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 181178172Simp /* 182178172Simp * FREEBSD_DEVELOPERS_FIXME: 183178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 184178172Simp * and/or bits in other standard MIPS registers (if CPU-Specific) 185178172Simp * that are needed. 186178172Simp */ 187178172Simp 188202046Simp td2->td_md.md_tls = td1->td_md.md_tls; 189178172Simp td2->td_md.md_saved_intr = MIPS_SR_INT_IE; 190178172Simp td2->td_md.md_spinlock_count = 1; 191210311Sjmallett#ifdef CPU_CNMIPS 192229677Sgonzo if (td1->td_md.md_flags & MDTD_COP2USED) { 193229677Sgonzo if (td1->td_md.md_cop2owner == COP2_OWNER_USERLAND) { 194229677Sgonzo if (td1->td_md.md_ucop2) 195229677Sgonzo octeon_cop2_save(td1->td_md.md_ucop2); 196229677Sgonzo else 197229677Sgonzo panic("cpu_fork: ucop2 is NULL but COP2 is enabled"); 198229677Sgonzo } 199229677Sgonzo else { 200229677Sgonzo if (td1->td_md.md_cop2) 201229677Sgonzo octeon_cop2_save(td1->td_md.md_cop2); 202229677Sgonzo else 203229677Sgonzo panic("cpu_fork: cop2 is NULL but COP2 is enabled"); 204229677Sgonzo } 205229677Sgonzo } 206229677Sgonzo 207229677Sgonzo if (td1->td_md.md_cop2) { 208229677Sgonzo td2->td_md.md_cop2 = octeon_cop2_alloc_ctx(); 209229677Sgonzo memcpy(td2->td_md.md_cop2, td1->td_md.md_cop2, 210229677Sgonzo sizeof(*td1->td_md.md_cop2)); 211229677Sgonzo } 212229677Sgonzo if (td1->td_md.md_ucop2) { 213229677Sgonzo td2->td_md.md_ucop2 = octeon_cop2_alloc_ctx(); 214229677Sgonzo memcpy(td2->td_md.md_ucop2, td1->td_md.md_ucop2, 215229677Sgonzo sizeof(*td1->td_md.md_ucop2)); 216229677Sgonzo } 217229677Sgonzo td2->td_md.md_cop2owner = td1->td_md.md_cop2owner; 218229677Sgonzo pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX; 219229677Sgonzo /* Clear COP2 bits for userland & kernel */ 220229677Sgonzo td2->td_frame->sr &= ~MIPS_SR_COP_2_BIT; 221229677Sgonzo pcb2->pcb_context[PCB_REG_SR] &= ~MIPS_SR_COP_2_BIT; 222178172Simp#endif 223178172Simp} 224178172Simp 225178172Simp/* 226178172Simp * Intercept the return address from a freshly forked process that has NOT 227178172Simp * been scheduled yet. 228178172Simp * 229178172Simp * This is needed to make kernel threads stay in kernel mode. 230178172Simp */ 231178172Simpvoid 232178172Simpcpu_set_fork_handler(struct thread *td, void (*func) __P((void *)), void *arg) 233178172Simp{ 234178172Simp /* 235178172Simp * Note that the trap frame follows the args, so the function 236178172Simp * is really called like this: func(arg, frame); 237178172Simp */ 238209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func; 239209500Sjchandra td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg; 240178172Simp} 241178172Simp 242178172Simpvoid 243178172Simpcpu_exit(struct thread *td) 244178172Simp{ 245178172Simp} 246178172Simp 247178172Simpvoid 248178172Simpcpu_thread_exit(struct thread *td) 249178172Simp{ 250178172Simp 251178172Simp if (PCPU_GET(fpcurthread) == td) 252178172Simp PCPU_GET(fpcurthread) = (struct thread *)0; 253229677Sgonzo#ifdef CPU_CNMIPS 254229677Sgonzo if (td->td_md.md_cop2) 255229677Sgonzo memset(td->td_md.md_cop2, 0, 256229677Sgonzo sizeof(*td->td_md.md_cop2)); 257229677Sgonzo if (td->td_md.md_ucop2) 258229677Sgonzo memset(td->td_md.md_ucop2, 0, 259229677Sgonzo sizeof(*td->td_md.md_ucop2)); 260229677Sgonzo#endif 261178172Simp} 262178172Simp 263178172Simpvoid 264178172Simpcpu_thread_free(struct thread *td) 265178172Simp{ 266229677Sgonzo#ifdef CPU_CNMIPS 267229677Sgonzo if (td->td_md.md_cop2) 268229677Sgonzo octeon_cop2_free_ctx(td->td_md.md_cop2); 269229677Sgonzo if (td->td_md.md_ucop2) 270229677Sgonzo octeon_cop2_free_ctx(td->td_md.md_ucop2); 271229677Sgonzo td->td_md.md_cop2 = NULL; 272229677Sgonzo td->td_md.md_ucop2 = NULL; 273229677Sgonzo#endif 274178172Simp} 275178172Simp 276178172Simpvoid 277178172Simpcpu_thread_clean(struct thread *td) 278178172Simp{ 279178172Simp} 280178172Simp 281178172Simpvoid 282178172Simpcpu_thread_swapin(struct thread *td) 283178172Simp{ 284178172Simp pt_entry_t *pte; 285178172Simp int i; 286178172Simp 287178172Simp /* 288178172Simp * The kstack may be at a different physical address now. 289178172Simp * Cache the PTEs for the Kernel stack in the machine dependent 290178172Simp * part of the thread struct so cpu_switch() can quickly map in 291178172Simp * the pcb struct and kernel stack. 292178172Simp */ 293206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 294206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 295209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 296178172Simp } 297178172Simp} 298178172Simp 299178172Simpvoid 300178172Simpcpu_thread_swapout(struct thread *td) 301178172Simp{ 302178172Simp} 303178172Simp 304178172Simpvoid 305178172Simpcpu_thread_alloc(struct thread *td) 306178172Simp{ 307178172Simp pt_entry_t *pte; 308178172Simp int i; 309178172Simp 310206819Sjmallett KASSERT((td->td_kstack & (1 << PAGE_SHIFT)) == 0, ("kernel stack must be aligned.")); 311206819Sjmallett td->td_pcb = (struct pcb *)(td->td_kstack + 312206819Sjmallett td->td_kstack_pages * PAGE_SIZE) - 1; 313178172Simp td->td_frame = &td->td_pcb->pcb_regs; 314178172Simp 315206819Sjmallett for (i = 0; i < KSTACK_PAGES; i++) { 316206819Sjmallett pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 317209482Sjchandra td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 318178172Simp } 319178172Simp} 320178172Simp 321199135Skibvoid 322199135Skibcpu_set_syscall_retval(struct thread *td, int error) 323199135Skib{ 324199135Skib struct trapframe *locr0 = td->td_frame; 325199135Skib unsigned int code; 326199135Skib int quad_syscall; 327199135Skib 328199135Skib code = locr0->v0; 329199135Skib quad_syscall = 0; 330232449Sjmallett#if defined(__mips_n32) || defined(__mips_n64) 331232449Sjmallett#ifdef COMPAT_FREEBSD32 332232449Sjmallett if (code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) 333232449Sjmallett quad_syscall = 1; 334232449Sjmallett#endif 335232449Sjmallett#else 336209500Sjchandra if (code == SYS___syscall) 337209500Sjchandra quad_syscall = 1; 338209500Sjchandra#endif 339209500Sjchandra 340199135Skib if (code == SYS_syscall) 341199135Skib code = locr0->a0; 342199135Skib else if (code == SYS___syscall) { 343209500Sjchandra if (quad_syscall) 344209500Sjchandra code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0; 345209500Sjchandra else 346209500Sjchandra code = locr0->a0; 347199135Skib } 348199135Skib 349199135Skib switch (error) { 350199135Skib case 0: 351199135Skib if (quad_syscall && code != SYS_lseek) { 352199135Skib /* 353199135Skib * System call invoked through the 354199135Skib * SYS___syscall interface but the 355199135Skib * return value is really just 32 356199135Skib * bits. 357199135Skib */ 358199135Skib locr0->v0 = td->td_retval[0]; 359199135Skib if (_QUAD_LOWWORD) 360199135Skib locr0->v1 = td->td_retval[0]; 361199135Skib locr0->a3 = 0; 362199135Skib } else { 363199135Skib locr0->v0 = td->td_retval[0]; 364199135Skib locr0->v1 = td->td_retval[1]; 365199135Skib locr0->a3 = 0; 366199135Skib } 367199135Skib break; 368199135Skib 369199135Skib case ERESTART: 370199135Skib locr0->pc = td->td_pcb->pcb_tpc; 371199135Skib break; 372199135Skib 373199135Skib case EJUSTRETURN: 374199135Skib break; /* nothing to do */ 375199135Skib 376199135Skib default: 377199135Skib if (quad_syscall && code != SYS_lseek) { 378199135Skib locr0->v0 = error; 379199135Skib if (_QUAD_LOWWORD) 380199135Skib locr0->v1 = error; 381199135Skib locr0->a3 = 1; 382199135Skib } else { 383199135Skib locr0->v0 = error; 384199135Skib locr0->a3 = 1; 385199135Skib } 386199135Skib } 387199135Skib} 388199135Skib 389178172Simp/* 390178172Simp * Initialize machine state (pcb and trap frame) for a new thread about to 391178172Simp * upcall. Put enough state in the new thread's PCB to get it to go back 392178172Simp * userret(), where we can intercept it again to set the return (upcall) 393215034Sbrucec * Address and stack, along with those from upcalls that are from other sources 394178172Simp * such as those generated in thread_userret() itself. 395178172Simp */ 396178172Simpvoid 397178172Simpcpu_set_upcall(struct thread *td, struct thread *td0) 398178172Simp{ 399178172Simp struct pcb *pcb2; 400178172Simp 401178172Simp /* Point the pcb to the top of the stack. */ 402178172Simp pcb2 = td->td_pcb; 403178172Simp 404178172Simp /* 405178172Simp * Copy the upcall pcb. This loads kernel regs. 406178172Simp * Those not loaded individually below get their default 407178172Simp * values here. 408178172Simp * 409178172Simp * XXXKSE It might be a good idea to simply skip this as 410178172Simp * the values of the other registers may be unimportant. 411178172Simp * This would remove any requirement for knowing the KSE 412178172Simp * at this time (see the matching comment below for 413178172Simp * more analysis) (need a good safe default). 414178172Simp * In MIPS, the trapframe is the first element of the PCB 415215034Sbrucec * and gets copied when we copy the PCB. No separate copy 416178172Simp * is needed. 417178172Simp */ 418178172Simp bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 419178172Simp 420178172Simp /* 421178172Simp * Set registers for trampoline to user mode. 422178172Simp */ 423178172Simp 424209500Sjchandra pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 425178172Simp /* Make sp 64-bit aligned */ 426202046Simp pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb & 427206834Sjmallett ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 428209500Sjchandra pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 429209500Sjchandra pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td; 430209500Sjchandra pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame; 431202046Simp /* Dont set IE bit in SR. sched lock release will take care of it */ 432210644Sjchandra pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 433232770Sjmallett (MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 434178172Simp 435178172Simp /* 436178172Simp * FREEBSD_DEVELOPERS_FIXME: 437178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 438178172Simp * that are needed. 439178172Simp */ 440178172Simp 441178172Simp /* SMP Setup to release sched_lock in fork_exit(). */ 442178172Simp td->td_md.md_spinlock_count = 1; 443178172Simp td->td_md.md_saved_intr = MIPS_SR_INT_IE; 444178172Simp#if 0 445178172Simp /* Maybe we need to fix this? */ 446178172Simp td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) | 447210038Simp (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) | 448178172Simp (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK)); 449178172Simp#endif 450178172Simp} 451178172Simp 452178172Simp/* 453178172Simp * Set that machine state for performing an upcall that has to 454178172Simp * be done in thread_userret() so that those upcalls generated 455178172Simp * in thread_userret() itself can be done as well. 456178172Simp */ 457178172Simpvoid 458178172Simpcpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 459178172Simp stack_t *stack) 460178172Simp{ 461178172Simp struct trapframe *tf; 462202046Simp register_t sp; 463178172Simp 464178172Simp /* 465250137Simp * At the point where a function is called, sp must be 8 466250137Simp * byte aligned[for compatibility with 64-bit CPUs] 467250137Simp * in ``See MIPS Run'' by D. Sweetman, p. 269 468250137Simp * align stack 469250137Simp */ 470209500Sjchandra sp = ((register_t)(intptr_t)(stack->ss_sp + stack->ss_size) & ~0x7) - 471206834Sjmallett CALLFRAME_SIZ; 472178172Simp 473178172Simp /* 474178172Simp * Set the trap frame to point at the beginning of the uts 475178172Simp * function. 476178172Simp */ 477178172Simp tf = td->td_frame; 478178172Simp bzero(tf, sizeof(struct trapframe)); 479209500Sjchandra tf->sp = sp; 480209500Sjchandra tf->pc = (register_t)(intptr_t)entry; 481202046Simp /* 482202046Simp * MIPS ABI requires T9 to be the same as PC 483202046Simp * in subroutine entry point 484202046Simp */ 485209500Sjchandra tf->t9 = (register_t)(intptr_t)entry; 486209500Sjchandra tf->a0 = (register_t)(intptr_t)arg; 487178172Simp 488202046Simp /* 489202046Simp * Keep interrupt mask 490202046Simp */ 491210644Sjchandra td->td_frame->sr = MIPS_SR_KSU_USER | MIPS_SR_EXL | MIPS_SR_INT_IE | 492210644Sjchandra (mips_rd_status() & MIPS_SR_INT_MASK); 493210644Sjchandra#if defined(__mips_n32) 494210644Sjchandra td->td_frame->sr |= MIPS_SR_PX; 495210644Sjchandra#elif defined(__mips_n64) 496211218Sjchandra td->td_frame->sr |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX; 497210644Sjchandra#endif 498178172Simp/* tf->sr |= (ALL_INT_MASK & idle_mask) | SR_INT_ENAB; */ 499178172Simp /**XXX the above may now be wrong -- mips2 implements this as panic */ 500178172Simp /* 501178172Simp * FREEBSD_DEVELOPERS_FIXME: 502178172Simp * Setup any other CPU-Specific registers (Not MIPS Standard) 503178172Simp * that are needed. 504178172Simp */ 505178172Simp} 506178172Simp 507178172Simp/* 508178172Simp * Implement the pre-zeroed page mechanism. 509178172Simp * This routine is called from the idle loop. 510178172Simp */ 511178172Simp 512178172Simp#define ZIDLE_LO(v) ((v) * 2 / 3) 513178172Simp#define ZIDLE_HI(v) ((v) * 4 / 5) 514178172Simp 515178172Simp/* 516178172Simp * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 517178172Simp */ 518217944Sjchandra#ifndef __mips_n64 519178172Simpstatic void 520178172Simpsf_buf_init(void *arg) 521178172Simp{ 522178172Simp struct sf_buf *sf_bufs; 523178172Simp vm_offset_t sf_base; 524178172Simp int i; 525178172Simp 526178172Simp nsfbufs = NSFBUFS; 527178172Simp TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); 528178172Simp 529206714Sjmallett mtx_init(&sf_freelist.sf_lock, "sf_bufs list lock", NULL, MTX_DEF); 530206714Sjmallett SLIST_INIT(&sf_freelist.sf_head); 531254025Sjeff sf_base = kva_alloc(nsfbufs * PAGE_SIZE); 532178172Simp sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, 533178172Simp M_NOWAIT | M_ZERO); 534178172Simp for (i = 0; i < nsfbufs; i++) { 535178172Simp sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 536206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, &sf_bufs[i], free_list); 537178172Simp } 538178172Simp sf_buf_alloc_want = 0; 539178172Simp} 540178172Simp 541178172Simp/* 542206714Sjmallett * Get an sf_buf from the freelist. Will block if none are available. 543178172Simp */ 544178172Simpstruct sf_buf * 545178172Simpsf_buf_alloc(struct vm_page *m, int flags) 546178172Simp{ 547178172Simp struct sf_buf *sf; 548178172Simp int error; 549178172Simp 550206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 551206714Sjmallett while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) { 552178172Simp if (flags & SFB_NOWAIT) 553206714Sjmallett break; 554178172Simp sf_buf_alloc_want++; 555253351Sae SFSTAT_INC(sf_allocwait); 556206714Sjmallett error = msleep(&sf_freelist, &sf_freelist.sf_lock, 557178172Simp (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); 558178172Simp sf_buf_alloc_want--; 559178172Simp 560178172Simp /* 561178172Simp * If we got a signal, don't risk going back to sleep. 562178172Simp */ 563178172Simp if (error) 564206714Sjmallett break; 565178172Simp } 566206714Sjmallett if (sf != NULL) { 567206714Sjmallett SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list); 568206714Sjmallett sf->m = m; 569206714Sjmallett nsfbufsused++; 570206714Sjmallett nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 571206714Sjmallett pmap_qenter(sf->kva, &sf->m, 1); 572206714Sjmallett } 573206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 574178172Simp return (sf); 575178172Simp} 576178172Simp 577178172Simp/* 578206714Sjmallett * Release resources back to the system. 579178172Simp */ 580178172Simpvoid 581178172Simpsf_buf_free(struct sf_buf *sf) 582178172Simp{ 583206714Sjmallett pmap_qremove(sf->kva, 1); 584206714Sjmallett mtx_lock(&sf_freelist.sf_lock); 585206714Sjmallett SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); 586206714Sjmallett nsfbufsused--; 587206714Sjmallett if (sf_buf_alloc_want > 0) 588217561Skib wakeup(&sf_freelist); 589206714Sjmallett mtx_unlock(&sf_freelist.sf_lock); 590178172Simp} 591255289Sglebius#endif /* !__mips_n64 */ 592178172Simp 593178172Simp/* 594178172Simp * Software interrupt handler for queued VM system processing. 595178172Simp */ 596178172Simpvoid 597178172Simpswi_vm(void *dummy) 598178172Simp{ 599216317Sjchandra 600216317Sjchandra if (busdma_swi_pending) 601216317Sjchandra busdma_swi(); 602178172Simp} 603178172Simp 604178172Simpint 605178172Simpcpu_set_user_tls(struct thread *td, void *tls_base) 606178172Simp{ 607178172Simp 608232577Sgonzo td->td_md.md_tls = (char*)tls_base; 609232449Sjmallett 610232478Sjmallett return (0); 611178172Simp} 612178172Simp 613202046Simp#ifdef DDB 614202046Simp#include <ddb/ddb.h> 615202046Simp 616202046Simp#define DB_PRINT_REG(ptr, regname) \ 617209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname)) 618202046Simp 619202046Simp#define DB_PRINT_REG_ARRAY(ptr, arrname, regname) \ 620209500Sjchandra db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname])) 621202046Simp 622202999Sneelstatic void 623202999Sneeldump_trapframe(struct trapframe *trapframe) 624202046Simp{ 625202046Simp 626202999Sneel db_printf("Trapframe at %p\n", trapframe); 627202046Simp 628202046Simp DB_PRINT_REG(trapframe, zero); 629202046Simp DB_PRINT_REG(trapframe, ast); 630202046Simp DB_PRINT_REG(trapframe, v0); 631202046Simp DB_PRINT_REG(trapframe, v1); 632202046Simp DB_PRINT_REG(trapframe, a0); 633202046Simp DB_PRINT_REG(trapframe, a1); 634202046Simp DB_PRINT_REG(trapframe, a2); 635202046Simp DB_PRINT_REG(trapframe, a3); 636249790Simp#if defined(__mips_n32) || defined(__mips_n64) 637249790Simp DB_PRINT_REG(trapframe, a4); 638249790Simp DB_PRINT_REG(trapframe, a5); 639249790Simp DB_PRINT_REG(trapframe, a6); 640249790Simp DB_PRINT_REG(trapframe, a7); 641202046Simp DB_PRINT_REG(trapframe, t0); 642202046Simp DB_PRINT_REG(trapframe, t1); 643202046Simp DB_PRINT_REG(trapframe, t2); 644202046Simp DB_PRINT_REG(trapframe, t3); 645249790Simp#else 646249790Simp DB_PRINT_REG(trapframe, t0); 647249790Simp DB_PRINT_REG(trapframe, t1); 648249790Simp DB_PRINT_REG(trapframe, t2); 649249790Simp DB_PRINT_REG(trapframe, t3); 650202046Simp DB_PRINT_REG(trapframe, t4); 651202046Simp DB_PRINT_REG(trapframe, t5); 652202046Simp DB_PRINT_REG(trapframe, t6); 653202046Simp DB_PRINT_REG(trapframe, t7); 654249790Simp#endif 655202046Simp DB_PRINT_REG(trapframe, s0); 656202046Simp DB_PRINT_REG(trapframe, s1); 657202046Simp DB_PRINT_REG(trapframe, s2); 658202046Simp DB_PRINT_REG(trapframe, s3); 659202046Simp DB_PRINT_REG(trapframe, s4); 660202046Simp DB_PRINT_REG(trapframe, s5); 661202046Simp DB_PRINT_REG(trapframe, s6); 662202046Simp DB_PRINT_REG(trapframe, s7); 663202046Simp DB_PRINT_REG(trapframe, t8); 664202046Simp DB_PRINT_REG(trapframe, t9); 665202046Simp DB_PRINT_REG(trapframe, k0); 666202046Simp DB_PRINT_REG(trapframe, k1); 667202046Simp DB_PRINT_REG(trapframe, gp); 668202046Simp DB_PRINT_REG(trapframe, sp); 669202046Simp DB_PRINT_REG(trapframe, s8); 670202046Simp DB_PRINT_REG(trapframe, ra); 671202046Simp DB_PRINT_REG(trapframe, sr); 672202046Simp DB_PRINT_REG(trapframe, mullo); 673202046Simp DB_PRINT_REG(trapframe, mulhi); 674202046Simp DB_PRINT_REG(trapframe, badvaddr); 675202046Simp DB_PRINT_REG(trapframe, cause); 676202046Simp DB_PRINT_REG(trapframe, pc); 677202999Sneel} 678202046Simp 679202999SneelDB_SHOW_COMMAND(pcb, ddb_dump_pcb) 680202999Sneel{ 681202999Sneel struct thread *td; 682202999Sneel struct pcb *pcb; 683202999Sneel struct trapframe *trapframe; 684202999Sneel 685202999Sneel /* Determine which thread to examine. */ 686202999Sneel if (have_addr) 687202999Sneel td = db_lookup_thread(addr, TRUE); 688202999Sneel else 689202999Sneel td = curthread; 690202999Sneel 691202999Sneel pcb = td->td_pcb; 692202999Sneel 693202999Sneel db_printf("Thread %d at %p\n", td->td_tid, td); 694202999Sneel 695202999Sneel db_printf("PCB at %p\n", pcb); 696202999Sneel 697202999Sneel trapframe = &pcb->pcb_regs; 698202999Sneel dump_trapframe(trapframe); 699202999Sneel 700202046Simp db_printf("PCB Context:\n"); 701202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S0); 702202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S1); 703202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S2); 704202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S3); 705202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S4); 706202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S5); 707202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S6); 708202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S7); 709202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SP); 710202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S8); 711202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_RA); 712202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SR); 713202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_GP); 714202046Simp DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_PC); 715202046Simp 716206749Sjmallett db_printf("PCB onfault = %p\n", pcb->pcb_onfault); 717202046Simp db_printf("md_saved_intr = 0x%0lx\n", (long)td->td_md.md_saved_intr); 718202046Simp db_printf("md_spinlock_count = %d\n", td->td_md.md_spinlock_count); 719202046Simp 720202046Simp if (td->td_frame != trapframe) { 721202046Simp db_printf("td->td_frame %p is not the same as pcb_regs %p\n", 722202046Simp td->td_frame, trapframe); 723202046Simp } 724202046Simp} 725202046Simp 726202999Sneel/* 727202999Sneel * Dump the trapframe beginning at address specified by first argument. 728202999Sneel */ 729202999SneelDB_SHOW_COMMAND(trapframe, ddb_dump_trapframe) 730202999Sneel{ 731202999Sneel 732202999Sneel if (!have_addr) 733202999Sneel return; 734202999Sneel 735202999Sneel dump_trapframe((struct trapframe *)addr); 736202999Sneel} 737202999Sneel 738202046Simp#endif /* DDB */ 739