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