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