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