xref: /netbsd/sys/arch/x68k/x68k/trap.c (revision c4a72b64)
1 /*	$NetBSD: trap.c,v 1.59 2002/10/28 00:55:19 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_kgdb.h"
47 #include "opt_execfmt.h"
48 #include "opt_compat_sunos.h"
49 #include "opt_compat_hpux.h"
50 #include "opt_m680x0.h"
51 #include "opt_fpu_emulate.h"
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/proc.h>
56 #include <sys/acct.h>
57 #include <sys/kernel.h>
58 #include <sys/signalvar.h>
59 #include <sys/resourcevar.h>
60 #include <sys/syscall.h>
61 #include <sys/syslog.h>
62 #include <sys/user.h>
63 
64 #include <machine/psl.h>
65 #include <machine/trap.h>
66 #include <machine/cpu.h>
67 #include <machine/reg.h>
68 #include <machine/db_machdep.h>
69 #include <m68k/cacheops.h>
70 
71 #include <uvm/uvm_extern.h>
72 
73 #include <dev/cons.h>
74 
75 #ifdef FPU_EMULATE
76 #include <m68k/fpe/fpu_emulate.h>
77 #endif
78 
79 #ifdef COMPAT_HPUX
80 #include <compat/hpux/hpux.h>
81 extern struct emul emul_hpux;
82 #endif
83 
84 #ifdef COMPAT_SUNOS
85 #include <compat/sunos/sunos_exec.h>
86 #include <compat/sunos/sunos_syscall.h>
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 #if defined(M68040) || defined(M68060)
93 #ifdef DEBUG
94 static void dumpssw __P((u_short));
95 static void dumpwb __P((int, u_short, u_int, u_int));
96 #endif
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 	/*
401 	 * FPU faults in supervisor mode.
402 	 */
403 	case T_ILLINST:	/* fnop generates this, apparently. */
404 	case T_FPEMULI:
405 	case T_FPEMULD: {
406 		extern label_t *nofault;
407 
408 		if (nofault)	/* If we're probing. */
409 			longjmp(nofault);
410 		if (type == T_ILLINST)
411 			printf("Kernel Illegal Instruction trap.\n");
412 		else
413 			printf("Kernel FPU trap.\n");
414 		goto dopanic;
415 	}
416 
417 	/*
418 	 * Unimplemented FPU instructions/datatypes.
419 	 */
420 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
421 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
422 #ifdef FPU_EMULATE
423 		i = fpu_emulate(&frame, &p->p_addr->u_pcb.pcb_fpregs);
424 		/* XXX -- deal with tracing? (frame.f_sr & PSL_T) */
425 		break;
426 #elif defined(M68040) || defined(M68060)
427 		/* XXX need to FSAVE */
428 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
429 		       p->p_pid, p->p_comm,
430 		       frame.f_format == 2 ? "instruction" : "data type",
431 		       frame.f_pc, frame.f_fmt2.f_iaddr);
432 		/* XXX need to FRESTORE */
433 		i = SIGFPE;
434 		break;
435 #endif
436 
437 	case T_ILLINST|T_USER:	/* illegal instruction fault */
438 #ifdef COMPAT_HPUX
439 		if (p->p_emul == &emul_hpux) {
440 			ucode = HPUX_ILL_ILLINST_TRAP;
441 			i = SIGILL;
442 			break;
443 		}
444 		/* fall through */
445 #endif
446 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
447 #ifdef COMPAT_HPUX
448 		if (p->p_emul == &emul_hpux)
449 			ucode = HPUX_ILL_PRIV_TRAP;
450 		else
451 #endif
452 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
453 		i = SIGILL;
454 		break;
455 
456 	case T_ZERODIV|T_USER:	/* Divide by zero */
457 #ifdef COMPAT_HPUX
458 		if (p->p_emul == &emul_hpux)
459 			ucode = HPUX_FPE_INTDIV_TRAP;
460 		else
461 #endif
462 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
463 		i = SIGFPE;
464 		break;
465 
466 	case T_CHKINST|T_USER:	/* CHK instruction trap */
467 #ifdef COMPAT_HPUX
468 		if (p->p_emul == &emul_hpux) {
469 			/* handled differently under hp-ux */
470 			i = SIGILL;
471 			ucode = HPUX_ILL_CHK_TRAP;
472 			break;
473 		}
474 #endif
475 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
476 		i = SIGFPE;
477 		break;
478 
479 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
480 #ifdef COMPAT_HPUX
481 		if (p->p_emul == &emul_hpux) {
482 			/* handled differently under hp-ux */
483 			i = SIGILL;
484 			ucode = HPUX_ILL_TRAPV_TRAP;
485 			break;
486 		}
487 #endif
488 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
489 		i = SIGFPE;
490 		break;
491 
492 	/*
493 	 * XXX: Trace traps are a nightmare.
494 	 *
495 	 *	HP-UX uses trap #1 for breakpoints,
496 	 *	NetBSD/m68k uses trap #2,
497 	 *	SUN 3.x uses trap #15,
498 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
499 	 *	handled elsewhere).
500 	 *
501 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
502 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
503 	 * supported yet.
504 	 *
505 	 * XXX: We should never get kernel-mode T_TRAP15
506 	 * XXX: because locore.s now gives them special treatment.
507 	 */
508 	case T_TRAP15:		/* kernel breakpoint */
509 #ifdef DEBUG
510 		printf("unexpected kernel trace trap, type = %d\n", type);
511 		printf("program counter = 0x%x\n", frame.f_pc);
512 #endif
513 		frame.f_sr &= ~PSL_T;
514 		return;
515 
516 	case T_TRACE|T_USER:	/* user trace trap */
517 #ifdef COMPAT_SUNOS
518 		/*
519 		 * SunOS uses Trap #2 for a "CPU cache flush".
520 		 * Just flush the on-chip caches and return.
521 		 */
522 		if (p->p_emul == &emul_sunos) {
523 			ICIA();
524 			DCIU();
525 			return;
526 		}
527 #endif
528 		/* FALLTHROUGH */
529 	case T_TRACE:		/* tracing a trap instruction */
530 	case T_TRAP15|T_USER:	/* SUN user trace trap */
531 		frame.f_sr &= ~PSL_T;
532 		i = SIGTRAP;
533 		break;
534 
535 	case T_ASTFLT:		/* system async trap, cannot happen */
536 		goto dopanic;
537 
538 	case T_ASTFLT|T_USER:	/* user async trap */
539 		astpending = 0;
540 		/*
541 		 * We check for software interrupts first.  This is because
542 		 * they are at a higher level than ASTs, and on a VAX would
543 		 * interrupt the AST.  We assume that if we are processing
544 		 * an AST that we must be at IPL0 so we don't bother to
545 		 * check.  Note that we ensure that we are at least at SIR
546 		 * IPL while processing the SIR.
547 		 */
548 		spl1();
549 		/* fall into... */
550 
551 	case T_SSIR:		/* software interrupt */
552 	case T_SSIR|T_USER:
553 		if (ssir & SIR_NET) {
554 			void netintr __P((void));
555 			siroff(SIR_NET);
556 			uvmexp.softs++;
557 			netintr();
558 		}
559 		if (ssir & SIR_CLOCK) {
560 			siroff(SIR_CLOCK);
561 			uvmexp.softs++;
562 			softclock(NULL);
563 		}
564 		if (ssir & SIR_SERIAL) {
565 #include "zsc.h"
566 #if NZSC > 0
567 			void zssoft __P((int));
568 #endif
569 			siroff(SIR_SERIAL);
570 			uvmexp.softs++;
571 #if NZSC > 0
572 			zssoft(0);
573 #endif
574 		}
575 		if (ssir & SIR_KBD) {
576 #include "kbd.h"
577 #if NKBD > 0
578 			void	kbdsoftint __P((void));
579 #endif
580 			siroff(SIR_KBD);
581 			uvmexp.softs++;
582 #if NKBD > 0
583 			kbdsoftint();
584 #endif
585 		}
586 		/*
587 		 * If this was not an AST trap, we are all done.
588 		 */
589 		if (type != (T_ASTFLT|T_USER)) {
590 			uvmexp.traps--;
591 			return;
592 		}
593 		spl0();
594 		if (p->p_flag & P_OWEUPC) {
595 			p->p_flag &= ~P_OWEUPC;
596 			ADDUPROF(p);
597 		}
598 		goto out;
599 
600 	case T_MMUFLT:		/* kernel mode page fault */
601 		/*
602 		 * If we were doing profiling ticks or other user mode
603 		 * stuff from interrupt code, Just Say No.
604 		 */
605 		if (p->p_addr->u_pcb.pcb_onfault == fubail ||
606 		    p->p_addr->u_pcb.pcb_onfault == subail)
607 			goto copyfault;
608 		/* fall into ... */
609 
610 	case T_MMUFLT|T_USER:	/* page fault */
611 	    {
612 		vaddr_t va;
613 		struct vmspace *vm = p->p_vmspace;
614 		struct vm_map *map;
615 		int rv;
616 		vm_prot_t ftype;
617 		extern struct vm_map *kernel_map;
618 
619 #ifdef DEBUG
620 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
621 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
622 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
623 #endif
624 		/*
625 		 * It is only a kernel address space fault iff:
626 		 * 	1. (type & T_USER) == 0  and
627 		 * 	2. pcb_onfault not set or
628 		 *	3. pcb_onfault set but supervisor space data fault
629 		 * The last can occur during an exec() copyin where the
630 		 * argument space is lazy-allocated.
631 		 */
632 		if ((type & T_USER) == 0 &&
633 		    ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
634 			map = kernel_map;
635 		else
636 			map = vm ? &vm->vm_map : kernel_map;
637 
638 		if (WRFAULT(code))
639 			ftype = VM_PROT_WRITE;
640 		else
641 			ftype = VM_PROT_READ;
642 
643 		va = trunc_page((vaddr_t)v);
644 
645 		if (map == kernel_map && va == 0) {
646 			printf("trap: bad kernel %s access at 0x%x\n",
647 			    (ftype & VM_PROT_WRITE) ? "read/write" :
648 			    "read", v);
649 			goto dopanic;
650 		}
651 
652 #ifdef COMPAT_HPUX
653 		if (ISHPMMADDR(va)) {
654 			int pmap_mapmulti __P((pmap_t, vaddr_t));
655 			vaddr_t bva;
656 
657 			rv = pmap_mapmulti(map->pmap, va);
658 			if (rv != 0) {
659 				bva = HPMMBASEADDR(va);
660 				rv = uvm_fault(map, bva, 0, ftype);
661 				if (rv == 0)
662 					(void) pmap_mapmulti(map->pmap, va);
663 			}
664 		} else
665 #endif
666 		rv = uvm_fault(map, va, 0, ftype);
667 #ifdef DEBUG
668 		if (rv && MDB_ISPID(p->p_pid))
669 			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
670 			    map, va, ftype, rv);
671 #endif
672 		/*
673 		 * If this was a stack access we keep track of the maximum
674 		 * accessed stack size.  Also, if vm_fault gets a protection
675 		 * failure it is due to accessing the stack region outside
676 		 * the current limit and we need to reflect that as an access
677 		 * error.
678 		 */
679 		if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
680 		    && map != kernel_map) {
681 			if (rv == 0) {
682 				unsigned nss;
683 
684 				nss = btoc(USRSTACK-(unsigned)va);
685 				if (nss > vm->vm_ssize)
686 					vm->vm_ssize = nss;
687 			} else if (rv == EACCES)
688 				rv = EFAULT;
689 		}
690 		if (rv == 0) {
691 			if (type == T_MMUFLT) {
692 #ifdef M68040
693 				if (cputype == CPU_68040)
694 					(void) writeback(&frame, 1);
695 #endif
696 				return;
697 			}
698 			goto out;
699 		}
700 		if (type == T_MMUFLT) {
701 			if (p->p_addr->u_pcb.pcb_onfault)
702 				goto copyfault;
703 			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
704 			    map, va, ftype, rv);
705 			printf("  type %x, code [mmu,,ssw]: %x\n",
706 			       type, code);
707 			goto dopanic;
708 		}
709 		ucode = v;
710 		if (rv == ENOMEM) {
711 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
712 			       p->p_pid, p->p_comm,
713 			       p->p_cred && p->p_ucred ?
714 			       p->p_ucred->cr_uid : -1);
715 			i = SIGKILL;
716 		} else {
717 			i = SIGSEGV;
718 		}
719 		break;
720 	    }
721 	}
722 	if (i)
723 		trapsignal(p, i, ucode);
724 	if ((type & T_USER) == 0)
725 		return;
726 out:
727 	userret(p, &frame, sticks, v, 1);
728 }
729 
730 #ifdef M68040
731 #ifdef DEBUG
732 struct writebackstats {
733 	int calls;
734 	int cpushes;
735 	int move16s;
736 	int wb1s, wb2s, wb3s;
737 	int wbsize[4];
738 } wbstats;
739 
740 char *f7sz[] = { "longword", "byte", "word", "line" };
741 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
742 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
743 		 "M-code", "k-data", "k-code", "RES" };
744 char wberrstr[] =
745     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
746 #endif
747 
748 int
749 writeback(fp, docachepush)
750 	struct frame *fp;
751 	int docachepush;
752 {
753 	struct fmt7 *f = &fp->f_fmt7;
754 	struct proc *p = curproc;
755 	int err = 0;
756 	u_int fa;
757 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
758 	paddr_t pa;
759 
760 #ifdef DEBUG
761 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
762 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
763 		dumpssw(f->f_ssw);
764 	}
765 	wbstats.calls++;
766 #endif
767 	/*
768 	 * Deal with special cases first.
769 	 */
770 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
771 		/*
772 		 * Dcache push fault.
773 		 * Line-align the address and write out the push data to
774 		 * the indicated physical address.
775 		 */
776 #ifdef DEBUG
777 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
778 			printf(" pushing %s to PA %x, data %x",
779 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
780 			       f->f_fa, f->f_pd0);
781 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
782 				printf("/%x/%x/%x",
783 				       f->f_pd1, f->f_pd2, f->f_pd3);
784 			printf("\n");
785 		}
786 		if (f->f_wb1s & SSW4_WBSV)
787 			panic("writeback: cache push with WB1S valid");
788 		wbstats.cpushes++;
789 #endif
790 		/*
791 		 * XXX there are security problems if we attempt to do a
792 		 * cache push after a signal handler has been called.
793 		 */
794 		if (docachepush) {
795 			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
796 			    trunc_page(f->f_fa), VM_PROT_WRITE,
797 			    VM_PROT_WRITE|PMAP_WIRED);
798 			pmap_update(pmap_kernel());
799 			fa = (u_int)&vmmap[m68k_page_offset(f->f_fa) & ~0xF];
800 			memcpy((caddr_t)fa, (caddr_t)&f->f_pd0, 16);
801 			(void) pmap_extract(pmap_kernel(), (paddr_t)fa, &pa);
802 			DCFL(pa);
803 			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
804 				    (vaddr_t)&vmmap[NBPG]);
805 			pmap_update(pmap_kernel());
806 		} else
807 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
808 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
809 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
810 		/*
811 		 * MOVE16 fault.
812 		 * Line-align the address and write out the push data to
813 		 * the indicated virtual address.
814 		 */
815 #ifdef DEBUG
816 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
817 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
818 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
819 			       f->f_pd2, f->f_pd3);
820 		if (f->f_wb1s & SSW4_WBSV)
821 			panic("writeback: MOVE16 with WB1S valid");
822 		wbstats.move16s++;
823 #endif
824 		if (KDFAULT(f->f_wb1s))
825 			memcpy((caddr_t)(f->f_fa & ~0xF),
826 			    (caddr_t)&f->f_pd0, 16);
827 		else
828 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
829 		if (err) {
830 			fa = f->f_fa & ~0xF;
831 #ifdef DEBUG
832 			if (mmudebug & MDB_WBFAILED)
833 				printf(wberrstr, p->p_pid, p->p_comm,
834 				       "MOVE16", fp->f_pc, f->f_fa,
835 				       f->f_fa & ~0xF, f->f_pd0);
836 #endif
837 		}
838 	} else if (f->f_wb1s & SSW4_WBSV) {
839 		/*
840 		 * Writeback #1.
841 		 * Position the "memory-aligned" data and write it out.
842 		 */
843 		u_int wb1d = f->f_wb1d;
844 		int off;
845 
846 #ifdef DEBUG
847 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
848 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
849 		wbstats.wb1s++;
850 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
851 #endif
852 		off = (f->f_wb1a & 3) * 8;
853 		switch (f->f_wb1s & SSW4_SZMASK) {
854 		case SSW4_SZLW:
855 			if (off)
856 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
857 			if (KDFAULT(f->f_wb1s))
858 				*(long *)f->f_wb1a = wb1d;
859 			else
860 				err = suword((caddr_t)f->f_wb1a, wb1d);
861 			break;
862 		case SSW4_SZB:
863 			off = 24 - off;
864 			if (off)
865 				wb1d >>= off;
866 			if (KDFAULT(f->f_wb1s))
867 				*(char *)f->f_wb1a = wb1d;
868 			else
869 				err = subyte((caddr_t)f->f_wb1a, wb1d);
870 			break;
871 		case SSW4_SZW:
872 			off = (off + 16) % 32;
873 			if (off)
874 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
875 			if (KDFAULT(f->f_wb1s))
876 				*(short *)f->f_wb1a = wb1d;
877 			else
878 				err = susword((caddr_t)f->f_wb1a, wb1d);
879 			break;
880 		}
881 		if (err) {
882 			fa = f->f_wb1a;
883 #ifdef DEBUG
884 			if (mmudebug & MDB_WBFAILED)
885 				printf(wberrstr, p->p_pid, p->p_comm,
886 				       "#1", fp->f_pc, f->f_fa,
887 				       f->f_wb1a, f->f_wb1d);
888 #endif
889 		}
890 	}
891 	/*
892 	 * Deal with the "normal" writebacks.
893 	 *
894 	 * XXX writeback2 is known to reflect a LINE size writeback after
895 	 * a MOVE16 was already dealt with above.  Ignore it.
896 	 */
897 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
898 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
899 #ifdef DEBUG
900 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
901 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
902 		wbstats.wb2s++;
903 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
904 #endif
905 		switch (f->f_wb2s & SSW4_SZMASK) {
906 		case SSW4_SZLW:
907 			if (KDFAULT(f->f_wb2s))
908 				*(long *)f->f_wb2a = f->f_wb2d;
909 			else
910 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
911 			break;
912 		case SSW4_SZB:
913 			if (KDFAULT(f->f_wb2s))
914 				*(char *)f->f_wb2a = f->f_wb2d;
915 			else
916 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
917 			break;
918 		case SSW4_SZW:
919 			if (KDFAULT(f->f_wb2s))
920 				*(short *)f->f_wb2a = f->f_wb2d;
921 			else
922 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
923 			break;
924 		}
925 		if (err) {
926 			fa = f->f_wb2a;
927 #ifdef DEBUG
928 			if (mmudebug & MDB_WBFAILED) {
929 				printf(wberrstr, p->p_pid, p->p_comm,
930 				       "#2", fp->f_pc, f->f_fa,
931 				       f->f_wb2a, f->f_wb2d);
932 				dumpssw(f->f_ssw);
933 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
934 			}
935 #endif
936 		}
937 	}
938 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
939 #ifdef DEBUG
940 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
941 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
942 		wbstats.wb3s++;
943 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
944 #endif
945 		switch (f->f_wb3s & SSW4_SZMASK) {
946 		case SSW4_SZLW:
947 			if (KDFAULT(f->f_wb3s))
948 				*(long *)f->f_wb3a = f->f_wb3d;
949 			else
950 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
951 			break;
952 		case SSW4_SZB:
953 			if (KDFAULT(f->f_wb3s))
954 				*(char *)f->f_wb3a = f->f_wb3d;
955 			else
956 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
957 			break;
958 		case SSW4_SZW:
959 			if (KDFAULT(f->f_wb3s))
960 				*(short *)f->f_wb3a = f->f_wb3d;
961 			else
962 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
963 			break;
964 #ifdef DEBUG
965 		case SSW4_SZLN:
966 			panic("writeback: wb3s indicates LINE write");
967 #endif
968 		}
969 		if (err) {
970 			fa = f->f_wb3a;
971 #ifdef DEBUG
972 			if (mmudebug & MDB_WBFAILED)
973 				printf(wberrstr, p->p_pid, p->p_comm,
974 				       "#3", fp->f_pc, f->f_fa,
975 				       f->f_wb3a, f->f_wb3d);
976 #endif
977 		}
978 	}
979 	p->p_addr->u_pcb.pcb_onfault = oonfault;
980 	if (err)
981 		err = SIGSEGV;
982 	return (err);
983 }
984 
985 #ifdef DEBUG
986 static void
987 dumpssw(ssw)
988 	u_short ssw;
989 {
990 	printf(" SSW: %x: ", ssw);
991 	if (ssw & SSW4_CP)
992 		printf("CP,");
993 	if (ssw & SSW4_CU)
994 		printf("CU,");
995 	if (ssw & SSW4_CT)
996 		printf("CT,");
997 	if (ssw & SSW4_CM)
998 		printf("CM,");
999 	if (ssw & SSW4_MA)
1000 		printf("MA,");
1001 	if (ssw & SSW4_ATC)
1002 		printf("ATC,");
1003 	if (ssw & SSW4_LK)
1004 		printf("LK,");
1005 	if (ssw & SSW4_RW)
1006 		printf("RW,");
1007 	printf(" SZ=%s, TT=%s, TM=%s\n",
1008 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
1009 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
1010 	       f7tm[ssw & SSW4_TMMASK]);
1011 }
1012 
1013 static void
1014 dumpwb(num, s, a, d)
1015 	int num;
1016 	u_short s;
1017 	u_int a, d;
1018 {
1019 	struct proc *p = curproc;
1020 	paddr_t pa;
1021 
1022 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
1023 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
1024 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
1025 	printf("               PA ");
1026 	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
1027 		printf("<invalid address>");
1028 	else
1029 		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
1030 	printf("\n");
1031 }
1032 #endif
1033 #endif
1034