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