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