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