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