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