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