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