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