trap.c revision 1.80
1/*	$NetBSD: trap.c,v 1.80 2010/06/06 04:50:08 mrg 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.80 2010/06/06 04:50:08 mrg Exp $");
88
89#include "opt_ddb.h"
90#include "opt_execfmt.h"
91#include "opt_kgdb.h"
92#include "opt_compat_sunos.h"
93#include "opt_m68k_arch.h"
94
95#include <sys/param.h>
96#include <sys/systm.h>
97#include <sys/proc.h>
98#include <sys/acct.h>
99#include <sys/kernel.h>
100#include <sys/signalvar.h>
101#include <sys/resourcevar.h>
102#include <sys/sa.h>
103#include <sys/savar.h>
104#include <sys/syscall.h>
105#include <sys/syslog.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	struct pcb *pcb;
307	void *onfault;
308	ksiginfo_t ksi;
309	int s;
310	int rv;
311	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
312	static int panicking = 0;
313
314	uvmexp.traps++;
315	l = curlwp;
316	p = l->l_proc;
317	pcb = lwp_getpcb(l);
318
319	KSI_INIT_TRAP(&ksi);
320	ksi.ksi_trap = type & ~T_USER;
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		onfault = pcb->pcb_onfault;
369		if (onfault == NULL)
370			goto dopanic;
371		rv = EFAULT;
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)onfault;
384		fp->f_regs[D0] = rv;
385		return;
386
387	case T_BUSERR|T_USER:	/* bus error */
388	case T_ADDRERR|T_USER:	/* address error */
389		ksi.ksi_addr = (void *)v;
390		ksi.ksi_signo = SIGBUS;
391		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
392			BUS_OBJERR : BUS_ADRERR;
393		break;
394
395	case T_COPERR:		/* kernel coprocessor violation */
396	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
397	case T_FMTERR:		/* ...just in case... */
398	/*
399	 * The user has most likely trashed the RTE or FP state info
400	 * in the stack frame of a signal handler.
401	 */
402		printf("pid %d: kernel %s exception\n", p->p_pid,
403		       type==T_COPERR ? "coprocessor" : "format");
404		type |= T_USER;
405
406		mutex_enter(p->p_lock);
407		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
408		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
409		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
410		sigdelset(&l->l_sigmask, SIGILL);
411		mutex_exit(p->p_lock);
412
413		ksi.ksi_signo = SIGILL;
414		ksi.ksi_addr = (void *)(int)fp->f_format;
415				/* XXX was ILL_RESAD_FAULT */
416		ksi.ksi_code = (type == T_COPERR) ?
417			ILL_COPROC : ILL_ILLOPC;
418		break;
419
420	case T_COPERR|T_USER:	/* user coprocessor violation */
421	/* What is a proper response here? */
422		ksi.ksi_signo = SIGFPE;
423		ksi.ksi_code = FPE_FLTINV;
424		break;
425
426	case T_FPERR|T_USER:	/* 68881 exceptions */
427	/*
428	 * We pass along the 68881 status register which locore stashed
429	 * in code for us.
430	 */
431		ksi.ksi_signo = SIGFPE;
432		ksi.ksi_code = fpsr2siginfocode(code);
433		break;
434
435#ifdef M68040
436	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
437	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
438		/* XXX need to FSAVE */
439		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
440		       p->p_pid, p->p_comm,
441		       fp->f_format == 2 ? "instruction" : "data type",
442		       fp->f_pc, fp->f_fmt2.f_iaddr);
443		/* XXX need to FRESTORE */
444		ksi.ksi_signo = SIGFPE;
445		ksi.ksi_code = FPE_FLTINV;
446		break;
447#endif
448
449	case T_ILLINST|T_USER:	/* illegal instruction fault */
450	case T_PRIVINST|T_USER:	/* privileged instruction fault */
451		ksi.ksi_addr = (void *)(int)fp->f_format;
452				/* XXX was ILL_PRIVIN_FAULT */
453		ksi.ksi_signo = SIGILL;
454		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
455			ILL_PRVOPC : ILL_ILLOPC;
456		break;
457
458	case T_ZERODIV|T_USER:	/* Divide by zero */
459		ksi.ksi_addr = (void *)(int)fp->f_format;
460				/* XXX was FPE_INTDIV_TRAP */
461		ksi.ksi_signo = SIGFPE;
462		ksi.ksi_code = FPE_FLTDIV;
463		break;
464
465	case T_CHKINST|T_USER:	/* CHK instruction trap */
466		ksi.ksi_addr = (void *)(int)fp->f_format;
467				/* XXX was FPE_SUBRNG_TRAP */
468		ksi.ksi_signo = SIGFPE;
469		break;
470
471	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
472		ksi.ksi_addr = (void *)(int)fp->f_format;
473				/* XXX was FPE_INTOVF_TRAP */
474		ksi.ksi_signo = SIGFPE;
475		break;
476
477	/*
478	 * XXX: Trace traps are a nightmare.
479	 *
480	 *	HP-UX uses trap #1 for breakpoints,
481	 *	NetBSD/m68k uses trap #2,
482	 *	SUN 3.x uses trap #15,
483	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
484	 *	handled elsewhere).
485	 *
486	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
487	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
488	 * supported yet.
489	 *
490	 * XXX: We should never get kernel-mode T_TRAP15
491	 * XXX: because locore.s now gives them special treatment.
492	 */
493	case T_TRAP15:		/* kernel breakpoint */
494#ifdef DEBUG
495		printf("unexpected kernel trace trap, type = %d\n", type);
496		printf("program counter = 0x%x\n", fp->f_pc);
497#endif
498		fp->f_sr &= ~PSL_T;
499		return;
500
501	case T_TRACE|T_USER:	/* user trace trap */
502#ifdef COMPAT_SUNOS
503		/*
504		 * SunOS uses Trap #2 for a "CPU cache flush".
505		 * Just flush the on-chip caches and return.
506		 */
507		if (p->p_emul == &emul_sunos) {
508			ICIA();
509			DCIU();
510			return;
511		}
512#endif
513		/* FALLTHROUGH */
514	case T_TRACE:		/* tracing a trap instruction */
515	case T_TRAP15|T_USER:	/* SUN user trace trap */
516		fp->f_sr &= ~PSL_T;
517		ksi.ksi_signo = SIGTRAP;
518		break;
519
520	case T_ASTFLT:		/* system async trap, cannot happen */
521		goto dopanic;
522
523	case T_ASTFLT|T_USER:	/* user async trap */
524		astpending = 0;
525		/*
526		 * We check for software interrupts first.  This is because
527		 * they are at a higher level than ASTs, and on a VAX would
528		 * interrupt the AST.  We assume that if we are processing
529		 * an AST that we must be at IPL0 so we don't bother to
530		 * check.  Note that we ensure that we are at least at SIR
531		 * IPL while processing the SIR.
532		 */
533		spl1();
534		/* fall into... */
535
536	case T_SSIR:		/* software interrupt */
537	case T_SSIR|T_USER:
538		/*
539		 * If this was not an AST trap, we are all done.
540		 */
541		if (type != (T_ASTFLT|T_USER)) {
542			uvmexp.traps--;
543			return;
544		}
545		spl0();
546		if (l->l_pflag & LP_OWEUPC) {
547			l->l_pflag &= ~LP_OWEUPC;
548			ADDUPROF(l);
549		}
550		if (curcpu()->ci_want_resched)
551			preempt();
552		goto out;
553
554	case T_MMUFLT:		/* kernel mode page fault */
555		/*
556		 * If we were doing profiling ticks or other user mode
557		 * stuff from interrupt code, Just Say No.
558		 */
559		onfault = pcb->pcb_onfault;
560		if (onfault == fubail || onfault == subail) {
561			rv = EFAULT;
562			goto copyfault;
563		}
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		vm_prot_t ftype;
572		extern struct vm_map *kernel_map;
573
574		onfault = pcb->pcb_onfault;
575
576#ifdef DEBUG
577		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
578		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
579		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
580#endif
581		/*
582		 * It is only a kernel address space fault iff:
583		 * 	1. (type & T_USER) == 0  and
584		 * 	2. pcb_onfault not set or
585		 *	3. pcb_onfault set but supervisor space data fault
586		 * The last can occur during an exec() copyin where the
587		 * argument space is lazy-allocated.
588		 */
589		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
590			map = kernel_map;
591		else {
592			map = vm ? &vm->vm_map : kernel_map;
593			if ((l->l_flag & LW_SA)
594			    && (~l->l_pflag & LP_SA_NOBLOCK)) {
595				l->l_savp->savp_faultaddr = (vaddr_t)v;
596				l->l_pflag |= LP_SA_PAGEFAULT;
597			}
598		}
599
600		if (WRFAULT(code))
601			ftype = VM_PROT_WRITE;
602		else
603			ftype = VM_PROT_READ;
604
605		va = trunc_page((vaddr_t)v);
606
607		if (map == kernel_map && va == 0) {
608			printf("trap: bad kernel %s access at 0x%x\n",
609			    (ftype & VM_PROT_WRITE) ? "read/write" :
610			    "read", v);
611			goto dopanic;
612		}
613
614#ifdef DIAGNOSTIC
615		if (interrupt_depth && !panicking) {
616			printf("trap: calling uvm_fault() from interrupt!\n");
617			goto dopanic;
618		}
619#endif
620
621		pcb->pcb_onfault = NULL;
622		rv = uvm_fault(map, va, ftype);
623		pcb->pcb_onfault = onfault;
624#ifdef DEBUG
625		if (rv && MDB_ISPID(p->p_pid))
626			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
627			    map, va, ftype, rv);
628#endif
629		/*
630		 * If this was a stack access we keep track of the maximum
631		 * accessed stack size.  Also, if vm_fault gets a protection
632		 * failure it is due to accessing the stack region outside
633		 * the current limit and we need to reflect that as an access
634		 * error.
635		 */
636		if (rv == 0) {
637			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
638				uvm_grow(p, va);
639
640			if (type == T_MMUFLT) {
641#ifdef M68040
642				if (cputype == CPU_68040)
643					(void) writeback(fp, 1);
644#endif
645				return;
646			}
647			l->l_pflag &= ~LP_SA_PAGEFAULT;
648			goto out;
649		}
650		if (rv == EACCES) {
651			ksi.ksi_code = SEGV_ACCERR;
652			rv = EFAULT;
653		} else
654			ksi.ksi_code = SEGV_MAPERR;
655		if (type == T_MMUFLT) {
656			if (onfault)
657				goto copyfault;
658			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
659			    map, va, ftype, rv);
660			printf("  type %x, code [mmu,,ssw]: %x\n",
661			       type, code);
662			goto dopanic;
663		}
664		l->l_pflag &= ~LP_SA_PAGEFAULT;
665		ksi.ksi_addr = (void *)v;
666		if (rv == ENOMEM) {
667			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
668			       p->p_pid, p->p_comm,
669			       l->l_cred ?
670			       kauth_cred_geteuid(l->l_cred) : -1);
671			ksi.ksi_signo = SIGKILL;
672		} else {
673			ksi.ksi_signo = SIGSEGV;
674		}
675		break;
676	    }
677	}
678	trapsignal(l, &ksi);
679	if ((type & T_USER) == 0)
680		return;
681out:
682	userret(l, fp, sticks, v, 1);
683}
684
685#ifdef M68040
686#ifdef DEBUG
687struct writebackstats {
688	int calls;
689	int cpushes;
690	int move16s;
691	int wb1s, wb2s, wb3s;
692	int wbsize[4];
693} wbstats;
694
695const char *f7sz[] = { "longword", "byte", "word", "line" };
696const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
697const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
698		 "M-code", "k-data", "k-code", "RES" };
699const char wberrstr[] =
700    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
701#endif
702
703int
704writeback(struct frame *fp, int docachepush)
705{
706	struct fmt7 *f = &fp->f_fmt7;
707	struct lwp *l = curlwp;
708	struct proc *p = l->l_proc;
709	struct pcb *pcb = lwp_getpcb(l);
710	int err = 0;
711	u_int fa;
712	void *oonfault = pcb->pcb_onfault;
713	paddr_t pa;
714
715#ifdef DEBUG
716	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
717		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
718		dumpssw(f->f_ssw);
719	}
720	wbstats.calls++;
721#endif
722	/*
723	 * Deal with special cases first.
724	 */
725	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
726		/*
727		 * Dcache push fault.
728		 * Line-align the address and write out the push data to
729		 * the indicated physical address.
730		 */
731#ifdef DEBUG
732		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
733			printf(" pushing %s to PA %x, data %x",
734			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
735			       f->f_fa, f->f_pd0);
736			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
737				printf("/%x/%x/%x",
738				       f->f_pd1, f->f_pd2, f->f_pd3);
739			printf("\n");
740		}
741		if (f->f_wb1s & SSW4_WBSV)
742			panic("writeback: cache push with WB1S valid");
743		wbstats.cpushes++;
744#endif
745		/*
746		 * XXX there are security problems if we attempt to do a
747		 * cache push after a signal handler has been called.
748		 */
749		if (docachepush) {
750			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
751			    trunc_page(f->f_fa), VM_PROT_WRITE,
752			    VM_PROT_WRITE|PMAP_WIRED);
753			pmap_update(pmap_kernel());
754			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
755			memcpy((void *)fa, (void *)&f->f_pd0, 16);
756			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
757			DCFL(pa);
758			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
759				    (vaddr_t)&vmmap[PAGE_SIZE]);
760			pmap_update(pmap_kernel());
761		} else
762			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
763			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
764	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
765		/*
766		 * MOVE16 fault.
767		 * Line-align the address and write out the push data to
768		 * the indicated virtual address.
769		 */
770#ifdef DEBUG
771		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
772			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
773			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
774			       f->f_pd2, f->f_pd3);
775		if (f->f_wb1s & SSW4_WBSV)
776			panic("writeback: MOVE16 with WB1S valid");
777		wbstats.move16s++;
778#endif
779		if (KDFAULT(f->f_wb1s))
780			memcpy((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0, 16);
781		else
782			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
783		if (err) {
784			fa = f->f_fa & ~0xF;
785#ifdef DEBUG
786			if (mmudebug & MDB_WBFAILED)
787				printf(wberrstr, p->p_pid, p->p_comm,
788				       "MOVE16", fp->f_pc, f->f_fa,
789				       f->f_fa & ~0xF, f->f_pd0);
790#endif
791		}
792	} else if (f->f_wb1s & SSW4_WBSV) {
793		/*
794		 * Writeback #1.
795		 * Position the "memory-aligned" data and write it out.
796		 */
797		u_int wb1d = f->f_wb1d;
798		int off;
799
800#ifdef DEBUG
801		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
802			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
803		wbstats.wb1s++;
804		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
805#endif
806		off = (f->f_wb1a & 3) * 8;
807		switch (f->f_wb1s & SSW4_SZMASK) {
808		case SSW4_SZLW:
809			if (off)
810				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
811			if (KDFAULT(f->f_wb1s))
812				*(long *)f->f_wb1a = wb1d;
813			else
814				err = suword((void *)f->f_wb1a, wb1d);
815			break;
816		case SSW4_SZB:
817			off = 24 - off;
818			if (off)
819				wb1d >>= off;
820			if (KDFAULT(f->f_wb1s))
821				*(char *)f->f_wb1a = wb1d;
822			else
823				err = subyte((void *)f->f_wb1a, wb1d);
824			break;
825		case SSW4_SZW:
826			off = (off + 16) % 32;
827			if (off)
828				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
829			if (KDFAULT(f->f_wb1s))
830				*(short *)f->f_wb1a = wb1d;
831			else
832				err = susword((void *)f->f_wb1a, wb1d);
833			break;
834		}
835		if (err) {
836			fa = f->f_wb1a;
837#ifdef DEBUG
838			if (mmudebug & MDB_WBFAILED)
839				printf(wberrstr, p->p_pid, p->p_comm,
840				       "#1", fp->f_pc, f->f_fa,
841				       f->f_wb1a, f->f_wb1d);
842#endif
843		}
844	}
845	/*
846	 * Deal with the "normal" writebacks.
847	 *
848	 * XXX writeback2 is known to reflect a LINE size writeback after
849	 * a MOVE16 was already dealt with above.  Ignore it.
850	 */
851	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
852	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
853#ifdef DEBUG
854		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
855			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
856		wbstats.wb2s++;
857		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
858#endif
859		switch (f->f_wb2s & SSW4_SZMASK) {
860		case SSW4_SZLW:
861			if (KDFAULT(f->f_wb2s))
862				*(long *)f->f_wb2a = f->f_wb2d;
863			else
864				err = suword((void *)f->f_wb2a, f->f_wb2d);
865			break;
866		case SSW4_SZB:
867			if (KDFAULT(f->f_wb2s))
868				*(char *)f->f_wb2a = f->f_wb2d;
869			else
870				err = subyte((void *)f->f_wb2a, f->f_wb2d);
871			break;
872		case SSW4_SZW:
873			if (KDFAULT(f->f_wb2s))
874				*(short *)f->f_wb2a = f->f_wb2d;
875			else
876				err = susword((void *)f->f_wb2a, f->f_wb2d);
877			break;
878		}
879		if (err) {
880			fa = f->f_wb2a;
881#ifdef DEBUG
882			if (mmudebug & MDB_WBFAILED) {
883				printf(wberrstr, p->p_pid, p->p_comm,
884				       "#2", fp->f_pc, f->f_fa,
885				       f->f_wb2a, f->f_wb2d);
886				dumpssw(f->f_ssw);
887				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
888			}
889#endif
890		}
891	}
892	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
893#ifdef DEBUG
894		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
895			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
896		wbstats.wb3s++;
897		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
898#endif
899		switch (f->f_wb3s & SSW4_SZMASK) {
900		case SSW4_SZLW:
901			if (KDFAULT(f->f_wb3s))
902				*(long *)f->f_wb3a = f->f_wb3d;
903			else
904				err = suword((void *)f->f_wb3a, f->f_wb3d);
905			break;
906		case SSW4_SZB:
907			if (KDFAULT(f->f_wb3s))
908				*(char *)f->f_wb3a = f->f_wb3d;
909			else
910				err = subyte((void *)f->f_wb3a, f->f_wb3d);
911			break;
912		case SSW4_SZW:
913			if (KDFAULT(f->f_wb3s))
914				*(short *)f->f_wb3a = f->f_wb3d;
915			else
916				err = susword((void *)f->f_wb3a, f->f_wb3d);
917			break;
918#ifdef DEBUG
919		case SSW4_SZLN:
920			panic("writeback: wb3s indicates LINE write");
921#endif
922		}
923		if (err) {
924			fa = f->f_wb3a;
925#ifdef DEBUG
926			if (mmudebug & MDB_WBFAILED)
927				printf(wberrstr, p->p_pid, p->p_comm,
928				       "#3", fp->f_pc, f->f_fa,
929				       f->f_wb3a, f->f_wb3d);
930#endif
931		}
932	}
933	pcb->pcb_onfault = oonfault;
934	if (err)
935		err = SIGSEGV;
936	return (err);
937}
938
939#ifdef DEBUG
940void
941dumpssw(u_short ssw)
942{
943	printf(" SSW: %x: ", ssw);
944	if (ssw & SSW4_CP)
945		printf("CP,");
946	if (ssw & SSW4_CU)
947		printf("CU,");
948	if (ssw & SSW4_CT)
949		printf("CT,");
950	if (ssw & SSW4_CM)
951		printf("CM,");
952	if (ssw & SSW4_MA)
953		printf("MA,");
954	if (ssw & SSW4_ATC)
955		printf("ATC,");
956	if (ssw & SSW4_LK)
957		printf("LK,");
958	if (ssw & SSW4_RW)
959		printf("RW,");
960	printf(" SZ=%s, TT=%s, TM=%s\n",
961	       f7sz[(ssw & SSW4_SZMASK) >> 5],
962	       f7tt[(ssw & SSW4_TTMASK) >> 3],
963	       f7tm[ssw & SSW4_TMMASK]);
964}
965
966void
967dumpwb(int num, u_short s, u_int a, u_int d)
968{
969	struct proc *p = curproc;
970	paddr_t pa;
971
972	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
973	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
974	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
975	printf("               PA ");
976	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
977		printf("<invalid address>");
978	else
979		printf("%lx, current value %lx", pa, fuword((void *)a));
980	printf("\n");
981}
982#endif
983#endif
984