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