trap.c revision 1.74
1/*	$NetBSD: trap.c,v 1.74 2008/10/15 06:51:18 wrstuden 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.74 2008/10/15 06:51:18 wrstuden 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.  Note that there is a possibility that the
429	 * bit pattern of this register will conflict with one of the
430	 * FPE_* codes defined in signal.h.  Fortunately for us, the
431	 * only such codes we use are all in the range 1-7 and the low
432	 * 3 bits of the status register are defined as 0 so there is
433	 * no clash.
434	 */
435		ksi.ksi_signo = SIGFPE;
436		ksi.ksi_addr = (void *)code;
437		break;
438
439#ifdef M68040
440	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
441	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
442		/* XXX need to FSAVE */
443		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
444		       p->p_pid, p->p_comm,
445		       fp->f_format == 2 ? "instruction" : "data type",
446		       fp->f_pc, fp->f_fmt2.f_iaddr);
447		/* XXX need to FRESTORE */
448		ksi.ksi_signo = SIGFPE;
449		ksi.ksi_code = FPE_FLTINV;
450		break;
451#endif
452
453	case T_ILLINST|T_USER:	/* illegal instruction fault */
454	case T_PRIVINST|T_USER:	/* privileged instruction fault */
455		ksi.ksi_addr = (void *)(int)fp->f_format;
456				/* XXX was ILL_PRIVIN_FAULT */
457		ksi.ksi_signo = SIGILL;
458		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
459			ILL_PRVOPC : ILL_ILLOPC;
460		break;
461
462	case T_ZERODIV|T_USER:	/* Divide by zero */
463		ksi.ksi_addr = (void *)(int)fp->f_format;
464				/* XXX was FPE_INTDIV_TRAP */
465		ksi.ksi_signo = SIGFPE;
466		ksi.ksi_code = FPE_FLTDIV;
467		break;
468
469	case T_CHKINST|T_USER:	/* CHK instruction trap */
470		ksi.ksi_addr = (void *)(int)fp->f_format;
471				/* XXX was FPE_SUBRNG_TRAP */
472		ksi.ksi_signo = SIGFPE;
473		break;
474
475	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
476		ksi.ksi_addr = (void *)(int)fp->f_format;
477				/* XXX was FPE_INTOVF_TRAP */
478		ksi.ksi_signo = SIGFPE;
479		break;
480
481	/*
482	 * XXX: Trace traps are a nightmare.
483	 *
484	 *	HP-UX uses trap #1 for breakpoints,
485	 *	NetBSD/m68k uses trap #2,
486	 *	SUN 3.x uses trap #15,
487	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
488	 *	handled elsewhere).
489	 *
490	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
491	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
492	 * supported yet.
493	 *
494	 * XXX: We should never get kernel-mode T_TRAP15
495	 * XXX: because locore.s now gives them special treatment.
496	 */
497	case T_TRAP15:		/* kernel breakpoint */
498#ifdef DEBUG
499		printf("unexpected kernel trace trap, type = %d\n", type);
500		printf("program counter = 0x%x\n", fp->f_pc);
501#endif
502		fp->f_sr &= ~PSL_T;
503		return;
504
505	case T_TRACE|T_USER:	/* user trace trap */
506#ifdef COMPAT_SUNOS
507		/*
508		 * SunOS uses Trap #2 for a "CPU cache flush".
509		 * Just flush the on-chip caches and return.
510		 */
511		if (p->p_emul == &emul_sunos) {
512			ICIA();
513			DCIU();
514			return;
515		}
516#endif
517		/* FALLTHROUGH */
518	case T_TRACE:		/* tracing a trap instruction */
519	case T_TRAP15|T_USER:	/* SUN user trace trap */
520		fp->f_sr &= ~PSL_T;
521		ksi.ksi_signo = SIGTRAP;
522		break;
523
524	case T_ASTFLT:		/* system async trap, cannot happen */
525		goto dopanic;
526
527	case T_ASTFLT|T_USER:	/* user async trap */
528		astpending = 0;
529		/*
530		 * We check for software interrupts first.  This is because
531		 * they are at a higher level than ASTs, and on a VAX would
532		 * interrupt the AST.  We assume that if we are processing
533		 * an AST that we must be at IPL0 so we don't bother to
534		 * check.  Note that we ensure that we are at least at SIR
535		 * IPL while processing the SIR.
536		 */
537		spl1();
538		/* fall into... */
539
540	case T_SSIR:		/* software interrupt */
541	case T_SSIR|T_USER:
542		/*
543		 * If this was not an AST trap, we are all done.
544		 */
545		if (type != (T_ASTFLT|T_USER)) {
546			uvmexp.traps--;
547			return;
548		}
549		spl0();
550		if (l->l_pflag & LP_OWEUPC) {
551			l->l_pflag &= ~LP_OWEUPC;
552			ADDUPROF(l);
553		}
554		if (curcpu()->ci_want_resched)
555			preempt();
556		goto out;
557
558	case T_MMUFLT:		/* kernel mode page fault */
559		/*
560		 * If we were doing profiling ticks or other user mode
561		 * stuff from interrupt code, Just Say No.
562		 */
563		if (l->l_addr->u_pcb.pcb_onfault == fubail ||
564		    l->l_addr->u_pcb.pcb_onfault == subail)
565			goto copyfault;
566		/* fall into ... */
567
568	case T_MMUFLT|T_USER:	/* page fault */
569	    {
570		vaddr_t va;
571		struct vmspace *vm = p->p_vmspace;
572		struct vm_map *map;
573		int rv;
574		vm_prot_t ftype;
575		extern struct vm_map *kernel_map;
576
577#ifdef DEBUG
578		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
579		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
580		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
581#endif
582		/*
583		 * It is only a kernel address space fault iff:
584		 * 	1. (type & T_USER) == 0  and
585		 * 	2. pcb_onfault not set or
586		 *	3. pcb_onfault set but supervisor space data fault
587		 * The last can occur during an exec() copyin where the
588		 * argument space is lazy-allocated.
589		 */
590		if ((type & T_USER) == 0 &&
591		    ((l->l_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
592			map = kernel_map;
593		else {
594			map = vm ? &vm->vm_map : kernel_map;
595			if ((l->l_flag & LW_SA)
596			    && (~l->l_pflag & LP_SA_NOBLOCK)) {
597				l->l_savp->savp_faultaddr = (vaddr_t)v;
598				l->l_pflag |= LP_SA_PAGEFAULT;
599			}
600		}
601
602		if (WRFAULT(code))
603			ftype = VM_PROT_WRITE;
604		else
605			ftype = VM_PROT_READ;
606
607		va = trunc_page((vaddr_t)v);
608
609		if (map == kernel_map && va == 0) {
610			printf("trap: bad kernel %s access at 0x%x\n",
611			    (ftype & VM_PROT_WRITE) ? "read/write" :
612			    "read", v);
613			goto dopanic;
614		}
615
616#ifdef DIAGNOSTIC
617		if (interrupt_depth && !panicking) {
618			printf("trap: calling uvm_fault() from interrupt!\n");
619			goto dopanic;
620		}
621#endif
622
623		rv = uvm_fault(map, va, ftype);
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 (l->l_addr->u_pcb.pcb_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	int err = 0;
710	u_int fa;
711	void *oonfault = l->l_addr->u_pcb.pcb_onfault;
712	paddr_t pa;
713
714#ifdef DEBUG
715	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
716		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
717		dumpssw(f->f_ssw);
718	}
719	wbstats.calls++;
720#endif
721	/*
722	 * Deal with special cases first.
723	 */
724	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
725		/*
726		 * Dcache push fault.
727		 * Line-align the address and write out the push data to
728		 * the indicated physical address.
729		 */
730#ifdef DEBUG
731		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
732			printf(" pushing %s to PA %x, data %x",
733			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
734			       f->f_fa, f->f_pd0);
735			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
736				printf("/%x/%x/%x",
737				       f->f_pd1, f->f_pd2, f->f_pd3);
738			printf("\n");
739		}
740		if (f->f_wb1s & SSW4_WBSV)
741			panic("writeback: cache push with WB1S valid");
742		wbstats.cpushes++;
743#endif
744		/*
745		 * XXX there are security problems if we attempt to do a
746		 * cache push after a signal handler has been called.
747		 */
748		if (docachepush) {
749			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
750			    trunc_page(f->f_fa), VM_PROT_WRITE,
751			    VM_PROT_WRITE|PMAP_WIRED);
752			pmap_update(pmap_kernel());
753			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
754			bcopy((void *)&f->f_pd0, (void *)fa, 16);
755			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
756			DCFL(pa);
757			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
758				    (vaddr_t)&vmmap[PAGE_SIZE]);
759			pmap_update(pmap_kernel());
760		} else
761			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
762			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
763	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
764		/*
765		 * MOVE16 fault.
766		 * Line-align the address and write out the push data to
767		 * the indicated virtual address.
768		 */
769#ifdef DEBUG
770		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
771			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
772			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
773			       f->f_pd2, f->f_pd3);
774		if (f->f_wb1s & SSW4_WBSV)
775			panic("writeback: MOVE16 with WB1S valid");
776		wbstats.move16s++;
777#endif
778		if (KDFAULT(f->f_wb1s))
779			bcopy((void *)&f->f_pd0, (void *)(f->f_fa & ~0xF), 16);
780		else
781			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
782		if (err) {
783			fa = f->f_fa & ~0xF;
784#ifdef DEBUG
785			if (mmudebug & MDB_WBFAILED)
786				printf(wberrstr, p->p_pid, p->p_comm,
787				       "MOVE16", fp->f_pc, f->f_fa,
788				       f->f_fa & ~0xF, f->f_pd0);
789#endif
790		}
791	} else if (f->f_wb1s & SSW4_WBSV) {
792		/*
793		 * Writeback #1.
794		 * Position the "memory-aligned" data and write it out.
795		 */
796		u_int wb1d = f->f_wb1d;
797		int off;
798
799#ifdef DEBUG
800		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
801			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
802		wbstats.wb1s++;
803		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
804#endif
805		off = (f->f_wb1a & 3) * 8;
806		switch (f->f_wb1s & SSW4_SZMASK) {
807		case SSW4_SZLW:
808			if (off)
809				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
810			if (KDFAULT(f->f_wb1s))
811				*(long *)f->f_wb1a = wb1d;
812			else
813				err = suword((void *)f->f_wb1a, wb1d);
814			break;
815		case SSW4_SZB:
816			off = 24 - off;
817			if (off)
818				wb1d >>= off;
819			if (KDFAULT(f->f_wb1s))
820				*(char *)f->f_wb1a = wb1d;
821			else
822				err = subyte((void *)f->f_wb1a, wb1d);
823			break;
824		case SSW4_SZW:
825			off = (off + 16) % 32;
826			if (off)
827				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
828			if (KDFAULT(f->f_wb1s))
829				*(short *)f->f_wb1a = wb1d;
830			else
831				err = susword((void *)f->f_wb1a, wb1d);
832			break;
833		}
834		if (err) {
835			fa = f->f_wb1a;
836#ifdef DEBUG
837			if (mmudebug & MDB_WBFAILED)
838				printf(wberrstr, p->p_pid, p->p_comm,
839				       "#1", fp->f_pc, f->f_fa,
840				       f->f_wb1a, f->f_wb1d);
841#endif
842		}
843	}
844	/*
845	 * Deal with the "normal" writebacks.
846	 *
847	 * XXX writeback2 is known to reflect a LINE size writeback after
848	 * a MOVE16 was already dealt with above.  Ignore it.
849	 */
850	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
851	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
852#ifdef DEBUG
853		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
854			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
855		wbstats.wb2s++;
856		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
857#endif
858		switch (f->f_wb2s & SSW4_SZMASK) {
859		case SSW4_SZLW:
860			if (KDFAULT(f->f_wb2s))
861				*(long *)f->f_wb2a = f->f_wb2d;
862			else
863				err = suword((void *)f->f_wb2a, f->f_wb2d);
864			break;
865		case SSW4_SZB:
866			if (KDFAULT(f->f_wb2s))
867				*(char *)f->f_wb2a = f->f_wb2d;
868			else
869				err = subyte((void *)f->f_wb2a, f->f_wb2d);
870			break;
871		case SSW4_SZW:
872			if (KDFAULT(f->f_wb2s))
873				*(short *)f->f_wb2a = f->f_wb2d;
874			else
875				err = susword((void *)f->f_wb2a, f->f_wb2d);
876			break;
877		}
878		if (err) {
879			fa = f->f_wb2a;
880#ifdef DEBUG
881			if (mmudebug & MDB_WBFAILED) {
882				printf(wberrstr, p->p_pid, p->p_comm,
883				       "#2", fp->f_pc, f->f_fa,
884				       f->f_wb2a, f->f_wb2d);
885				dumpssw(f->f_ssw);
886				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
887			}
888#endif
889		}
890	}
891	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
892#ifdef DEBUG
893		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
894			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
895		wbstats.wb3s++;
896		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
897#endif
898		switch (f->f_wb3s & SSW4_SZMASK) {
899		case SSW4_SZLW:
900			if (KDFAULT(f->f_wb3s))
901				*(long *)f->f_wb3a = f->f_wb3d;
902			else
903				err = suword((void *)f->f_wb3a, f->f_wb3d);
904			break;
905		case SSW4_SZB:
906			if (KDFAULT(f->f_wb3s))
907				*(char *)f->f_wb3a = f->f_wb3d;
908			else
909				err = subyte((void *)f->f_wb3a, f->f_wb3d);
910			break;
911		case SSW4_SZW:
912			if (KDFAULT(f->f_wb3s))
913				*(short *)f->f_wb3a = f->f_wb3d;
914			else
915				err = susword((void *)f->f_wb3a, f->f_wb3d);
916			break;
917#ifdef DEBUG
918		case SSW4_SZLN:
919			panic("writeback: wb3s indicates LINE write");
920#endif
921		}
922		if (err) {
923			fa = f->f_wb3a;
924#ifdef DEBUG
925			if (mmudebug & MDB_WBFAILED)
926				printf(wberrstr, p->p_pid, p->p_comm,
927				       "#3", fp->f_pc, f->f_fa,
928				       f->f_wb3a, f->f_wb3d);
929#endif
930		}
931	}
932	l->l_addr->u_pcb.pcb_onfault = oonfault;
933	if (err)
934		err = SIGSEGV;
935	return (err);
936}
937
938#ifdef DEBUG
939void
940dumpssw(u_short ssw)
941{
942	printf(" SSW: %x: ", ssw);
943	if (ssw & SSW4_CP)
944		printf("CP,");
945	if (ssw & SSW4_CU)
946		printf("CU,");
947	if (ssw & SSW4_CT)
948		printf("CT,");
949	if (ssw & SSW4_CM)
950		printf("CM,");
951	if (ssw & SSW4_MA)
952		printf("MA,");
953	if (ssw & SSW4_ATC)
954		printf("ATC,");
955	if (ssw & SSW4_LK)
956		printf("LK,");
957	if (ssw & SSW4_RW)
958		printf("RW,");
959	printf(" SZ=%s, TT=%s, TM=%s\n",
960	       f7sz[(ssw & SSW4_SZMASK) >> 5],
961	       f7tt[(ssw & SSW4_TTMASK) >> 3],
962	       f7tm[ssw & SSW4_TMMASK]);
963}
964
965void
966dumpwb(int num, u_short s, u_int a, u_int d)
967{
968	struct proc *p = curproc;
969	paddr_t pa;
970
971	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
972	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
973	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
974	printf("               PA ");
975	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
976		printf("<invalid address>");
977	else
978		printf("%lx, current value %lx", pa, fuword((void *)a));
979	printf("\n");
980}
981#endif
982#endif
983