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