trap.c revision 1.52
1/*	$NetBSD: trap.c,v 1.52 2004/08/28 17:53:01 jdolecek 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.52 2004/08/28 17:53:01 jdolecek 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 panicking = 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		panicking = 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 && !panicking) {
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 (rv == 0) {
711			if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr)
712				uvm_grow(p, va);
713
714			if (type == T_MMUFLT) {
715#ifdef M68040
716				if (cputype == CPU_68040)
717					(void) writeback(&frame, 1);
718#endif
719				return;
720			}
721			l->l_flag &= ~L_SA_PAGEFAULT;
722			goto out;
723		}
724		if (rv == EACCES) {
725			ksi.ksi_code = SEGV_ACCERR;
726			rv = EFAULT;
727		} else
728			ksi.ksi_code = SEGV_MAPERR;
729		if (type == T_MMUFLT) {
730			if (l->l_addr->u_pcb.pcb_onfault)
731				goto copyfault;
732			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
733			    map, va, ftype, rv);
734			printf("  type %x, code [mmu,,ssw]: %x\n",
735			       type, code);
736			goto dopanic;
737		}
738		l->l_flag &= ~L_SA_PAGEFAULT;
739		ksi.ksi_addr = (void *)v;
740		if (rv == ENOMEM) {
741			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
742			       p->p_pid, p->p_comm,
743			       p->p_cred && p->p_ucred ?
744			       p->p_ucred->cr_uid : -1);
745			ksi.ksi_signo = SIGKILL;
746		} else {
747			ksi.ksi_signo = SIGSEGV;
748		}
749		break;
750	    }
751	}
752	trapsignal(l, &ksi);
753	if ((type & T_USER) == 0)
754		return;
755out:
756	userret(l, &frame, sticks, v, 1);
757}
758
759#ifdef M68040
760#ifdef DEBUG
761struct writebackstats {
762	int calls;
763	int cpushes;
764	int move16s;
765	int wb1s, wb2s, wb3s;
766	int wbsize[4];
767} wbstats;
768
769char *f7sz[] = { "longword", "byte", "word", "line" };
770char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
771char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
772		 "M-code", "k-data", "k-code", "RES" };
773char wberrstr[] =
774    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
775#endif
776
777int
778writeback(fp, docachepush)
779	struct frame *fp;
780	int docachepush;
781{
782	struct fmt7 *f = &fp->f_fmt7;
783	struct lwp *l = curlwp;
784	struct proc *p = l->l_proc;
785	int err = 0;
786	u_int fa;
787	caddr_t oonfault = l->l_addr->u_pcb.pcb_onfault;
788	paddr_t pa;
789
790#ifdef DEBUG
791	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
792		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
793		dumpssw(f->f_ssw);
794	}
795	wbstats.calls++;
796#endif
797	/*
798	 * Deal with special cases first.
799	 */
800	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
801		/*
802		 * Dcache push fault.
803		 * Line-align the address and write out the push data to
804		 * the indicated physical address.
805		 */
806#ifdef DEBUG
807		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
808			printf(" pushing %s to PA %x, data %x",
809			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
810			       f->f_fa, f->f_pd0);
811			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
812				printf("/%x/%x/%x",
813				       f->f_pd1, f->f_pd2, f->f_pd3);
814			printf("\n");
815		}
816		if (f->f_wb1s & SSW4_WBSV)
817			panic("writeback: cache push with WB1S valid");
818		wbstats.cpushes++;
819#endif
820		/*
821		 * XXX there are security problems if we attempt to do a
822		 * cache push after a signal handler has been called.
823		 */
824		if (docachepush) {
825			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
826			    trunc_page(f->f_fa), VM_PROT_WRITE,
827			    VM_PROT_WRITE|PMAP_WIRED);
828			pmap_update(pmap_kernel());
829			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
830			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
831			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
832			DCFL(pa);
833			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
834				    (vaddr_t)&vmmap[PAGE_SIZE]);
835			pmap_update(pmap_kernel());
836		} else
837			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
838			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
839	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
840		/*
841		 * MOVE16 fault.
842		 * Line-align the address and write out the push data to
843		 * the indicated virtual address.
844		 */
845#ifdef DEBUG
846		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
847			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
848			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
849			       f->f_pd2, f->f_pd3);
850		if (f->f_wb1s & SSW4_WBSV)
851			panic("writeback: MOVE16 with WB1S valid");
852		wbstats.move16s++;
853#endif
854		if (KDFAULT(f->f_wb1s))
855			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
856		else
857			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
858		if (err) {
859			fa = f->f_fa & ~0xF;
860#ifdef DEBUG
861			if (mmudebug & MDB_WBFAILED)
862				printf(wberrstr, p->p_pid, p->p_comm,
863				       "MOVE16", fp->f_pc, f->f_fa,
864				       f->f_fa & ~0xF, f->f_pd0);
865#endif
866		}
867	} else if (f->f_wb1s & SSW4_WBSV) {
868		/*
869		 * Writeback #1.
870		 * Position the "memory-aligned" data and write it out.
871		 */
872		u_int wb1d = f->f_wb1d;
873		int off;
874
875#ifdef DEBUG
876		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
877			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
878		wbstats.wb1s++;
879		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
880#endif
881		off = (f->f_wb1a & 3) * 8;
882		switch (f->f_wb1s & SSW4_SZMASK) {
883		case SSW4_SZLW:
884			if (off)
885				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
886			if (KDFAULT(f->f_wb1s))
887				*(long *)f->f_wb1a = wb1d;
888			else
889				err = suword((caddr_t)f->f_wb1a, wb1d);
890			break;
891		case SSW4_SZB:
892			off = 24 - off;
893			if (off)
894				wb1d >>= off;
895			if (KDFAULT(f->f_wb1s))
896				*(char *)f->f_wb1a = wb1d;
897			else
898				err = subyte((caddr_t)f->f_wb1a, wb1d);
899			break;
900		case SSW4_SZW:
901			off = (off + 16) % 32;
902			if (off)
903				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
904			if (KDFAULT(f->f_wb1s))
905				*(short *)f->f_wb1a = wb1d;
906			else
907				err = susword((caddr_t)f->f_wb1a, wb1d);
908			break;
909		}
910		if (err) {
911			fa = f->f_wb1a;
912#ifdef DEBUG
913			if (mmudebug & MDB_WBFAILED)
914				printf(wberrstr, p->p_pid, p->p_comm,
915				       "#1", fp->f_pc, f->f_fa,
916				       f->f_wb1a, f->f_wb1d);
917#endif
918		}
919	}
920	/*
921	 * Deal with the "normal" writebacks.
922	 *
923	 * XXX writeback2 is known to reflect a LINE size writeback after
924	 * a MOVE16 was already dealt with above.  Ignore it.
925	 */
926	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
927	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
928#ifdef DEBUG
929		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
930			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
931		wbstats.wb2s++;
932		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
933#endif
934		switch (f->f_wb2s & SSW4_SZMASK) {
935		case SSW4_SZLW:
936			if (KDFAULT(f->f_wb2s))
937				*(long *)f->f_wb2a = f->f_wb2d;
938			else
939				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
940			break;
941		case SSW4_SZB:
942			if (KDFAULT(f->f_wb2s))
943				*(char *)f->f_wb2a = f->f_wb2d;
944			else
945				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
946			break;
947		case SSW4_SZW:
948			if (KDFAULT(f->f_wb2s))
949				*(short *)f->f_wb2a = f->f_wb2d;
950			else
951				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
952			break;
953		}
954		if (err) {
955			fa = f->f_wb2a;
956#ifdef DEBUG
957			if (mmudebug & MDB_WBFAILED) {
958				printf(wberrstr, p->p_pid, p->p_comm,
959				       "#2", fp->f_pc, f->f_fa,
960				       f->f_wb2a, f->f_wb2d);
961				dumpssw(f->f_ssw);
962				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
963			}
964#endif
965		}
966	}
967	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
968#ifdef DEBUG
969		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
970			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
971		wbstats.wb3s++;
972		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
973#endif
974		switch (f->f_wb3s & SSW4_SZMASK) {
975		case SSW4_SZLW:
976			if (KDFAULT(f->f_wb3s))
977				*(long *)f->f_wb3a = f->f_wb3d;
978			else
979				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
980			break;
981		case SSW4_SZB:
982			if (KDFAULT(f->f_wb3s))
983				*(char *)f->f_wb3a = f->f_wb3d;
984			else
985				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
986			break;
987		case SSW4_SZW:
988			if (KDFAULT(f->f_wb3s))
989				*(short *)f->f_wb3a = f->f_wb3d;
990			else
991				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
992			break;
993#ifdef DEBUG
994		case SSW4_SZLN:
995			panic("writeback: wb3s indicates LINE write");
996#endif
997		}
998		if (err) {
999			fa = f->f_wb3a;
1000#ifdef DEBUG
1001			if (mmudebug & MDB_WBFAILED)
1002				printf(wberrstr, p->p_pid, p->p_comm,
1003				       "#3", fp->f_pc, f->f_fa,
1004				       f->f_wb3a, f->f_wb3d);
1005#endif
1006		}
1007	}
1008	l->l_addr->u_pcb.pcb_onfault = oonfault;
1009	if (err)
1010		err = SIGSEGV;
1011	return (err);
1012}
1013
1014#ifdef DEBUG
1015void
1016dumpssw(ssw)
1017	u_short ssw;
1018{
1019	printf(" SSW: %x: ", ssw);
1020	if (ssw & SSW4_CP)
1021		printf("CP,");
1022	if (ssw & SSW4_CU)
1023		printf("CU,");
1024	if (ssw & SSW4_CT)
1025		printf("CT,");
1026	if (ssw & SSW4_CM)
1027		printf("CM,");
1028	if (ssw & SSW4_MA)
1029		printf("MA,");
1030	if (ssw & SSW4_ATC)
1031		printf("ATC,");
1032	if (ssw & SSW4_LK)
1033		printf("LK,");
1034	if (ssw & SSW4_RW)
1035		printf("RW,");
1036	printf(" SZ=%s, TT=%s, TM=%s\n",
1037	       f7sz[(ssw & SSW4_SZMASK) >> 5],
1038	       f7tt[(ssw & SSW4_TTMASK) >> 3],
1039	       f7tm[ssw & SSW4_TMMASK]);
1040}
1041
1042void
1043dumpwb(num, s, a, d)
1044	int num;
1045	u_short s;
1046	u_int a, d;
1047{
1048	struct proc *p = curproc;
1049	paddr_t pa;
1050
1051	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
1052	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
1053	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
1054	printf("               PA ");
1055	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
1056		printf("<invalid address>");
1057	else
1058		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
1059	printf("\n");
1060}
1061#endif
1062#endif
1063
1064/*
1065 * Allocation routines for software interrupts.
1066 */
1067u_long
1068allocate_sir(proc, arg)
1069	void (*proc)(void *);
1070	void *arg;
1071{
1072	int bit;
1073
1074	if( next_sir >= NSIR )
1075		panic("allocate_sir: none left");
1076	bit = next_sir++;
1077	sir_routines[bit] = proc;
1078	sir_args[bit] = arg;
1079	return (1 << bit);
1080}
1081
1082void
1083init_sir()
1084{
1085	extern void netintr(void);
1086
1087	sir_routines[0] = (void (*)(void *))netintr;
1088	sir_routines[1] = softclock;
1089	next_sir = 2;
1090}
1091