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