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