trap.c revision 233748
180708Sjake/*-
281899Sjake * Copyright (c) 2001, Jake Burkholder
381185Sjake * Copyright (C) 1994, David Greenman
481185Sjake * Copyright (c) 1990, 1993
581185Sjake *      The Regents of the University of California.  All rights reserved.
681185Sjake *
781185Sjake * This code is derived from software contributed to Berkeley by
881185Sjake * the University of Utah, and William Jolitz.
981185Sjake *
1081185Sjake * Redistribution and use in source and binary forms, with or without
1181185Sjake * modification, are permitted provided that the following conditions
1281185Sjake * are met:
1381185Sjake * 1. Redistributions of source code must retain the above copyright
1481185Sjake *    notice, this list of conditions and the following disclaimer.
1581185Sjake * 2. Redistributions in binary form must reproduce the above copyright
1681185Sjake *    notice, this list of conditions and the following disclaimer in the
1781185Sjake *    documentation and/or other materials provided with the distribution.
1881185Sjake * 4. Neither the name of the University nor the names of its contributors
1981185Sjake *    may be used to endorse or promote products derived from this software
2081185Sjake *    without specific prior written permission.
2181185Sjake *
2281337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2381185Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2481185Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2581337Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2681185Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2781185Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2881185Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2981185Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3081185Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3181185Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3281185Sjake * SUCH DAMAGE.
3381185Sjake *
34181701Smarius *	from: @(#)trap.c        7.4 (Berkeley) 5/13/91
35181701Smarius *	from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
3680708Sjake */
3780708Sjake
38157445Smarius#include <sys/cdefs.h>
39157445Smarius__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/trap.c 233748 2012-03-31 14:03:16Z marius $");
40157445Smarius
4180709Sjake#include "opt_ddb.h"
4282903Sjake#include "opt_ktr.h"
4380709Sjake
4480708Sjake#include <sys/param.h>
45131950Smarcel#include <sys/kdb.h>
4698037Sjake#include <sys/kernel.h>
4784849Stmm#include <sys/bus.h>
4884849Stmm#include <sys/interrupt.h>
4982903Sjake#include <sys/ktr.h>
5081135Stmm#include <sys/lock.h>
5180709Sjake#include <sys/mutex.h>
5280709Sjake#include <sys/systm.h>
53204152Smarius#include <sys/pcpu.h>
5482006Sjake#include <sys/pioctl.h>
55120965Srobert#include <sys/ptrace.h>
5680708Sjake#include <sys/proc.h>
5791783Sjake#include <sys/smp.h>
58120937Srobert#include <sys/signalvar.h>
5982006Sjake#include <sys/syscall.h>
6098037Sjake#include <sys/sysctl.h>
6181135Stmm#include <sys/sysent.h>
6282006Sjake#include <sys/vmmeter.h>
63155814Srwatson#include <security/audit/audit.h>
6480708Sjake
65182773Smarius#include <dev/ofw/openfirm.h>
66182773Smarius
6780709Sjake#include <vm/vm.h>
6881185Sjake#include <vm/pmap.h>
6981185Sjake#include <vm/vm_extern.h>
7080709Sjake#include <vm/vm_param.h>
7180709Sjake#include <vm/vm_kern.h>
7281185Sjake#include <vm/vm_map.h>
7380709Sjake#include <vm/vm_page.h>
7480709Sjake
75105939Sjake#include <machine/cpu.h>
7680708Sjake#include <machine/frame.h>
7781387Sjake#include <machine/intr_machdep.h>
78190107Smarius#include <machine/ofw_machdep.h>
79200215Smarius#include <machine/pcb.h>
8091783Sjake#include <machine/smp.h>
8180709Sjake#include <machine/trap.h>
8282006Sjake#include <machine/tstate.h>
8380709Sjake#include <machine/tte.h>
8480709Sjake#include <machine/tlb.h>
8580709Sjake#include <machine/tsb.h>
8682006Sjake#include <machine/watch.h>
8780708Sjake
8880709Sjakevoid trap(struct trapframe *tf);
8984186Sjakevoid syscall(struct trapframe *tf);
9080708Sjake
91206086Smariusstatic int trap_cecc(void);
9288642Sjakestatic int trap_pfault(struct thread *td, struct trapframe *tf);
9382903Sjake
94101955Sjakeextern char copy_fault[];
95101955Sjakeextern char copy_nofault_begin[];
96101955Sjakeextern char copy_nofault_end[];
9784186Sjake
98101955Sjakeextern char fs_fault[];
99101955Sjakeextern char fs_nofault_begin[];
100101955Sjakeextern char fs_nofault_end[];
101101955Sjakeextern char fs_nofault_intr_begin[];
102101955Sjakeextern char fs_nofault_intr_end[];
103101955Sjake
104116659Sjmgextern char fas_fault[];
105116659Sjmgextern char fas_nofault_begin[];
106116659Sjmgextern char fas_nofault_end[];
107116659Sjmg
108190107Smariusconst char *const trap_msg[] = {
10980709Sjake	"reserved",
11080709Sjake	"instruction access exception",
11180709Sjake	"instruction access error",
11288642Sjake	"instruction access protection",
11388642Sjake	"illtrap instruction",
11480709Sjake	"illegal instruction",
11580709Sjake	"privileged opcode",
11680709Sjake	"floating point disabled",
11780709Sjake	"floating point exception ieee 754",
11880709Sjake	"floating point exception other",
11980709Sjake	"tag overflow",
12080709Sjake	"division by zero",
12180709Sjake	"data access exception",
12280709Sjake	"data access error",
12388642Sjake	"data access protection",
12480709Sjake	"memory address not aligned",
12580709Sjake	"privileged action",
12688642Sjake	"async data error",
12788642Sjake	"trap instruction 16",
12888642Sjake	"trap instruction 17",
12988642Sjake	"trap instruction 18",
13088642Sjake	"trap instruction 19",
13188642Sjake	"trap instruction 20",
13288642Sjake	"trap instruction 21",
13388642Sjake	"trap instruction 22",
13488642Sjake	"trap instruction 23",
13588642Sjake	"trap instruction 24",
13688642Sjake	"trap instruction 25",
13788642Sjake	"trap instruction 26",
13888642Sjake	"trap instruction 27",
13988642Sjake	"trap instruction 28",
14088642Sjake	"trap instruction 29",
14188642Sjake	"trap instruction 30",
14288642Sjake	"trap instruction 31",
143114650Sjake	"fast instruction access mmu miss",
144114650Sjake	"fast data access mmu miss",
14588642Sjake	"interrupt",
14680709Sjake	"physical address watchpoint",
14780709Sjake	"virtual address watchpoint",
14880709Sjake	"corrected ecc error",
14982903Sjake	"spill",
15082903Sjake	"fill",
15182903Sjake	"fill",
15280709Sjake	"breakpoint",
15388642Sjake	"clean window",
15488642Sjake	"range check",
15588642Sjake	"fix alignment",
15688642Sjake	"integer overflow",
15782006Sjake	"syscall",
15885236Sjake	"restore physical watchpoint",
15985236Sjake	"restore virtual watchpoint",
16088781Sjake	"kernel stack fault",
16180709Sjake};
16280709Sjake
163157445Smariusstatic const int trap_sig[] = {
164105939Sjake	SIGILL,			/* reserved */
165105939Sjake	SIGILL,			/* instruction access exception */
166105939Sjake	SIGILL,			/* instruction access error */
167105939Sjake	SIGILL,			/* instruction access protection */
168105939Sjake	SIGILL,			/* illtrap instruction */
169105939Sjake	SIGILL,			/* illegal instruction */
170105939Sjake	SIGBUS,			/* privileged opcode */
171105939Sjake	SIGFPE,			/* floating point disabled */
172105939Sjake	SIGFPE,			/* floating point exception ieee 754 */
173105939Sjake	SIGFPE,			/* floating point exception other */
174105939Sjake	SIGEMT,			/* tag overflow */
175105939Sjake	SIGFPE,			/* division by zero */
176105939Sjake	SIGILL,			/* data access exception */
177105939Sjake	SIGILL,			/* data access error */
178105939Sjake	SIGBUS,			/* data access protection */
179105939Sjake	SIGBUS,			/* memory address not aligned */
180105939Sjake	SIGBUS,			/* privileged action */
181105939Sjake	SIGBUS,			/* async data error */
182105939Sjake	SIGILL,			/* trap instruction 16 */
183105939Sjake	SIGILL,			/* trap instruction 17 */
184105939Sjake	SIGILL,			/* trap instruction 18 */
185105939Sjake	SIGILL,			/* trap instruction 19 */
186105939Sjake	SIGILL,			/* trap instruction 20 */
187105939Sjake	SIGILL,			/* trap instruction 21 */
188105939Sjake	SIGILL,			/* trap instruction 22 */
189105939Sjake	SIGILL,			/* trap instruction 23 */
190105939Sjake	SIGILL,			/* trap instruction 24 */
191105939Sjake	SIGILL,			/* trap instruction 25 */
192105939Sjake	SIGILL,			/* trap instruction 26 */
193105939Sjake	SIGILL,			/* trap instruction 27 */
194105939Sjake	SIGILL,			/* trap instruction 28 */
195105939Sjake	SIGILL,			/* trap instruction 29 */
196105939Sjake	SIGILL,			/* trap instruction 30 */
197105939Sjake	SIGILL,			/* trap instruction 31 */
198114650Sjake	SIGSEGV,		/* fast instruction access mmu miss */
199114650Sjake	SIGSEGV,		/* fast data access mmu miss */
200105939Sjake	-1,			/* interrupt */
201105939Sjake	-1,			/* physical address watchpoint */
202105939Sjake	-1,			/* virtual address watchpoint */
203105939Sjake	-1,			/* corrected ecc error */
204105939Sjake	SIGILL,			/* spill */
205105939Sjake	SIGILL,			/* fill */
206105939Sjake	SIGILL,			/* fill */
207105939Sjake	SIGTRAP,		/* breakpoint */
208105939Sjake	SIGILL,			/* clean window */
209105939Sjake	SIGILL,			/* range check */
210105939Sjake	SIGILL,			/* fix alignment */
211105939Sjake	SIGILL,			/* integer overflow */
212105996Sjake	SIGSYS,			/* syscall */
213105939Sjake	-1,			/* restore physical watchpoint */
214105939Sjake	-1,			/* restore virtual watchpoint */
215105939Sjake	-1,			/* kernel stack fault */
216105939Sjake};
217105939Sjake
218233747SmariusCTASSERT(sizeof(trap_msg) / sizeof(*trap_msg) == T_MAX);
219233747SmariusCTASSERT(sizeof(trap_sig) / sizeof(*trap_sig) == T_MAX);
220233747Smarius
221105733SjakeCTASSERT(sizeof(struct trapframe) == 256);
222105733Sjake
22398037Sjakeint debugger_on_signal = 0;
22498037SjakeSYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
22598037Sjake    &debugger_on_signal, 0, "");
22698037Sjake
227206086Smariusu_int corrected_ecc = 0;
228206086SmariusSYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0,
229206086Smarius    "corrected ECC errors");
230206086Smarius
231182773Smarius/*
232182773Smarius * SUNW,set-trap-table allows to take over %tba from the PROM, which
233182773Smarius * will turn off interrupts and handle outstanding ones while doing so,
234182773Smarius * in a safe way.
235182773Smarius */
23680708Sjakevoid
237182773Smariussun4u_set_traptable(void *tba_addr)
238182773Smarius{
239182773Smarius	static struct {
240182773Smarius		cell_t name;
241182773Smarius		cell_t nargs;
242182773Smarius		cell_t nreturns;
243182773Smarius		cell_t tba_addr;
244182773Smarius	} args = {
245182773Smarius		(cell_t)"SUNW,set-trap-table",
246206449Smarius		1,
247206449Smarius		0,
248182773Smarius	};
249182773Smarius
250182773Smarius	args.tba_addr = (cell_t)tba_addr;
251186347Snwhitehorn	ofw_entry(&args);
252182773Smarius}
253182773Smarius
254182773Smariusvoid
25580709Sjaketrap(struct trapframe *tf)
25680708Sjake{
25783366Sjulian	struct thread *td;
25881135Stmm	struct proc *p;
25981387Sjake	int error;
26081135Stmm	int sig;
261157445Smarius	register_t addr;
262151316Sdavidxu	ksiginfo_t ksi;
26380709Sjake
264181701Smarius	td = curthread;
26581185Sjake
266105939Sjake	CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
267105939Sjake	    trap_msg[tf->tf_type & ~T_KERNEL],
268105939Sjake	    (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
269105939Sjake
270170291Sattilio	PCPU_INC(cnt.v_trap);
27184186Sjake
272105939Sjake	if ((tf->tf_tstate & TSTATE_PRIV) == 0) {
273105939Sjake		KASSERT(td != NULL, ("trap: curthread NULL"));
274105939Sjake		KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
27584186Sjake
276105939Sjake		p = td->td_proc;
277155455Sphk		td->td_pticks = 0;
27883366Sjulian		td->td_frame = tf;
279157445Smarius		addr = tf->tf_tpc;
28090894Sjulian		if (td->td_ucred != p->p_ucred)
28190894Sjulian			cred_update_thread(td);
28281135Stmm
283105939Sjake		switch (tf->tf_type) {
284105939Sjake		case T_DATA_MISS:
285105939Sjake		case T_DATA_PROTECTION:
286157445Smarius			addr = tf->tf_sfar;
287157445Smarius			/* FALLTHROUGH */
288105939Sjake		case T_INSTRUCTION_MISS:
289105939Sjake			sig = trap_pfault(td, tf);
290105939Sjake			break;
291105939Sjake		case T_FILL:
292105939Sjake			sig = rwindow_load(td, tf, 2);
293105939Sjake			break;
294105939Sjake		case T_FILL_RET:
295105939Sjake			sig = rwindow_load(td, tf, 1);
296105939Sjake			break;
297105939Sjake		case T_SPILL:
298105939Sjake			sig = rwindow_save(td);
299105939Sjake			break;
300206086Smarius		case T_CORRECTED_ECC_ERROR:
301206086Smarius			sig = trap_cecc();
302206086Smarius			break;
303105939Sjake		default:
304233748Smarius			if (tf->tf_type > T_MAX)
305206086Smarius				panic("trap: bad trap type %#lx (user)",
306206086Smarius				    tf->tf_type);
307206086Smarius			else if (trap_sig[tf->tf_type] == -1)
308206086Smarius				panic("trap: %s (user)",
309206086Smarius				    trap_msg[tf->tf_type]);
310105939Sjake			sig = trap_sig[tf->tf_type];
311105939Sjake			break;
312105939Sjake		}
31384186Sjake
314105939Sjake		if (sig != 0) {
315105939Sjake			/* Translate fault for emulators. */
316105939Sjake			if (p->p_sysent->sv_transtrap != NULL) {
317105939Sjake				sig = p->p_sysent->sv_transtrap(sig,
318105939Sjake				    tf->tf_type);
319105939Sjake			}
320105939Sjake			if (debugger_on_signal &&
321105939Sjake			    (sig == 4 || sig == 10 || sig == 11))
322174898Srwatson				kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
323151316Sdavidxu			ksiginfo_init_trap(&ksi);
324151316Sdavidxu			ksi.ksi_signo = sig;
325151316Sdavidxu			ksi.ksi_code = (int)tf->tf_type; /* XXX not POSIX */
326157445Smarius			ksi.ksi_addr = (void *)addr;
327151354Sdavidxu			ksi.ksi_trapno = (int)tf->tf_type;
328151316Sdavidxu			trapsignal(td, &ksi);
32984186Sjake		}
33084186Sjake
331155455Sphk		userret(td, tf);
332105939Sjake		mtx_assert(&Giant, MA_NOTOWNED);
333181701Smarius	} else {
334105939Sjake		KASSERT((tf->tf_type & T_KERNEL) != 0,
335105939Sjake		    ("trap: kernel trap isn't"));
336105939Sjake
337131950Smarcel		if (kdb_active) {
338131950Smarcel			kdb_reenter();
339131950Smarcel			return;
340131950Smarcel		}
341131950Smarcel
342105939Sjake		switch (tf->tf_type & ~T_KERNEL) {
343105939Sjake		case T_BREAKPOINT:
344105939Sjake		case T_KSTACK_FAULT:
345131950Smarcel			error = (kdb_trap(tf->tf_type, 0, tf) == 0);
346131950Smarcel			TF_DONE(tf);
347105939Sjake			break;
348105939Sjake#ifdef notyet
349105939Sjake		case T_PA_WATCHPOINT:
350105939Sjake		case T_VA_WATCHPOINT:
351105939Sjake			error = db_watch_trap(tf);
352105939Sjake			break;
35380709Sjake#endif
354105939Sjake		case T_DATA_MISS:
355105939Sjake		case T_DATA_PROTECTION:
356105939Sjake		case T_INSTRUCTION_MISS:
357105939Sjake			error = trap_pfault(td, tf);
358101955Sjake			break;
359105939Sjake		case T_DATA_EXCEPTION:
360105939Sjake		case T_MEM_ADDRESS_NOT_ALIGNED:
361105939Sjake			if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 &&
362105939Sjake			    MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) {
363105939Sjake				if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
364105939Sjake				    tf->tf_tpc <= (u_long)copy_nofault_end) {
365105939Sjake					tf->tf_tpc = (u_long)copy_fault;
366105939Sjake					tf->tf_tnpc = tf->tf_tpc + 4;
367105939Sjake					error = 0;
368105939Sjake					break;
369105939Sjake				}
370105939Sjake				if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
371105939Sjake				    tf->tf_tpc <= (u_long)fs_nofault_end) {
372105939Sjake					tf->tf_tpc = (u_long)fs_fault;
373105939Sjake					tf->tf_tnpc = tf->tf_tpc + 4;
374105939Sjake					error = 0;
375105939Sjake					break;
376105939Sjake				}
377105939Sjake			}
378181701Smarius			error = 1;
379105939Sjake			break;
380116659Sjmg		case T_DATA_ERROR:
381116659Sjmg			/*
382157513Smarius			 * Handle PCI poke/peek as per UltraSPARC IIi
383157513Smarius			 * User's Manual 16.2.1, modulo checking the
384157513Smarius			 * TPC as USIII CPUs generate a precise trap
385157513Smarius			 * instead of a special deferred one.
386116659Sjmg			 */
387116659Sjmg			if (tf->tf_tpc > (u_long)fas_nofault_begin &&
388157513Smarius			    tf->tf_tpc < (u_long)fas_nofault_end) {
389122464Sjake				cache_flush();
390204152Smarius				cache_enable(PCPU_GET(impl));
391116659Sjmg				tf->tf_tpc = (u_long)fas_fault;
392116659Sjmg				tf->tf_tnpc = tf->tf_tpc + 4;
393116659Sjmg				error = 0;
394116659Sjmg				break;
395116659Sjmg			}
396116659Sjmg			error = 1;
397116659Sjmg			break;
398206086Smarius		case T_CORRECTED_ECC_ERROR:
399206086Smarius			error = trap_cecc();
400206086Smarius			break;
401105939Sjake		default:
402105939Sjake			error = 1;
403105939Sjake			break;
404101955Sjake		}
405105939Sjake
406206086Smarius		if (error != 0) {
407206086Smarius			tf->tf_type &= ~T_KERNEL;
408233748Smarius			if (tf->tf_type > T_MAX)
409206086Smarius				panic("trap: bad trap type %#lx (kernel)",
410206086Smarius				    tf->tf_type);
411233747Smarius			panic("trap: %s (kernel)", trap_msg[tf->tf_type]);
412206086Smarius		}
41380709Sjake	}
41484186Sjake	CTR1(KTR_TRAP, "trap: td=%p return", td);
41580708Sjake}
41681185Sjake
41788642Sjakestatic int
418206086Smariustrap_cecc(void)
419206086Smarius{
420206086Smarius	u_long eee;
421206086Smarius
422206086Smarius	/*
423206086Smarius	 * Turn off (non-)correctable error reporting while we're dealing
424206086Smarius	 * with the error.
425206086Smarius	 */
426206086Smarius	eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG);
427206086Smarius	stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN |
428206086Smarius	    AA_ESTATE_CEEN));
429206086Smarius	/* Flush the caches in order ensure no corrupt data got installed. */
430206086Smarius	cache_flush();
431206086Smarius	/* Ensure the caches are still turned on (should be). */
432206086Smarius	cache_enable(PCPU_GET(impl));
433218909Sbrucec	/* Clear the error from the AFSR. */
434206086Smarius	stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR));
435206086Smarius	corrected_ecc++;
436206086Smarius	printf("corrected ECC error\n");
437206086Smarius	/* Turn (non-)correctable error reporting back on. */
438206086Smarius	stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee);
439206086Smarius	return (0);
440206086Smarius}
441206086Smarius
442206086Smariusstatic int
44388642Sjaketrap_pfault(struct thread *td, struct trapframe *tf)
44481185Sjake{
44581185Sjake	struct vmspace *vm;
44683366Sjulian	struct proc *p;
44781185Sjake	vm_offset_t va;
44882903Sjake	vm_prot_t prot;
449182122Smarius	vm_map_entry_t entry;
45082903Sjake	u_long ctx;
45182903Sjake	int type;
45281185Sjake	int rv;
45381185Sjake
454105939Sjake	if (td == NULL)
455105939Sjake		return (-1);
45688642Sjake	KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
457105939Sjake	KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
458105939Sjake	KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
45981185Sjake
460105939Sjake	p = td->td_proc;
461105939Sjake
46282903Sjake	rv = KERN_SUCCESS;
46388642Sjake	ctx = TLB_TAR_CTX(tf->tf_tar);
46482903Sjake	type = tf->tf_type & ~T_KERNEL;
46588642Sjake	va = TLB_TAR_VA(tf->tf_tar);
46681185Sjake
46788642Sjake	CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
468181701Smarius	    td, p->p_vmspace->vm_pmap.pm_context[curcpu], va, ctx);
46981185Sjake
470199868Salc	if (type == T_DATA_PROTECTION)
47182903Sjake		prot = VM_PROT_WRITE;
472199868Salc	else {
47388642Sjake		if (type == T_DATA_MISS)
47482903Sjake			prot = VM_PROT_READ;
47581387Sjake		else
47682903Sjake			prot = VM_PROT_READ | VM_PROT_EXECUTE;
47782903Sjake	}
47881185Sjake
47988642Sjake	if (ctx != TLB_CTX_KERNEL) {
48088642Sjake		if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
481101955Sjake		    (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
482181701Smarius		    tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
483101955Sjake			tf->tf_tpc = (u_long)fs_fault;
484101955Sjake			tf->tf_tnpc = tf->tf_tpc + 4;
485101955Sjake			return (0);
486101955Sjake		}
48788642Sjake
48888642Sjake		/*
48988642Sjake		 * This is a fault on non-kernel virtual memory.
49088642Sjake		 */
49188642Sjake		vm = p->p_vmspace;
49288642Sjake
49388642Sjake		/*
49488642Sjake		 * Keep swapout from messing with us during this
49588642Sjake		 * critical time.
49688642Sjake		 */
49788642Sjake		PROC_LOCK(p);
49888642Sjake		++p->p_lock;
49988642Sjake		PROC_UNLOCK(p);
50088642Sjake
50195139Sjake		/* Fault in the user page. */
502199868Salc		rv = vm_fault(&vm->vm_map, va, prot, VM_FAULT_NORMAL);
50388642Sjake
50488642Sjake		/*
50588642Sjake		 * Now the process can be swapped again.
50688642Sjake		 */
50788642Sjake		PROC_LOCK(p);
50888642Sjake		--p->p_lock;
50988642Sjake		PROC_UNLOCK(p);
51082903Sjake	} else {
51188642Sjake		/*
512101955Sjake		 * This is a fault on kernel virtual memory.  Attempts to
513101955Sjake		 * access kernel memory from user mode cause privileged
514101955Sjake		 * action traps, not page fault.
51588642Sjake		 */
51688642Sjake		KASSERT(tf->tf_tstate & TSTATE_PRIV,
51788642Sjake		    ("trap_pfault: fault on nucleus context from user mode"));
51888642Sjake
519182122Smarius		if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
520182122Smarius		    tf->tf_tpc <= (u_long)copy_nofault_end) {
521182122Smarius			vm_map_lock_read(kernel_map);
522182122Smarius			if (vm_map_lookup_entry(kernel_map, va, &entry) &&
523182122Smarius			    (entry->eflags & MAP_ENTRY_NOFAULT) != 0) {
524182122Smarius				tf->tf_tpc = (u_long)copy_fault;
525182122Smarius				tf->tf_tnpc = tf->tf_tpc + 4;
526182122Smarius				vm_map_unlock_read(kernel_map);
527182122Smarius				return (0);
528182122Smarius			}
529182122Smarius			vm_map_unlock_read(kernel_map);
530182122Smarius		}
531182122Smarius
53288642Sjake		/*
533181701Smarius		 * We don't have to worry about process locking or stacks in
534181701Smarius		 * the kernel.
53588642Sjake		 */
53688642Sjake		rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
53781185Sjake	}
53888642Sjake
53988642Sjake	CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
54088642Sjake	    td, va, rv);
54181185Sjake	if (rv == KERN_SUCCESS)
54281185Sjake		return (0);
543101955Sjake	if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
544101955Sjake		if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
545101955Sjake		    tf->tf_tpc <= (u_long)fs_nofault_end) {
546101955Sjake			tf->tf_tpc = (u_long)fs_fault;
54781185Sjake			tf->tf_tnpc = tf->tf_tpc + 4;
54881185Sjake			return (0);
54981185Sjake		}
550101955Sjake		if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
551101955Sjake		    tf->tf_tpc <= (u_long)copy_nofault_end) {
552101955Sjake			tf->tf_tpc = (u_long)copy_fault;
553101955Sjake			tf->tf_tnpc = tf->tf_tpc + 4;
554101955Sjake			return (0);
555101955Sjake		}
55681185Sjake	}
55788642Sjake	return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
55881185Sjake}
55982006Sjake
56082006Sjake/* Maximum number of arguments that can be passed via the out registers. */
56182006Sjake#define	REG_MAXARGS	6
56282006Sjake
563208453Skibint
564208453Skibcpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
565202900Smarius{
566202900Smarius	struct trapframe *tf;
567202900Smarius	struct proc *p;
568208453Skib	register_t *argp;
569202900Smarius	int reg;
570202900Smarius	int regcnt;
571202900Smarius	int error;
572202900Smarius
573202900Smarius	p = td->td_proc;
574202900Smarius	tf = td->td_frame;
575202900Smarius	reg = 0;
576202900Smarius	regcnt = REG_MAXARGS;
577202900Smarius
578202900Smarius	sa->code = tf->tf_global[1];
579202900Smarius
580208453Skib	if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
581202900Smarius		sa->code = tf->tf_out[reg++];
582202900Smarius		regcnt--;
583202900Smarius	}
584202900Smarius
585202900Smarius	if (p->p_sysent->sv_mask)
586202900Smarius		sa->code &= p->p_sysent->sv_mask;
587202900Smarius	if (sa->code >= p->p_sysent->sv_size)
588202900Smarius		sa->callp = &p->p_sysent->sv_table[0];
589202900Smarius	else
590202900Smarius		sa->callp = &p->p_sysent->sv_table[sa->code];
591202900Smarius
592202900Smarius	sa->narg = sa->callp->sy_narg;
593202900Smarius	KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
594202900Smarius	    ("Too many syscall arguments!"));
595202900Smarius	error = 0;
596208453Skib	argp = sa->args;
597202900Smarius	bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
598202900Smarius	if (sa->narg > regcnt)
599202900Smarius		error = copyin((void *)(tf->tf_out[6] + SPOFF +
600202900Smarius		    offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
601202900Smarius		    (sa->narg - regcnt) * sizeof(sa->args[0]));
602208453Skib	if (error == 0) {
603208453Skib		td->td_retval[0] = 0;
604208453Skib		td->td_retval[1] = 0;
605208453Skib	}
606202900Smarius
607202900Smarius	return (error);
608202900Smarius}
609202900Smarius
610225474Skib#include "../../kern/subr_syscall.c"
611225474Skib
61282006Sjake/*
613202900Smarius * Syscall handler
614202900Smarius * The arguments to the syscall are passed in the out registers by the caller,
615202900Smarius * and are saved in the trap frame.  The syscall number is passed in %g1 (and
616202900Smarius * also saved in the trap frame).
61782006Sjake */
61882006Sjakevoid
61984186Sjakesyscall(struct trapframe *tf)
62082006Sjake{
621208453Skib	struct thread *td;
622202900Smarius	struct syscall_args sa;
62382006Sjake	int error;
62482006Sjake
625181701Smarius	td = curthread;
626208453Skib	td->td_frame = tf;
627208453Skib
628105939Sjake	KASSERT(td != NULL, ("trap: curthread NULL"));
629105939Sjake	KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
63084186Sjake
63182006Sjake	/*
63282006Sjake	 * For syscalls, we don't want to retry the faulting instruction
63382006Sjake	 * (usually), instead we need to advance one instruction.
63482006Sjake	 */
635199135Skib	td->td_pcb->pcb_tpc = tf->tf_tpc;
63686146Stmm	TF_DONE(tf);
63782006Sjake
638208453Skib	error = syscallenter(td, &sa);
639208453Skib	syscallret(td, error, &sa);
64082006Sjake}
641