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