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