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