trap.c revision 1.82
1/*	$NetBSD: trap.c,v 1.82 2010/12/20 00:25:40 matt 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.82 2010/12/20 00:25:40 matt 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	curcpu()->ci_data.cpu_ntrap++;
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			curcpu()->ci_data.cpu_ntrap--;
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				if (ucas_ras_check(&fp->F_t)) {
642					return;
643				}
644#ifdef M68040
645				if (cputype == CPU_68040)
646					(void) writeback(fp, 1);
647#endif
648				return;
649			}
650			l->l_pflag &= ~LP_SA_PAGEFAULT;
651			goto out;
652		}
653		if (rv == EACCES) {
654			ksi.ksi_code = SEGV_ACCERR;
655			rv = EFAULT;
656		} else
657			ksi.ksi_code = SEGV_MAPERR;
658		if (type == T_MMUFLT) {
659			if (onfault)
660				goto copyfault;
661			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
662			    map, va, ftype, rv);
663			printf("  type %x, code [mmu,,ssw]: %x\n",
664			       type, code);
665			goto dopanic;
666		}
667		l->l_pflag &= ~LP_SA_PAGEFAULT;
668		ksi.ksi_addr = (void *)v;
669		if (rv == ENOMEM) {
670			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
671			       p->p_pid, p->p_comm,
672			       l->l_cred ?
673			       kauth_cred_geteuid(l->l_cred) : -1);
674			ksi.ksi_signo = SIGKILL;
675		} else {
676			ksi.ksi_signo = SIGSEGV;
677		}
678		break;
679	    }
680	}
681	trapsignal(l, &ksi);
682	if ((type & T_USER) == 0)
683		return;
684out:
685	userret(l, fp, sticks, v, 1);
686}
687
688#ifdef M68040
689#ifdef DEBUG
690struct writebackstats {
691	int calls;
692	int cpushes;
693	int move16s;
694	int wb1s, wb2s, wb3s;
695	int wbsize[4];
696} wbstats;
697
698const char *f7sz[] = { "longword", "byte", "word", "line" };
699const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
700const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
701		 "M-code", "k-data", "k-code", "RES" };
702const char wberrstr[] =
703    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
704#endif
705
706int
707writeback(struct frame *fp, int docachepush)
708{
709	struct fmt7 *f = &fp->f_fmt7;
710	struct lwp *l = curlwp;
711	struct proc *p = l->l_proc;
712	struct pcb *pcb = lwp_getpcb(l);
713	int err = 0;
714	u_int fa;
715	void *oonfault = pcb->pcb_onfault;
716	paddr_t pa;
717
718#ifdef DEBUG
719	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
720		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
721		dumpssw(f->f_ssw);
722	}
723	wbstats.calls++;
724#endif
725	/*
726	 * Deal with special cases first.
727	 */
728	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
729		/*
730		 * Dcache push fault.
731		 * Line-align the address and write out the push data to
732		 * the indicated physical address.
733		 */
734#ifdef DEBUG
735		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
736			printf(" pushing %s to PA %x, data %x",
737			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
738			       f->f_fa, f->f_pd0);
739			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
740				printf("/%x/%x/%x",
741				       f->f_pd1, f->f_pd2, f->f_pd3);
742			printf("\n");
743		}
744		if (f->f_wb1s & SSW4_WBSV)
745			panic("writeback: cache push with WB1S valid");
746		wbstats.cpushes++;
747#endif
748		/*
749		 * XXX there are security problems if we attempt to do a
750		 * cache push after a signal handler has been called.
751		 */
752		if (docachepush) {
753			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
754			    trunc_page(f->f_fa), VM_PROT_WRITE,
755			    VM_PROT_WRITE|PMAP_WIRED);
756			pmap_update(pmap_kernel());
757			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
758			memcpy((void *)fa, (void *)&f->f_pd0, 16);
759			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
760			DCFL(pa);
761			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
762				    (vaddr_t)&vmmap[PAGE_SIZE]);
763			pmap_update(pmap_kernel());
764		} else
765			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
766			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
767	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
768		/*
769		 * MOVE16 fault.
770		 * Line-align the address and write out the push data to
771		 * the indicated virtual address.
772		 */
773#ifdef DEBUG
774		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
775			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
776			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
777			       f->f_pd2, f->f_pd3);
778		if (f->f_wb1s & SSW4_WBSV)
779			panic("writeback: MOVE16 with WB1S valid");
780		wbstats.move16s++;
781#endif
782		if (KDFAULT(f->f_wb1s))
783			memcpy((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0, 16);
784		else
785			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
786		if (err) {
787			fa = f->f_fa & ~0xF;
788#ifdef DEBUG
789			if (mmudebug & MDB_WBFAILED)
790				printf(wberrstr, p->p_pid, p->p_comm,
791				       "MOVE16", fp->f_pc, f->f_fa,
792				       f->f_fa & ~0xF, f->f_pd0);
793#endif
794		}
795	} else if (f->f_wb1s & SSW4_WBSV) {
796		/*
797		 * Writeback #1.
798		 * Position the "memory-aligned" data and write it out.
799		 */
800		u_int wb1d = f->f_wb1d;
801		int off;
802
803#ifdef DEBUG
804		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
805			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
806		wbstats.wb1s++;
807		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
808#endif
809		off = (f->f_wb1a & 3) * 8;
810		switch (f->f_wb1s & SSW4_SZMASK) {
811		case SSW4_SZLW:
812			if (off)
813				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
814			if (KDFAULT(f->f_wb1s))
815				*(long *)f->f_wb1a = wb1d;
816			else
817				err = suword((void *)f->f_wb1a, wb1d);
818			break;
819		case SSW4_SZB:
820			off = 24 - off;
821			if (off)
822				wb1d >>= off;
823			if (KDFAULT(f->f_wb1s))
824				*(char *)f->f_wb1a = wb1d;
825			else
826				err = subyte((void *)f->f_wb1a, wb1d);
827			break;
828		case SSW4_SZW:
829			off = (off + 16) % 32;
830			if (off)
831				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
832			if (KDFAULT(f->f_wb1s))
833				*(short *)f->f_wb1a = wb1d;
834			else
835				err = susword((void *)f->f_wb1a, wb1d);
836			break;
837		}
838		if (err) {
839			fa = f->f_wb1a;
840#ifdef DEBUG
841			if (mmudebug & MDB_WBFAILED)
842				printf(wberrstr, p->p_pid, p->p_comm,
843				       "#1", fp->f_pc, f->f_fa,
844				       f->f_wb1a, f->f_wb1d);
845#endif
846		}
847	}
848	/*
849	 * Deal with the "normal" writebacks.
850	 *
851	 * XXX writeback2 is known to reflect a LINE size writeback after
852	 * a MOVE16 was already dealt with above.  Ignore it.
853	 */
854	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
855	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
856#ifdef DEBUG
857		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
858			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
859		wbstats.wb2s++;
860		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
861#endif
862		switch (f->f_wb2s & SSW4_SZMASK) {
863		case SSW4_SZLW:
864			if (KDFAULT(f->f_wb2s))
865				*(long *)f->f_wb2a = f->f_wb2d;
866			else
867				err = suword((void *)f->f_wb2a, f->f_wb2d);
868			break;
869		case SSW4_SZB:
870			if (KDFAULT(f->f_wb2s))
871				*(char *)f->f_wb2a = f->f_wb2d;
872			else
873				err = subyte((void *)f->f_wb2a, f->f_wb2d);
874			break;
875		case SSW4_SZW:
876			if (KDFAULT(f->f_wb2s))
877				*(short *)f->f_wb2a = f->f_wb2d;
878			else
879				err = susword((void *)f->f_wb2a, f->f_wb2d);
880			break;
881		}
882		if (err) {
883			fa = f->f_wb2a;
884#ifdef DEBUG
885			if (mmudebug & MDB_WBFAILED) {
886				printf(wberrstr, p->p_pid, p->p_comm,
887				       "#2", fp->f_pc, f->f_fa,
888				       f->f_wb2a, f->f_wb2d);
889				dumpssw(f->f_ssw);
890				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
891			}
892#endif
893		}
894	}
895	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
896#ifdef DEBUG
897		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
898			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
899		wbstats.wb3s++;
900		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
901#endif
902		switch (f->f_wb3s & SSW4_SZMASK) {
903		case SSW4_SZLW:
904			if (KDFAULT(f->f_wb3s))
905				*(long *)f->f_wb3a = f->f_wb3d;
906			else
907				err = suword((void *)f->f_wb3a, f->f_wb3d);
908			break;
909		case SSW4_SZB:
910			if (KDFAULT(f->f_wb3s))
911				*(char *)f->f_wb3a = f->f_wb3d;
912			else
913				err = subyte((void *)f->f_wb3a, f->f_wb3d);
914			break;
915		case SSW4_SZW:
916			if (KDFAULT(f->f_wb3s))
917				*(short *)f->f_wb3a = f->f_wb3d;
918			else
919				err = susword((void *)f->f_wb3a, f->f_wb3d);
920			break;
921#ifdef DEBUG
922		case SSW4_SZLN:
923			panic("writeback: wb3s indicates LINE write");
924#endif
925		}
926		if (err) {
927			fa = f->f_wb3a;
928#ifdef DEBUG
929			if (mmudebug & MDB_WBFAILED)
930				printf(wberrstr, p->p_pid, p->p_comm,
931				       "#3", fp->f_pc, f->f_fa,
932				       f->f_wb3a, f->f_wb3d);
933#endif
934		}
935	}
936	pcb->pcb_onfault = oonfault;
937	if (err)
938		err = SIGSEGV;
939	return (err);
940}
941
942#ifdef DEBUG
943void
944dumpssw(u_short ssw)
945{
946	printf(" SSW: %x: ", ssw);
947	if (ssw & SSW4_CP)
948		printf("CP,");
949	if (ssw & SSW4_CU)
950		printf("CU,");
951	if (ssw & SSW4_CT)
952		printf("CT,");
953	if (ssw & SSW4_CM)
954		printf("CM,");
955	if (ssw & SSW4_MA)
956		printf("MA,");
957	if (ssw & SSW4_ATC)
958		printf("ATC,");
959	if (ssw & SSW4_LK)
960		printf("LK,");
961	if (ssw & SSW4_RW)
962		printf("RW,");
963	printf(" SZ=%s, TT=%s, TM=%s\n",
964	       f7sz[(ssw & SSW4_SZMASK) >> 5],
965	       f7tt[(ssw & SSW4_TTMASK) >> 3],
966	       f7tm[ssw & SSW4_TMMASK]);
967}
968
969void
970dumpwb(int num, u_short s, u_int a, u_int d)
971{
972	struct proc *p = curproc;
973	paddr_t pa;
974
975	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
976	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
977	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
978	printf("               PA ");
979	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
980		printf("<invalid address>");
981	else
982		printf("%lx, current value %lx", pa, fuword((void *)a));
983	printf("\n");
984}
985#endif
986#endif
987