trap.c revision 1.28
1/*	$NetBSD: trap.c,v 1.28 2000/12/19 21:09:57 scw 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		p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL;
380		sigdelset(&p->p_sigignore, SIGILL);
381		sigdelset(&p->p_sigcatch, SIGILL);
382		sigdelset(&p->p_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 != KERN_SUCCESS) {
616				bva = HPMMBASEADDR(va);
617				rv = uvm_fault(map, bva, 0, ftype);
618				if (rv == KERN_SUCCESS)
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 == KERN_SUCCESS) {
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 == KERN_PROTECTION_FAILURE)
645				rv = KERN_INVALID_ADDRESS;
646		}
647		if (rv == KERN_SUCCESS) {
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 == KERN_RESOURCE_SHORTAGE) {
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			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
755			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
756			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
757			DCFL(pa);
758			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
759				    (vaddr_t)&vmmap[NBPG]);
760		} else
761			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
762			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
763	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
764		/*
765		 * MOVE16 fault.
766		 * Line-align the address and write out the push data to
767		 * the indicated virtual address.
768		 */
769#ifdef DEBUG
770		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
771			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
772			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
773			       f->f_pd2, f->f_pd3);
774		if (f->f_wb1s & SSW4_WBSV)
775			panic("writeback: MOVE16 with WB1S valid");
776		wbstats.move16s++;
777#endif
778		if (KDFAULT(f->f_wb1s))
779			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
780		else
781			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
782		if (err) {
783			fa = f->f_fa & ~0xF;
784#ifdef DEBUG
785			if (mmudebug & MDB_WBFAILED)
786				printf(wberrstr, p->p_pid, p->p_comm,
787				       "MOVE16", fp->f_pc, f->f_fa,
788				       f->f_fa & ~0xF, f->f_pd0);
789#endif
790		}
791	} else if (f->f_wb1s & SSW4_WBSV) {
792		/*
793		 * Writeback #1.
794		 * Position the "memory-aligned" data and write it out.
795		 */
796		u_int wb1d = f->f_wb1d;
797		int off;
798
799#ifdef DEBUG
800		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
801			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
802		wbstats.wb1s++;
803		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
804#endif
805		off = (f->f_wb1a & 3) * 8;
806		switch (f->f_wb1s & SSW4_SZMASK) {
807		case SSW4_SZLW:
808			if (off)
809				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
810			if (KDFAULT(f->f_wb1s))
811				*(long *)f->f_wb1a = wb1d;
812			else
813				err = suword((caddr_t)f->f_wb1a, wb1d);
814			break;
815		case SSW4_SZB:
816			off = 24 - off;
817			if (off)
818				wb1d >>= off;
819			if (KDFAULT(f->f_wb1s))
820				*(char *)f->f_wb1a = wb1d;
821			else
822				err = subyte((caddr_t)f->f_wb1a, wb1d);
823			break;
824		case SSW4_SZW:
825			off = (off + 16) % 32;
826			if (off)
827				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
828			if (KDFAULT(f->f_wb1s))
829				*(short *)f->f_wb1a = wb1d;
830			else
831				err = susword((caddr_t)f->f_wb1a, wb1d);
832			break;
833		}
834		if (err) {
835			fa = f->f_wb1a;
836#ifdef DEBUG
837			if (mmudebug & MDB_WBFAILED)
838				printf(wberrstr, p->p_pid, p->p_comm,
839				       "#1", fp->f_pc, f->f_fa,
840				       f->f_wb1a, f->f_wb1d);
841#endif
842		}
843	}
844	/*
845	 * Deal with the "normal" writebacks.
846	 *
847	 * XXX writeback2 is known to reflect a LINE size writeback after
848	 * a MOVE16 was already dealt with above.  Ignore it.
849	 */
850	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
851	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
852#ifdef DEBUG
853		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
854			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
855		wbstats.wb2s++;
856		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
857#endif
858		switch (f->f_wb2s & SSW4_SZMASK) {
859		case SSW4_SZLW:
860			if (KDFAULT(f->f_wb2s))
861				*(long *)f->f_wb2a = f->f_wb2d;
862			else
863				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
864			break;
865		case SSW4_SZB:
866			if (KDFAULT(f->f_wb2s))
867				*(char *)f->f_wb2a = f->f_wb2d;
868			else
869				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
870			break;
871		case SSW4_SZW:
872			if (KDFAULT(f->f_wb2s))
873				*(short *)f->f_wb2a = f->f_wb2d;
874			else
875				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
876			break;
877		}
878		if (err) {
879			fa = f->f_wb2a;
880#ifdef DEBUG
881			if (mmudebug & MDB_WBFAILED) {
882				printf(wberrstr, p->p_pid, p->p_comm,
883				       "#2", fp->f_pc, f->f_fa,
884				       f->f_wb2a, f->f_wb2d);
885				dumpssw(f->f_ssw);
886				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
887			}
888#endif
889		}
890	}
891	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
892#ifdef DEBUG
893		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
894			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
895		wbstats.wb3s++;
896		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
897#endif
898		switch (f->f_wb3s & SSW4_SZMASK) {
899		case SSW4_SZLW:
900			if (KDFAULT(f->f_wb3s))
901				*(long *)f->f_wb3a = f->f_wb3d;
902			else
903				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
904			break;
905		case SSW4_SZB:
906			if (KDFAULT(f->f_wb3s))
907				*(char *)f->f_wb3a = f->f_wb3d;
908			else
909				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
910			break;
911		case SSW4_SZW:
912			if (KDFAULT(f->f_wb3s))
913				*(short *)f->f_wb3a = f->f_wb3d;
914			else
915				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
916			break;
917#ifdef DEBUG
918		case SSW4_SZLN:
919			panic("writeback: wb3s indicates LINE write");
920#endif
921		}
922		if (err) {
923			fa = f->f_wb3a;
924#ifdef DEBUG
925			if (mmudebug & MDB_WBFAILED)
926				printf(wberrstr, p->p_pid, p->p_comm,
927				       "#3", fp->f_pc, f->f_fa,
928				       f->f_wb3a, f->f_wb3d);
929#endif
930		}
931	}
932	p->p_addr->u_pcb.pcb_onfault = oonfault;
933	if (err)
934		err = SIGSEGV;
935	return (err);
936}
937
938#ifdef DEBUG
939void
940dumpssw(ssw)
941	u_short ssw;
942{
943	printf(" SSW: %x: ", ssw);
944	if (ssw & SSW4_CP)
945		printf("CP,");
946	if (ssw & SSW4_CU)
947		printf("CU,");
948	if (ssw & SSW4_CT)
949		printf("CT,");
950	if (ssw & SSW4_CM)
951		printf("CM,");
952	if (ssw & SSW4_MA)
953		printf("MA,");
954	if (ssw & SSW4_ATC)
955		printf("ATC,");
956	if (ssw & SSW4_LK)
957		printf("LK,");
958	if (ssw & SSW4_RW)
959		printf("RW,");
960	printf(" SZ=%s, TT=%s, TM=%s\n",
961	       f7sz[(ssw & SSW4_SZMASK) >> 5],
962	       f7tt[(ssw & SSW4_TTMASK) >> 3],
963	       f7tm[ssw & SSW4_TMMASK]);
964}
965
966void
967dumpwb(num, s, a, d)
968	int num;
969	u_short s;
970	u_int a, d;
971{
972	struct proc *p = curproc;
973	paddr_t pa;
974
975	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
976	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
977	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
978	printf("               PA ");
979	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
980		printf("<invalid address>");
981	else
982		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
983	printf("\n");
984}
985#endif
986#endif
987
988/*
989 * Allocation routines for software interrupts.
990 */
991u_long
992allocate_sir(proc, arg)
993	void (*proc)(void *);
994	void *arg;
995{
996	int bit;
997
998	if( next_sir >= NSIR )
999		panic("allocate_sir: none left");
1000	bit = next_sir++;
1001	sir_routines[bit] = proc;
1002	sir_args[bit] = arg;
1003	return (1 << bit);
1004}
1005
1006void
1007init_sir()
1008{
1009	extern void netintr(void);
1010
1011	sir_routines[0] = (void (*)(void *))netintr;
1012	sir_routines[1] = (void (*)(void *))softclock;
1013	next_sir = 2;
1014}
1015