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