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