trap.c revision 1.62
1/*	$NetBSD: trap.c,v 1.62 2007/02/09 21:55:07 ad Exp $	*/
2
3/*
4 * This file was taken from mvme68k/mvme68k/trap.c
5 * should probably be re-synced when needed.
6 * Darrin B. Jewell <jewell@mit.edu> Tue Aug  3 10:53:12 UTC 1999
7 * original cvs id: NetBSD: trap.c,v 1.32 1999/08/03 10:52:06 dbj Exp
8 */
9
10/*
11 * Copyright (c) 1982, 1986, 1990, 1993
12 *	The Regents of the University of California.  All rights reserved.
13 *
14 * This code is derived from software contributed to Berkeley by
15 * the Systems Programming Group of the University of Utah Computer
16 * Science Department.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 * 3. Neither the name of the University nor the names of its contributors
27 *    may be used to endorse or promote products derived from this software
28 *    without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * from: Utah $Hdr: trap.c 1.37 92/12/20$
43 *
44 *	@(#)trap.c	8.5 (Berkeley) 1/4/94
45 */
46/*
47 * Copyright (c) 1988 University of Utah.
48 *
49 * This code is derived from software contributed to Berkeley by
50 * the Systems Programming Group of the University of Utah Computer
51 * Science Department.
52 *
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
55 * are met:
56 * 1. Redistributions of source code must retain the above copyright
57 *    notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 *    notice, this list of conditions and the following disclaimer in the
60 *    documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 *    must display the following acknowledgement:
63 *	This product includes software developed by the University of
64 *	California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 *    may be used to endorse or promote products derived from this software
67 *    without specific prior written permission.
68 *
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79 * SUCH DAMAGE.
80 *
81 * from: Utah $Hdr: trap.c 1.37 92/12/20$
82 *
83 *	@(#)trap.c	8.5 (Berkeley) 1/4/94
84 */
85
86#include <sys/cdefs.h>
87__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.62 2007/02/09 21:55:07 ad Exp $");
88
89#include "opt_ddb.h"
90#include "opt_execfmt.h"
91#include "opt_kgdb.h"
92#include "opt_compat_sunos.h"
93#include "opt_compat_hpux.h"
94
95#include <sys/param.h>
96#include <sys/systm.h>
97#include <sys/proc.h>
98#include <sys/acct.h>
99#include <sys/kernel.h>
100#include <sys/signalvar.h>
101#include <sys/resourcevar.h>
102#include <sys/syscall.h>
103#include <sys/syslog.h>
104#include <sys/user.h>
105#include <sys/userret.h>
106#include <sys/kauth.h>
107
108#ifdef DEBUG
109#include <dev/cons.h>
110#endif
111
112#include <machine/db_machdep.h>
113#include <machine/psl.h>
114#include <machine/trap.h>
115#include <machine/cpu.h>
116#include <machine/reg.h>
117
118#include <m68k/cacheops.h>
119
120#include <uvm/uvm_extern.h>
121
122#ifdef COMPAT_HPUX
123#include <compat/hpux/hpux.h>
124#endif
125
126#ifdef COMPAT_SUNOS
127#include <compat/sunos/sunos_syscall.h>
128extern struct emul emul_sunos;
129#endif
130
131#ifdef KGDB
132#include <sys/kgdb.h>
133#endif
134
135int	writeback(struct frame *, int);
136void	trap(int, u_int, u_int, struct frame);
137
138#ifdef DEBUG
139void	dumpssw(u_short);
140void	dumpwb(int, u_short, u_int, u_int);
141#endif
142
143static inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int);
144
145int	astpending;
146
147const char *trap_type[] = {
148	"Bus error",
149	"Address error",
150	"Illegal instruction",
151	"Zero divide",
152	"CHK instruction",
153	"TRAPV instruction",
154	"Privilege violation",
155	"Trace trap",
156	"MMU fault",
157	"SSIR trap",
158	"Format error",
159	"68881 exception",
160	"Coprocessor violation",
161	"Async system trap"
162};
163int	trap_types = sizeof trap_type / sizeof trap_type[0];
164
165/*
166 * Size of various exception stack frames (minus the standard 8 bytes)
167 */
168short	exframesize[] = {
169	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
170	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
171	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
172	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
173	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
174	-1, -1,		/* type 5-6 - undefined */
175	FMT7SIZE,	/* type 7 - access error (68040) */
176	58,		/* type 8 - bus fault (68010) */
177	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
178	FMTASIZE,	/* type A - short bus fault (68020/030) */
179	FMTBSIZE,	/* type B - long bus fault (68020/030) */
180	-1, -1, -1, -1	/* type C-F - undefined */
181};
182
183#ifdef M68060
184#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
185#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
186#else
187#define	KDFAULT_060(c)	0
188#define	WRFAULT_060(c)	0
189#endif
190
191#ifdef M68040
192#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
193			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
194#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
195			 ((c) & SSW4_RW) == 0)
196#else
197#define	KDFAULT_040(c)	0
198#define	WRFAULT_040(c)	0
199#endif
200
201#if defined(M68030) || defined(M68020)
202#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
203			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
204#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
205			 ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
206#else
207#define	KDFAULT_OTH(c)	0
208#define	WRFAULT_OTH(c)	0
209#endif
210
211#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
212#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
213
214#ifdef DEBUG
215int mmudebug = 0;
216int mmupid = -1;
217#define MDB_FOLLOW	1
218#define MDB_WBFOLLOW	2
219#define MDB_WBFAILED	4
220#define MDB_ISPID(p)	((p) == mmupid)
221#endif
222
223
224#define NSIR	32
225void (*sir_routines[NSIR])(void *);
226void *sir_args[NSIR];
227int next_sir;
228
229/*
230 * trap and syscall both need the following work done before returning
231 * to user mode.
232 */
233static inline void
234userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr,
235    int fromtrap)
236{
237	struct proc *p = l->l_proc;
238#ifdef M68040
239	int sig;
240	int beenhere = 0;
241
242again:
243#endif
244	/* Invoke MI userret code */
245	mi_userret(l);
246
247	/*
248	 * If profiling, charge system time to the trapped pc.
249	 */
250	if (p->p_stflag & PST_PROFIL) {
251		extern int psratio;
252
253		addupc_task(l, fp->f_pc,
254			    (int)(p->p_sticks - oticks) * psratio);
255	}
256#ifdef M68040
257	/*
258	 * Deal with user mode writebacks (from trap, or from sigreturn).
259	 * If any writeback fails, go back and attempt signal delivery.
260	 * unless we have already been here and attempted the writeback
261	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
262	 * we just return to the user without successfully completing
263	 * the writebacks.  Maybe we should just drop the sucker?
264	 */
265	if (cputype == CPU_68040 && fp->f_format == FMT7) {
266		if (beenhere) {
267#ifdef DEBUG
268			if (mmudebug & MDB_WBFAILED)
269				printf(fromtrap ?
270		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
271		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
272				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
273#endif
274		} else if ((sig = writeback(fp, fromtrap))) {
275			ksiginfo_t ksi;
276			beenhere = 1;
277			oticks = p->p_sticks;
278			(void)memset(&ksi, 0, sizeof(ksi));
279			ksi.ksi_signo = sig;
280			ksi.ksi_addr = (void *)faultaddr;
281			ksi.ksi_code = BUS_OBJERR;
282			trapsignal(l, &ksi);
283			goto again;
284		}
285	}
286#endif
287	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
288}
289
290/*
291 * Used by the common m68k syscall() and child_return() functions.
292 * XXX: Temporary until all m68k ports share common trap()/userret() code.
293 */
294void machine_userret(struct lwp *, struct frame *, u_quad_t);
295
296void
297machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
298{
299
300	userret(l, f, t, 0, 0);
301}
302
303/*
304 * Trap is called from locore to handle most types of processor traps,
305 * including events such as simulated software interrupts/AST's.
306 * System calls are broken out for efficiency.
307 */
308/*ARGSUSED*/
309void
310trap(int type, unsigned code, unsigned v, struct frame frame)
311{
312	extern char fubail[], subail[];
313	struct lwp *l;
314	struct proc *p;
315	ksiginfo_t ksi;
316	int s;
317	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
318	int bit;
319	static int panicking = 0;
320
321	uvmexp.traps++;
322	l = curlwp;
323
324	KSI_INIT_TRAP(&ksi);
325	ksi.ksi_trap = type & ~T_USER;
326
327	if (l == NULL)
328		l = &lwp0;
329	p = l->l_proc;
330
331#ifdef DIAGNOSTIC
332	if (l->l_addr == NULL)
333		panic("trap: no pcb");
334#endif
335
336	if (USERMODE(frame.f_sr)) {
337		type |= T_USER;
338		sticks = p->p_sticks;
339		l->l_md.md_regs = frame.f_regs;
340		LWP_CACHE_CREDS(l, p);
341	}
342	switch (type) {
343
344	default:
345	dopanic:
346		/*
347		 * Let the kernel debugger see the trap frame that
348		 * caused us to panic.  This is a convenience so
349		 * one can see registers at the point of failure.
350		 */
351		s = splhigh();
352		panicking = 1;
353		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
354		printf("%s program counter = 0x%x\n",
355		    (type & T_USER) ? "user" : "kernel", frame.f_pc);
356#ifdef KGDB
357		/* If connected, step or cont returns 1 */
358		if (kgdb_trap(type, (db_regs_t *)&frame))
359			goto kgdb_cont;
360#endif
361#ifdef DDB
362		(void)kdb_trap(type, (db_regs_t *)&frame);
363#endif
364#ifdef KGDB
365	kgdb_cont:
366#endif
367		splx(s);
368		if (panicstr) {
369			printf("trap during panic!\n");
370#ifdef DEBUG
371			/* XXX should be a machine-dependent hook */
372			printf("(press a key)\n"); (void)cngetc();
373#endif
374		}
375		regdump((struct trapframe *)&frame, 128);
376		type &= ~T_USER;
377		if ((u_int)type < trap_types)
378			panic(trap_type[type]);
379		panic("trap");
380
381	case T_BUSERR:		/* kernel bus error */
382		if (l->l_addr->u_pcb.pcb_onfault == 0)
383			goto dopanic;
384		/* FALLTHROUGH */
385
386	copyfault:
387		/*
388		 * If we have arranged to catch this fault in any of the
389		 * copy to/from user space routines, set PC to return to
390		 * indicated location and set flag informing buserror code
391		 * that it may need to clean up stack frame.
392		 */
393		frame.f_stackadj = exframesize[frame.f_format];
394		frame.f_format = frame.f_vector = 0;
395		frame.f_pc = (int) l->l_addr->u_pcb.pcb_onfault;
396		return;
397
398	case T_BUSERR|T_USER:	/* bus error */
399	case T_ADDRERR|T_USER:	/* address error */
400		ksi.ksi_addr = (void *)v;
401		ksi.ksi_signo = SIGBUS;
402		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
403			BUS_OBJERR : BUS_ADRERR;
404		break;
405
406	case T_COPERR:		/* kernel coprocessor violation */
407	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
408	case T_FMTERR:		/* ...just in case... */
409	/*
410	 * The user has most likely trashed the RTE or FP state info
411	 * in the stack frame of a signal handler.
412	 */
413		printf("pid %d: kernel %s exception\n", p->p_pid,
414		       type==T_COPERR ? "coprocessor" : "format");
415		type |= T_USER;
416
417		mutex_enter(&p->p_smutex);
418		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
419		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
420		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
421		sigdelset(&l->l_sigmask, SIGILL);
422		mutex_exit(&p->p_smutex);
423
424		ksi.ksi_signo = SIGILL;
425		ksi.ksi_addr = (void *)(int)frame.f_format;
426				/* XXX was ILL_RESAD_FAULT */
427		ksi.ksi_code = (type == T_COPERR) ?
428			ILL_COPROC : ILL_ILLOPC;
429		break;
430
431	case T_COPERR|T_USER:	/* user coprocessor violation */
432	/* What is a proper response here? */
433		ksi.ksi_signo = SIGFPE;
434		ksi.ksi_code = FPE_FLTINV;
435		break;
436
437	case T_FPERR|T_USER:	/* 68881 exceptions */
438	/*
439	 * We pass along the 68881 status register which locore stashed
440	 * in code for us.  Note that there is a possibility that the
441	 * bit pattern of this register will conflict with one of the
442	 * FPE_* codes defined in signal.h.  Fortunately for us, the
443	 * only such codes we use are all in the range 1-7 and the low
444	 * 3 bits of the status register are defined as 0 so there is
445	 * no clash.
446	 */
447		ksi.ksi_signo = SIGFPE;
448		ksi.ksi_addr = (void *)code;
449		break;
450
451#ifdef M68040
452	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
453	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
454		/* XXX need to FSAVE */
455		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
456		       p->p_pid, p->p_comm,
457		       frame.f_format == 2 ? "instruction" : "data type",
458		       frame.f_pc, frame.f_fmt2.f_iaddr);
459		/* XXX need to FRESTORE */
460		ksi.ksi_signo = SIGFPE;
461		ksi.ksi_code = FPE_FLTINV;
462		break;
463#endif
464
465	case T_ILLINST|T_USER:	/* illegal instruction fault */
466#ifdef COMPAT_HPUX
467		if (p->p_emul == &emul_hpux) {
468			ksi.ksi_addr = (void *)HPUX_ILL_ILLINST_TRAP;
469			ksi.ksi_signo = SIGILL;
470			break;
471		}
472		/* fall through */
473#endif
474	case T_PRIVINST|T_USER:	/* privileged instruction fault */
475#ifdef COMPAT_HPUX
476		if (p->p_emul == &emul_hpux)
477			ksi.ksi_addr = (void *)HPUX_ILL_PRIV_TRAP;
478		else
479#endif
480		ksi.ksi_addr = (void *)(int)frame.f_format;
481				/* XXX was ILL_PRIVIN_FAULT */
482		ksi.ksi_signo = SIGILL;
483		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
484			ILL_PRVOPC : ILL_ILLOPC;
485		break;
486
487	case T_ZERODIV|T_USER:	/* Divide by zero */
488#ifdef COMPAT_HPUX
489		if (p->p_emul == &emul_hpux)
490			ksi.ksi_addr = (void *)HPUX_FPE_INTDIV_TRAP;
491		else
492#endif
493		ksi.ksi_addr = (void *)(int)frame.f_format;
494				/* XXX was FPE_INTDIV_TRAP */
495		ksi.ksi_signo = SIGFPE;
496		ksi.ksi_code = FPE_FLTDIV;
497		break;
498
499	case T_CHKINST|T_USER:	/* CHK instruction trap */
500#ifdef COMPAT_HPUX
501		if (p->p_emul == &emul_hpux) {
502			/* handled differently under hp-ux */
503			ksi.ksi_signo = SIGILL;
504			ksi.ksi_addr = (void *)HPUX_ILL_CHK_TRAP;
505			break;
506		}
507#endif
508		ksi.ksi_addr = (void *)(int)frame.f_format;
509				/* XXX was FPE_SUBRNG_TRAP */
510		ksi.ksi_signo = SIGFPE;
511		break;
512
513	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
514#ifdef COMPAT_HPUX
515		if (p->p_emul == &emul_hpux) {
516			/* handled differently under hp-ux */
517			ksi.ksi_signo = SIGILL;
518			ksi.ksi_addr = (void *)HPUX_ILL_TRAPV_TRAP;
519			break;
520		}
521#endif
522		ksi.ksi_addr = (void *)(int)frame.f_format;
523				/* XXX was FPE_INTOVF_TRAP */
524		ksi.ksi_signo = SIGFPE;
525		break;
526
527	/*
528	 * XXX: Trace traps are a nightmare.
529	 *
530	 *	HP-UX uses trap #1 for breakpoints,
531	 *	NetBSD/m68k uses trap #2,
532	 *	SUN 3.x uses trap #15,
533	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
534	 *	handled elsewhere).
535	 *
536	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
537	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
538	 * supported yet.
539	 *
540	 * XXX: We should never get kernel-mode T_TRAP15
541	 * XXX: because locore.s now gives them special treatment.
542	 */
543	case T_TRAP15:		/* kernel breakpoint */
544#ifdef DEBUG
545		printf("unexpected kernel trace trap, type = %d\n", type);
546		printf("program counter = 0x%x\n", frame.f_pc);
547#endif
548		frame.f_sr &= ~PSL_T;
549		return;
550
551	case T_TRACE|T_USER:	/* user trace trap */
552#ifdef COMPAT_SUNOS
553		/*
554		 * SunOS uses Trap #2 for a "CPU cache flush".
555		 * Just flush the on-chip caches and return.
556		 */
557		if (p->p_emul == &emul_sunos) {
558			ICIA();
559			DCIU();
560			return;
561		}
562#endif
563		/* FALLTHROUGH */
564	case T_TRACE:		/* tracing a trap instruction */
565	case T_TRAP15|T_USER:	/* SUN user trace trap */
566		frame.f_sr &= ~PSL_T;
567		ksi.ksi_signo = SIGTRAP;
568		break;
569
570	case T_ASTFLT:		/* system async trap, cannot happen */
571		goto dopanic;
572
573	case T_ASTFLT|T_USER:	/* user async trap */
574		astpending = 0;
575		/*
576		 * We check for software interrupts first.  This is because
577		 * they are at a higher level than ASTs, and on a VAX would
578		 * interrupt the AST.  We assume that if we are processing
579		 * an AST that we must be at IPL0 so we don't bother to
580		 * check.  Note that we ensure that we are at least at SIR
581		 * IPL while processing the SIR.
582		 */
583		spl1();
584		/* fall into... */
585
586	case T_SSIR:		/* software interrupt */
587	case T_SSIR|T_USER:
588		while ((bit = ffs(ssir))) {
589			--bit;
590			ssir &= ~(1 << bit);
591			uvmexp.softs++;
592			if (sir_routines[bit])
593				sir_routines[bit](sir_args[bit]);
594		}
595		/*
596		 * If this was not an AST trap, we are all done.
597		 */
598		if (type != (T_ASTFLT|T_USER)) {
599			uvmexp.traps--;
600			return;
601		}
602		spl0();
603		if (l->l_pflag & LP_OWEUPC) {
604			l->l_pflag &= ~LP_OWEUPC;
605			ADDUPROF(l);
606		}
607		if (want_resched)
608			preempt();
609		goto out;
610
611	case T_MMUFLT:		/* kernel mode page fault */
612		/*
613		 * If we were doing profiling ticks or other user mode
614		 * stuff from interrupt code, Just Say No.
615		 */
616		if (l->l_addr->u_pcb.pcb_onfault == fubail ||
617		    l->l_addr->u_pcb.pcb_onfault == subail)
618			goto copyfault;
619		/* fall into ... */
620
621	case T_MMUFLT|T_USER:	/* page fault */
622	    {
623		vaddr_t va;
624		struct vmspace *vm = p->p_vmspace;
625		struct vm_map *map;
626		int rv;
627		vm_prot_t ftype;
628		extern struct vm_map *kernel_map;
629
630#ifdef DEBUG
631		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
632		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
633		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
634#endif
635		/*
636		 * It is only a kernel address space fault iff:
637		 * 	1. (type & T_USER) == 0  and
638		 * 	2. pcb_onfault not set or
639		 *	3. pcb_onfault set but supervisor space data fault
640		 * The last can occur during an exec() copyin where the
641		 * argument space is lazy-allocated.
642		 */
643		if ((type & T_USER) == 0 &&
644		    ((l->l_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
645			map = kernel_map;
646		else
647			map = vm ? &vm->vm_map : kernel_map;
648
649		if (WRFAULT(code))
650			ftype = VM_PROT_WRITE;
651		else
652			ftype = VM_PROT_READ;
653
654		va = trunc_page((vaddr_t)v);
655
656		if (map == kernel_map && va == 0) {
657			printf("trap: bad kernel %s access at 0x%x\n",
658			    (ftype & VM_PROT_WRITE) ? "read/write" :
659			    "read", v);
660			goto dopanic;
661		}
662
663#ifdef DIAGNOSTIC
664		if (interrupt_depth && !panicking) {
665			printf("trap: calling uvm_fault() from interrupt!\n");
666			goto dopanic;
667		}
668#endif
669
670#ifdef COMPAT_HPUX
671		if (ISHPMMADDR(va)) {
672			int pmap_mapmulti(pmap_t, vaddr_t);
673			vaddr_t bva;
674
675			rv = pmap_mapmulti(map->pmap, va);
676			if (rv != 0) {
677				bva = HPMMBASEADDR(va);
678				rv = uvm_fault(map, bva, ftype);
679				if (rv == 0)
680					(void) pmap_mapmulti(map->pmap, va);
681			}
682		} else
683#endif
684		rv = uvm_fault(map, va, ftype);
685#ifdef DEBUG
686		if (rv && MDB_ISPID(p->p_pid))
687			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
688			    map, va, ftype, rv);
689#endif
690		/*
691		 * If this was a stack access we keep track of the maximum
692		 * accessed stack size.  Also, if vm_fault gets a protection
693		 * failure it is due to accessing the stack region outside
694		 * the current limit and we need to reflect that as an access
695		 * error.
696		 */
697		if (rv == 0) {
698			if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr)
699				uvm_grow(p, va);
700
701			if (type == T_MMUFLT) {
702#ifdef M68040
703				if (cputype == CPU_68040)
704					(void) writeback(&frame, 1);
705#endif
706				return;
707			}
708			goto out;
709		}
710		if (rv == EACCES) {
711			ksi.ksi_code = SEGV_ACCERR;
712			rv = EFAULT;
713		} else
714			ksi.ksi_code = SEGV_MAPERR;
715		if (type == T_MMUFLT) {
716			if (l->l_addr->u_pcb.pcb_onfault)
717				goto copyfault;
718			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
719			    map, va, ftype, rv);
720			printf("  type %x, code [mmu,,ssw]: %x\n",
721			       type, code);
722			goto dopanic;
723		}
724		ksi.ksi_addr = (void *)v;
725		if (rv == ENOMEM) {
726			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
727			       p->p_pid, p->p_comm,
728			       l->l_cred ?
729			       kauth_cred_geteuid(l->l_cred) : -1);
730			ksi.ksi_signo = SIGKILL;
731		} else {
732			ksi.ksi_signo = SIGSEGV;
733		}
734		break;
735	    }
736	}
737	trapsignal(l, &ksi);
738	if ((type & T_USER) == 0)
739		return;
740out:
741	userret(l, &frame, sticks, v, 1);
742}
743
744#ifdef M68040
745#ifdef DEBUG
746struct writebackstats {
747	int calls;
748	int cpushes;
749	int move16s;
750	int wb1s, wb2s, wb3s;
751	int wbsize[4];
752} wbstats;
753
754const char *f7sz[] = { "longword", "byte", "word", "line" };
755const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
756const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
757		 "M-code", "k-data", "k-code", "RES" };
758const char wberrstr[] =
759    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
760#endif
761
762int
763writeback(struct frame *fp, int docachepush)
764{
765	struct fmt7 *f = &fp->f_fmt7;
766	struct lwp *l = curlwp;
767	struct proc *p = l->l_proc;
768	int err = 0;
769	u_int fa;
770	caddr_t oonfault = l->l_addr->u_pcb.pcb_onfault;
771	paddr_t pa;
772
773#ifdef DEBUG
774	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
775		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
776		dumpssw(f->f_ssw);
777	}
778	wbstats.calls++;
779#endif
780	/*
781	 * Deal with special cases first.
782	 */
783	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
784		/*
785		 * Dcache push fault.
786		 * Line-align the address and write out the push data to
787		 * the indicated physical address.
788		 */
789#ifdef DEBUG
790		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
791			printf(" pushing %s to PA %x, data %x",
792			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
793			       f->f_fa, f->f_pd0);
794			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
795				printf("/%x/%x/%x",
796				       f->f_pd1, f->f_pd2, f->f_pd3);
797			printf("\n");
798		}
799		if (f->f_wb1s & SSW4_WBSV)
800			panic("writeback: cache push with WB1S valid");
801		wbstats.cpushes++;
802#endif
803		/*
804		 * XXX there are security problems if we attempt to do a
805		 * cache push after a signal handler has been called.
806		 */
807		if (docachepush) {
808			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
809			    trunc_page(f->f_fa), VM_PROT_WRITE,
810			    VM_PROT_WRITE|PMAP_WIRED);
811			pmap_update(pmap_kernel());
812			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
813			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
814			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
815			DCFL(pa);
816			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
817				    (vaddr_t)&vmmap[PAGE_SIZE]);
818			pmap_update(pmap_kernel());
819		} else
820			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
821			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
822	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
823		/*
824		 * MOVE16 fault.
825		 * Line-align the address and write out the push data to
826		 * the indicated virtual address.
827		 */
828#ifdef DEBUG
829		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
830			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
831			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
832			       f->f_pd2, f->f_pd3);
833		if (f->f_wb1s & SSW4_WBSV)
834			panic("writeback: MOVE16 with WB1S valid");
835		wbstats.move16s++;
836#endif
837		if (KDFAULT(f->f_wb1s))
838			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
839		else
840			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
841		if (err) {
842			fa = f->f_fa & ~0xF;
843#ifdef DEBUG
844			if (mmudebug & MDB_WBFAILED)
845				printf(wberrstr, p->p_pid, p->p_comm,
846				       "MOVE16", fp->f_pc, f->f_fa,
847				       f->f_fa & ~0xF, f->f_pd0);
848#endif
849		}
850	} else if (f->f_wb1s & SSW4_WBSV) {
851		/*
852		 * Writeback #1.
853		 * Position the "memory-aligned" data and write it out.
854		 */
855		u_int wb1d = f->f_wb1d;
856		int off;
857
858#ifdef DEBUG
859		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
860			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
861		wbstats.wb1s++;
862		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
863#endif
864		off = (f->f_wb1a & 3) * 8;
865		switch (f->f_wb1s & SSW4_SZMASK) {
866		case SSW4_SZLW:
867			if (off)
868				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
869			if (KDFAULT(f->f_wb1s))
870				*(long *)f->f_wb1a = wb1d;
871			else
872				err = suword((caddr_t)f->f_wb1a, wb1d);
873			break;
874		case SSW4_SZB:
875			off = 24 - off;
876			if (off)
877				wb1d >>= off;
878			if (KDFAULT(f->f_wb1s))
879				*(char *)f->f_wb1a = wb1d;
880			else
881				err = subyte((caddr_t)f->f_wb1a, wb1d);
882			break;
883		case SSW4_SZW:
884			off = (off + 16) % 32;
885			if (off)
886				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
887			if (KDFAULT(f->f_wb1s))
888				*(short *)f->f_wb1a = wb1d;
889			else
890				err = susword((caddr_t)f->f_wb1a, wb1d);
891			break;
892		}
893		if (err) {
894			fa = f->f_wb1a;
895#ifdef DEBUG
896			if (mmudebug & MDB_WBFAILED)
897				printf(wberrstr, p->p_pid, p->p_comm,
898				       "#1", fp->f_pc, f->f_fa,
899				       f->f_wb1a, f->f_wb1d);
900#endif
901		}
902	}
903	/*
904	 * Deal with the "normal" writebacks.
905	 *
906	 * XXX writeback2 is known to reflect a LINE size writeback after
907	 * a MOVE16 was already dealt with above.  Ignore it.
908	 */
909	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
910	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
911#ifdef DEBUG
912		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
913			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
914		wbstats.wb2s++;
915		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
916#endif
917		switch (f->f_wb2s & SSW4_SZMASK) {
918		case SSW4_SZLW:
919			if (KDFAULT(f->f_wb2s))
920				*(long *)f->f_wb2a = f->f_wb2d;
921			else
922				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
923			break;
924		case SSW4_SZB:
925			if (KDFAULT(f->f_wb2s))
926				*(char *)f->f_wb2a = f->f_wb2d;
927			else
928				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
929			break;
930		case SSW4_SZW:
931			if (KDFAULT(f->f_wb2s))
932				*(short *)f->f_wb2a = f->f_wb2d;
933			else
934				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
935			break;
936		}
937		if (err) {
938			fa = f->f_wb2a;
939#ifdef DEBUG
940			if (mmudebug & MDB_WBFAILED) {
941				printf(wberrstr, p->p_pid, p->p_comm,
942				       "#2", fp->f_pc, f->f_fa,
943				       f->f_wb2a, f->f_wb2d);
944				dumpssw(f->f_ssw);
945				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
946			}
947#endif
948		}
949	}
950	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
951#ifdef DEBUG
952		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
953			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
954		wbstats.wb3s++;
955		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
956#endif
957		switch (f->f_wb3s & SSW4_SZMASK) {
958		case SSW4_SZLW:
959			if (KDFAULT(f->f_wb3s))
960				*(long *)f->f_wb3a = f->f_wb3d;
961			else
962				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
963			break;
964		case SSW4_SZB:
965			if (KDFAULT(f->f_wb3s))
966				*(char *)f->f_wb3a = f->f_wb3d;
967			else
968				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
969			break;
970		case SSW4_SZW:
971			if (KDFAULT(f->f_wb3s))
972				*(short *)f->f_wb3a = f->f_wb3d;
973			else
974				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
975			break;
976#ifdef DEBUG
977		case SSW4_SZLN:
978			panic("writeback: wb3s indicates LINE write");
979#endif
980		}
981		if (err) {
982			fa = f->f_wb3a;
983#ifdef DEBUG
984			if (mmudebug & MDB_WBFAILED)
985				printf(wberrstr, p->p_pid, p->p_comm,
986				       "#3", fp->f_pc, f->f_fa,
987				       f->f_wb3a, f->f_wb3d);
988#endif
989		}
990	}
991	l->l_addr->u_pcb.pcb_onfault = oonfault;
992	if (err)
993		err = SIGSEGV;
994	return (err);
995}
996
997#ifdef DEBUG
998void
999dumpssw(u_short ssw)
1000{
1001	printf(" SSW: %x: ", ssw);
1002	if (ssw & SSW4_CP)
1003		printf("CP,");
1004	if (ssw & SSW4_CU)
1005		printf("CU,");
1006	if (ssw & SSW4_CT)
1007		printf("CT,");
1008	if (ssw & SSW4_CM)
1009		printf("CM,");
1010	if (ssw & SSW4_MA)
1011		printf("MA,");
1012	if (ssw & SSW4_ATC)
1013		printf("ATC,");
1014	if (ssw & SSW4_LK)
1015		printf("LK,");
1016	if (ssw & SSW4_RW)
1017		printf("RW,");
1018	printf(" SZ=%s, TT=%s, TM=%s\n",
1019	       f7sz[(ssw & SSW4_SZMASK) >> 5],
1020	       f7tt[(ssw & SSW4_TTMASK) >> 3],
1021	       f7tm[ssw & SSW4_TMMASK]);
1022}
1023
1024void
1025dumpwb(int num, u_short s, u_int a, u_int d)
1026{
1027	struct proc *p = curproc;
1028	paddr_t pa;
1029
1030	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
1031	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
1032	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
1033	printf("               PA ");
1034	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
1035		printf("<invalid address>");
1036	else
1037		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
1038	printf("\n");
1039}
1040#endif
1041#endif
1042
1043/*
1044 * Allocation routines for software interrupts.
1045 */
1046u_long
1047allocate_sir(void (*proc)(void *), void *arg)
1048{
1049	int bit;
1050
1051	if( next_sir >= NSIR )
1052		panic("allocate_sir: none left");
1053	bit = next_sir++;
1054	sir_routines[bit] = proc;
1055	sir_args[bit] = arg;
1056	return (1 << bit);
1057}
1058
1059void
1060init_sir(void)
1061{
1062	extern void netintr(void);
1063
1064	sir_routines[0] = (void (*)(void *))netintr;
1065	sir_routines[1] = softclock;
1066	next_sir = 2;
1067}
1068