xref: /netbsd/sys/arch/atari/atari/trap.c (revision 6550d01e)
1 /*	$NetBSD: trap.c,v 1.110 2011/01/17 14:36:32 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * from: Utah $Hdr: trap.c 1.32 91/04/06$
36  *
37  *	@(#)trap.c	7.15 (Berkeley) 8/2/91
38  */
39 /*
40  * Copyright (c) 1988 University of Utah.
41  *
42  * This code is derived from software contributed to Berkeley by
43  * the Systems Programming Group of the University of Utah Computer
44  * Science Department.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *	This product includes software developed by the University of
57  *	California, Berkeley and its contributors.
58  * 4. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  * from: Utah $Hdr: trap.c 1.32 91/04/06$
75  *
76  *	@(#)trap.c	7.15 (Berkeley) 8/2/91
77  */
78 
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.110 2011/01/17 14:36:32 tsutsui Exp $");
81 
82 #include "opt_ddb.h"
83 #include "opt_execfmt.h"
84 #include "opt_kgdb.h"
85 #include "opt_compat_sunos.h"
86 #include "opt_fpu_emulate.h"
87 #include "opt_m68k_arch.h"
88 
89 #include <sys/param.h>
90 #include <sys/systm.h>
91 #include <sys/proc.h>
92 #include <sys/acct.h>
93 #include <sys/kernel.h>
94 #include <sys/signalvar.h>
95 #include <sys/resourcevar.h>
96 #include <sys/syslog.h>
97 #include <sys/syscall.h>
98 #include <sys/sa.h>
99 #include <sys/savar.h>
100 #include <sys/userret.h>
101 #include <sys/kauth.h>
102 
103 #include <uvm/uvm_extern.h>
104 
105 #include <m68k/cpu.h>
106 #include <m68k/cacheops.h>
107 
108 #include <machine/psl.h>
109 #include <machine/trap.h>
110 #include <machine/cpu.h>
111 #include <machine/pcb.h>
112 #include <machine/reg.h>
113 #include <machine/pte.h>
114 #ifdef DDB
115 #include <machine/db_machdep.h>
116 #endif
117 
118 #ifdef DEBUG
119 #include <dev/cons.h>  /* cngetc() */
120 #endif
121 
122 #ifdef FPU_EMULATE
123 #include <m68k/fpe/fpu_emulate.h>
124 #endif
125 
126 #ifdef COMPAT_SUNOS
127 #include <compat/sunos/sunos_syscall.h>
128 extern struct emul emul_sunos;
129 #endif
130 
131 void trap(struct frame *, int, u_int, u_int);
132 
133 static void panictrap(int, u_int, u_int, struct frame *);
134 static void trapcpfault(struct lwp *, struct frame *, int);
135 static void userret(struct lwp *, struct frame *fp, u_quad_t, u_int, int);
136 #ifdef M68040
137 static int  writeback(struct frame *, int);
138 #endif /* M68040 */
139 
140 const char *trap_type[] = {
141 	"Bus error",
142 	"Address error",
143 	"Illegal instruction",
144 	"Zero divide",
145 	"CHK instruction",
146 	"TRAPV instruction",
147 	"Privilege violation",
148 	"Trace trap",
149 	"MMU fault",
150 	"SSIR trap",
151 	"Format error",
152 	"68881 exception",
153 	"Coprocessor violation",
154 	"Async system trap"
155 };
156 int	trap_types = sizeof trap_type / sizeof trap_type[0];
157 
158 /*
159  * Size of various exception stack frames (minus the standard 8 bytes)
160  */
161 short	exframesize[] = {
162 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
163 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
164 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
165 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
166 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
167 	-1, -1,		/* type 5-6 - undefined */
168 	FMT7SIZE,	/* type 7 - access error (68040) */
169 	58,		/* type 8 - bus fault (68010) */
170 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
171 	FMTASIZE,	/* type A - short bus fault (68020/030) */
172 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
173 	-1, -1, -1, -1	/* type C-F - undefined */
174 };
175 
176 #ifdef M68060
177 #define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
178 #define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
179 #else
180 #define	KDFAULT_060(c)	0
181 #define	WRFAULT_060(c)	0
182 #endif
183 
184 #ifdef M68040
185 #define	KDFAULT_040(c)	(cputype == CPU_68040 && \
186 			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
187 #define	WRFAULT_040(c)	(cputype == CPU_68040 && \
188 			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
189 #else
190 #define	KDFAULT_040(c)	0
191 #define	WRFAULT_040(c)	0
192 #endif
193 
194 #if defined(M68030) || defined(M68020)
195 #define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
196 			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
197 #define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
198 			 (((c) & SSW_DF) != 0 && \
199 			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
200 #else
201 #define	KDFAULT_OTH(c)	0
202 #define	WRFAULT_OTH(c)	0
203 #endif
204 
205 #define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
206 #define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
207 
208 #ifdef DEBUG
209 int mmudebug = 0;
210 int mmupid   = -1;
211 #define MDB_FOLLOW	1
212 #define MDB_WBFOLLOW	2
213 #define MDB_WBFAILED	4
214 #define MDB_ISPID(pid)	((pid) == mmupid)
215 #endif
216 
217 extern struct pcb *curpcb;
218 
219 /*
220  * trap and syscall both need the following work done before returning
221  * to user mode.
222  */
223 static inline void
224 userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr, int fromtrap)
225 {
226 	struct proc *p = l->l_proc;
227 #ifdef M68040
228 	int sig;
229 	int beenhere = 0;
230 
231 again:
232 #endif
233 	/* Invoke MI userret code */
234 	mi_userret(l);
235 
236 	/*
237 	 * If profiling, charge system time to the trapped pc.
238 	 */
239 	if (p->p_stflag & PST_PROFIL) {
240 		extern int psratio;
241 
242 		addupc_task(l, fp->f_pc,
243 			    (int)(p->p_sticks - oticks) * psratio);
244 	}
245 #ifdef M68040
246 	/*
247 	 * Deal with user mode writebacks (from trap, or from sigreturn).
248 	 * If any writeback fails, go back and attempt signal delivery.
249 	 * unless we have already been here and attempted the writeback
250 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
251 	 * we just return to the user without successfully completing
252 	 * the writebacks.  Maybe we should just drop the sucker?
253 	 */
254 	if (cputype == CPU_68040 && fp->f_format == FMT7) {
255 		if (beenhere) {
256 #ifdef DEBUG
257 			if (mmudebug & MDB_WBFAILED)
258 				printf(fromtrap ?
259 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
260 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
261 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
262 #endif
263 		} else if ((sig = writeback(fp, fromtrap))) {
264 			ksiginfo_t ksi;
265 			beenhere = 1;
266 			oticks = p->p_sticks;
267 			(void)memset(&ksi, 0, sizeof(ksi));
268 			ksi.ksi_signo = sig;
269 			ksi.ksi_addr = (void *)faultaddr;
270 			ksi.ksi_code = BUS_OBJERR;
271 			trapsignal(l, &ksi);
272 			goto again;
273 		}
274 	}
275 #endif
276 }
277 
278 /*
279  * Used by the common m68k syscall() and child_return() functions.
280  * XXX: Temporary until all m68k ports share common trap()/userret() code.
281  */
282 void machine_userret(struct lwp *, struct frame *, u_quad_t);
283 
284 void
285 machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
286 {
287 
288 	userret(l, f, t, 0, 0);
289 }
290 
291 static void
292 panictrap(int type, u_int code, u_int v, struct frame *fp)
293 {
294 	int	s;
295 
296 	printf("trap type %d, code = %x, v = %x\n", type, code, v);
297 	printf("%s program counter = 0x%x\n",
298 			(type & T_USER) ? "user" : "kernel", fp->f_pc);
299 
300 	/*
301 	 * Let the kernel debugger see the trap frame that
302 	 * caused us to panic.  This is a convenience so
303 	 * one can see registers at the point of failure.
304 	 */
305 	s = splhigh();
306 #ifdef KGDB
307 	/* If connected, step or cont returns 1 */
308 	if (kgdb_trap(type, &fp))
309 		goto kgdb_cont;
310 #endif
311 #ifdef DDB
312 	(void)kdb_trap(type, (db_regs_t *)fp);
313 #endif
314 #ifdef KGDB
315 kgdb_cont:
316 #endif
317 	splx(s);
318 
319 	if (panicstr) {
320 		printf("Double panic\n");
321 #ifdef DEBUG
322 		/* XXX Should be a machine dependent hook */
323 		printf("(press a key)\n"); (void)cngetc();
324 #endif
325 	}
326 
327 	regdump((struct trapframe *)fp, 128);
328 	DCIS(); /* XXX? push cache */
329 
330 	type &= ~T_USER;
331 	if ((u_int)type < trap_types)
332 		panic(trap_type[type]);
333 	panic("trap");
334 	/*NOTREACHED*/
335 }
336 
337 /*
338  * return to fault handler
339  */
340 static void
341 trapcpfault(struct lwp *l, struct frame *fp, int error)
342 {
343 	struct pcb *pcb = lwp_getpcb(l);
344 
345 	/*
346 	 * We have arranged to catch this fault in one 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 	fp->f_stackadj = exframesize[fp->f_format];
352 	fp->f_format = fp->f_vector = 0;
353 	fp->f_pc = (int)pcb->pcb_onfault;
354 	fp->f_regs[D0] = error;
355 }
356 
357 /*
358  * Trap is called from locore to handle most types of processor traps,
359  * including events such as simulated software interrupts/AST's.
360  * System calls are broken out for efficiency.
361  */
362 /*ARGSUSED*/
363 void
364 trap(struct frame *fp, int type, u_int code, u_int v)
365 {
366 	struct lwp	*l;
367 	struct proc	*p;
368 	struct pcb	*pcb;
369 	ksiginfo_t ksi;
370 	u_quad_t	sticks;
371 	extern char	fubail[], subail[];
372 
373 	l = curlwp;
374 	sticks = 0;
375 
376 	curcpu()->ci_data.cpu_ntrap++;
377 
378 	KSI_INIT_TRAP(&ksi);
379 	ksi.ksi_trap = type & ~T_USER;
380 
381 	p = l->l_proc;
382 	pcb = lwp_getpcb(l);
383 	KASSERT(pcb != NULL);
384 
385 	if (USERMODE(fp->f_sr)) {
386 		type |= T_USER;
387 		sticks = p->p_sticks;
388 		l->l_md.md_regs = fp->f_regs;
389 		LWP_CACHE_CREDS(l, p);
390 	}
391 	switch (type) {
392 	default:
393 		panictrap(type, code, v, fp);
394 	/*
395 	 * Kernel Bus error
396 	 */
397 	case T_BUSERR:
398 		if (pcb->pcb_onfault == 0)
399 			panictrap(type, code, v, fp);
400 		trapcpfault(l, fp, EFAULT);
401 		return;
402 	/*
403 	 * User Bus/Addr error.
404 	 */
405 	case T_BUSERR|T_USER:
406 	case T_ADDRERR|T_USER:
407 		ksi.ksi_addr = (void *)v;
408 		ksi.ksi_signo = SIGBUS;
409 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
410 			BUS_OBJERR : BUS_ADRERR;
411 		break;
412 
413 	/*
414 	 * Kernel coprocessor violation
415 	 */
416 	case T_COPERR:
417 		/*FALLTHROUGH*/
418 	/*
419 	 * Kernel/User format error
420 	 */
421 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
422 	case T_FMTERR:
423 		/*
424 		 * The user has most likely trashed the RTE or FP state info
425 		 * in the stack frame of a signal handler.
426 		 */
427 		type |= T_USER;
428 #ifdef DEBUG
429 		printf("pid %d: kernel %s exception\n", p->p_pid,
430 		    type==T_COPERR ? "coprocessor" : "format");
431 #endif
432 		mutex_enter(p->p_lock);
433 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
434 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
435 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
436 		sigdelset(&l->l_sigmask, SIGILL);
437 		mutex_exit(p->p_lock);
438 
439 		ksi.ksi_signo = SIGILL;
440 		ksi.ksi_addr = (void *)(int)fp->f_format;
441 				/* XXX was ILL_RESAD_FAULT */
442 		ksi.ksi_code = (type == T_COPERR) ?
443 			ILL_COPROC : ILL_ILLOPC;
444 		break;
445 
446 	/*
447 	 * User coprocessor violation
448 	 */
449 	case T_COPERR|T_USER:
450 	/* XXX What is a proper response here? */
451 		ksi.ksi_signo = SIGFPE;
452 		ksi.ksi_code = FPE_FLTINV;
453 		break;
454 
455 	/*
456 	 * 6888x exceptions
457 	 */
458 	case T_FPERR|T_USER:
459 		/*
460 		 * We pass along the 68881 status register which locore
461 		 * stashed in code for us.
462 		 */
463 		ksi.ksi_signo = SIGFPE;
464 		ksi.ksi_code = fpsr2siginfocode(code);
465 		break;
466 
467 	/*
468 	 * Unimplemented FPU instructions/datatypes.
469 	 */
470 	case T_FPEMULI|T_USER:
471 	case T_FPEMULD|T_USER:
472 #ifdef FPU_EMULATE
473 		if (fpu_emulate(fp, &pcb->pcb_fpregs, &ksi) == 0)
474 			; /* XXX - Deal with tracing? (fp->f_sr & PSL_T) */
475 #else
476 		uprintf("pid %d killed: no floating point support.\n",
477 			p->p_pid);
478 		ksi.ksi_signo = SIGILL;
479 		ksi.ksi_code = ILL_ILLOPC;
480 #endif
481 		break;
482 
483 	/*
484 	 * FPU faults in supervisor mode.
485 	 */
486 	case T_FPEMULI:
487 	case T_FPEMULD: {
488 		extern int	*nofault;
489 
490 		if (nofault)	/* If we're probing. */
491 			longjmp((label_t *) nofault);
492 		panictrap(type, code, v, fp);
493 	}
494 
495 	/*
496 	 * User illegal/privileged inst fault
497 	 */
498 	case T_ILLINST|T_USER:
499 	case T_PRIVINST|T_USER:
500 		ksi.ksi_addr = (void *)(int)fp->f_format;
501 				/* XXX was ILL_PRIVIN_FAULT */
502 		ksi.ksi_signo = SIGILL;
503 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
504 			ILL_PRVOPC : ILL_ILLOPC;
505 		break;
506 
507 	/*
508 	 * divde by zero, CHK/TRAPV inst
509 	 */
510 	case T_ZERODIV|T_USER:
511 		ksi.ksi_code = FPE_FLTDIV;
512 	case T_CHKINST|T_USER:
513 	case T_TRAPVINST|T_USER:
514 		ksi.ksi_addr = (void *)(int)fp->f_format;
515 		ksi.ksi_signo = SIGFPE;
516 		break;
517 	/*
518 	 * XXX: Trace traps are a nightmare.
519 	 *
520 	 *	HP-UX uses trap #1 for breakpoints,
521 	 *	NetBSD/m68k uses trap #2,
522 	 *	SUN 3.x uses trap #15,
523 	 *	DDB and KGDB use trap #15 (for kernel breakpoints;
524 	 *	handled elsewhere).
525 	 *
526 	 * NetBSD and HP-UX traps get mapped by locore.s into T_TRACE.
527 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
528 	 * supported yet.
529 	 *
530 	 * XXX: We should never get kernel-mode T_TRAP15
531 	 * XXX: because locore.s now gives them special treatment.
532 	 */
533 	case T_TRAP15:
534 		fp->f_sr &= ~PSL_T;
535 		return;
536 
537 	case T_TRACE|T_USER:
538 #ifdef COMPAT_SUNOS
539 		/*
540 		 * SunOS uses Trap #2 for a "CPU cache flush".
541 		 * Just flush the on-chip caches and return.
542 		 */
543 		if (p->p_emul == &emul_sunos) {
544 			ICIA();
545 			DCIU();
546 			return;
547 		}
548 #endif
549 		/* FALLTHROUGH */
550 	case T_TRACE:		/* tracing a trap instruction */
551 	case T_TRAP15|T_USER:
552 		fp->f_sr &= ~PSL_T;
553 		ksi.ksi_signo = SIGTRAP;
554 		break;
555 	/*
556 	 * Kernel AST (should not happen)
557 	 */
558 	case T_ASTFLT:
559 		panictrap(type, code, v, fp);
560 	/*
561 	 * User AST
562 	 */
563 	case T_ASTFLT|T_USER:
564 		astpending = 0;
565 		/*
566 		 * We check for software interrupts first.  This is because
567 		 * they are at a higher level than ASTs, and on a VAX would
568 		 * interrupt the AST.  We assume that if we are processing
569 		 * an AST that we must be at IPL0 so we don't bother to
570 		 * check.  Note that we ensure that we are at least at SIR
571 		 * IPL while processing the SIR.
572 		 */
573 		spl1();
574 		/*FALLTHROUGH*/
575 	/*
576 	 * Software interrupt
577 	 */
578 	case T_SSIR:
579 	case T_SSIR|T_USER:
580 		/*
581 		 * If this was not an AST trap, we are all done.
582 		 */
583 		if (type != (T_ASTFLT|T_USER)) {
584 			curcpu()->ci_data.cpu_ntrap--;
585 			return;
586 		}
587 		spl0();
588 		if (l->l_pflag & LP_OWEUPC) {
589 			l->l_pflag &= ~LP_OWEUPC;
590 			ADDUPROF(l);
591 		}
592 		if (curcpu()->ci_want_resched)
593 			preempt();
594 		goto out;
595 	/*
596 	 * Kernel/User page fault
597 	 */
598 	case T_MMUFLT:
599 		/*
600 		 * If we were doing profiling ticks or other user mode
601 		 * stuff from interrupt code, Just Say No.
602 		 */
603 		if (pcb->pcb_onfault == (void *)fubail ||
604 		    pcb->pcb_onfault == (void *)subail) {
605 			trapcpfault(l, fp, EFAULT);
606 			return;
607 		}
608 		/*FALLTHROUGH*/
609 	case T_MMUFLT|T_USER:	/* page fault */
610 	    {
611 		vaddr_t	va;
612 		struct vmspace *vm = p->p_vmspace;
613 		struct vm_map *map;
614 		void *onfault;
615 		int rv;
616 		vm_prot_t ftype;
617 		extern struct vm_map *kernel_map;
618 
619 		onfault = pcb->pcb_onfault;
620 
621 #ifdef DEBUG
622 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
623 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
624 		       p ? p->p_pid : -1, code, v, fp->f_pc, fp->f_sr);
625 #endif
626 		/*
627 		 * It is only a kernel address space fault iff:
628 		 * 	1. (type & T_USER) == 0  and
629 		 * 	2. pcb_onfault not set or
630 		 *	3. pcb_onfault set but supervisor space data fault
631 		 * The last can occur during an exec() copyin where the
632 		 * argument space is lazy-allocated.
633 		 */
634 		if (type == T_MMUFLT && (onfault == 0 || KDFAULT(code)))
635 			map = kernel_map;
636 		else {
637 			map = vm ? &vm->vm_map : kernel_map;
638 			if ((l->l_flag & LW_SA)
639 			    && (~l->l_pflag & LP_SA_NOBLOCK)) {
640 				l->l_savp->savp_faultaddr = (vaddr_t)v;
641 				l->l_pflag |= LP_SA_PAGEFAULT;
642 			}
643 		}
644 
645 		if (WRFAULT(code))
646 			ftype = VM_PROT_WRITE;
647 		else
648 			ftype = VM_PROT_READ;
649 		va = trunc_page(v);
650 #ifdef DEBUG
651 		if (map == kernel_map && va == 0) {
652 			printf("trap: bad kernel access at %x\n", v);
653 			panictrap(type, code, v, fp);
654 		}
655 #endif
656 		pcb->pcb_onfault = NULL;
657 		rv = uvm_fault(map, va, ftype);
658 		pcb->pcb_onfault = onfault;
659 #ifdef DEBUG
660 		if (rv && MDB_ISPID(p->p_pid))
661 			printf("vm_fault(%p, %lx, %x) -> %x\n",
662 			       map, va, ftype, rv);
663 #endif
664 		/*
665 		 * If this was a stack access we keep track of the maximum
666 		 * accessed stack size.  Also, if vm_fault gets a protection
667 		 * failure it is due to accessing the stack region outside
668 		 * the current limit and we need to reflect that as an access
669 		 * error.
670 		 */
671 		if (rv == 0) {
672 			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
673 				uvm_grow(p, va);
674 
675 			if (type == T_MMUFLT) {
676 				if (ucas_ras_check(&fp->F_t)) {
677 					return;
678 				}
679 #ifdef M68040
680 				if (cputype == CPU_68040)
681 					(void) writeback(fp, 1);
682 #endif
683 				return;
684 			}
685 			l->l_pflag &= ~LP_SA_PAGEFAULT;
686 			goto out;
687 		}
688 		if (rv == EACCES) {
689 			ksi.ksi_code = SEGV_ACCERR;
690 			rv = EFAULT;
691 		} else
692 			ksi.ksi_code = SEGV_MAPERR;
693 		if (type == T_MMUFLT) {
694 			if (onfault) {
695 				trapcpfault(l, fp, rv);
696 				return;
697 			}
698 			printf("\nvm_fault(%p, %lx, %x) -> %x\n",
699 			       map, va, ftype, rv);
700 			printf("  type %x, code [mmu,,ssw]: %x\n",
701 			       type, code);
702 			panictrap(type, code, v, fp);
703 		}
704 		l->l_pflag &= ~LP_SA_PAGEFAULT;
705 		ksi.ksi_addr = (void *)v;
706 		if (rv == ENOMEM) {
707 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
708 			       p->p_pid, p->p_comm,
709 			       l->l_cred ?
710 			       kauth_cred_geteuid(l->l_cred) : -1);
711 			ksi.ksi_signo = SIGKILL;
712 		} else {
713 			ksi.ksi_signo = SIGSEGV;
714 		}
715 		break;
716 	    }
717 	}
718 
719 	if (ksi.ksi_signo)
720 		trapsignal(l, &ksi);
721 	if ((type & T_USER) == 0)
722 		return;
723 out:
724 	userret(l, fp, sticks, v, 1);
725 }
726 
727 #ifdef M68040
728 #ifdef DEBUG
729 struct writebackstats {
730 	int calls;
731 	int cpushes;
732 	int move16s;
733 	int wb1s, wb2s, wb3s;
734 	int wbsize[4];
735 } wbstats;
736 
737 const char *f7sz[] = { "longword", "byte", "word", "line" };
738 const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
739 const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
740 		 "M-code", "k-data", "k-code", "RES" };
741 const char wberrstr[] =
742     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
743 
744 static void dumpwb(int, u_short, u_int, u_int);
745 static void dumpssw(u_short);
746 #endif /* DEBUG */
747 
748 static int
749 writeback(struct frame *fp, int docachepush)
750 {
751 	struct fmt7 *f = &fp->f_fmt7;
752 	struct lwp *l = curlwp;
753 	struct proc *p = l->l_proc;
754 	struct pcb *pcb = lwp_getpcb(l);
755 	int	err = 0;
756 	u_int	fa = 0;
757 	void *oonfault = 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[(f->f_fa & PGOFSET) & ~0xF];
800 			memcpy((void *)fa, (void *)&f->f_pd0, 16);
801 			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
802 			DCFL(pa);
803 			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
804 				    (vaddr_t)&vmmap[PAGE_SIZE]);
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, kauth_cred_geteuid(l->l_cred));
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((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0, 16);
826 		else
827 			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
828 		if (err) {
829 			fa = f->f_fa & ~0xF;
830 #ifdef DEBUG
831 			if (mmudebug & MDB_WBFAILED)
832 				printf(wberrstr, p->p_pid, p->p_comm,
833 				       "MOVE16", fp->f_pc, f->f_fa,
834 				       f->f_fa & ~0xF, f->f_pd0);
835 #endif
836 		}
837 	} else if (f->f_wb1s & SSW4_WBSV) {
838 		/*
839 		 * Writeback #1.
840 		 * Position the "memory-aligned" data and write it out.
841 		 */
842 		u_int wb1d = f->f_wb1d;
843 		int off;
844 
845 #ifdef DEBUG
846 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
847 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
848 		wbstats.wb1s++;
849 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
850 #endif
851 		off = (f->f_wb1a & 3) * 8;
852 		switch (f->f_wb1s & SSW4_SZMASK) {
853 		case SSW4_SZLW:
854 			if (off)
855 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
856 			if (KDFAULT(f->f_wb1s))
857 				*(long *)f->f_wb1a = wb1d;
858 			else
859 				err = suword((void *)f->f_wb1a, wb1d);
860 			break;
861 		case SSW4_SZB:
862 			off = 24 - off;
863 			if (off)
864 				wb1d >>= off;
865 			if (KDFAULT(f->f_wb1s))
866 				*(char *)f->f_wb1a = wb1d;
867 			else
868 				err = subyte((void *)f->f_wb1a, wb1d);
869 			break;
870 		case SSW4_SZW:
871 			off = (off + 16) % 32;
872 			if (off)
873 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
874 			if (KDFAULT(f->f_wb1s))
875 				*(short *)f->f_wb1a = wb1d;
876 			else
877 				err = susword((void *)f->f_wb1a, wb1d);
878 			break;
879 		}
880 		if (err) {
881 			fa = f->f_wb1a;
882 #ifdef DEBUG
883 			if (mmudebug & MDB_WBFAILED)
884 				printf(wberrstr, p->p_pid, p->p_comm,
885 				       "#1", fp->f_pc, f->f_fa,
886 				       f->f_wb1a, f->f_wb1d);
887 #endif
888 		}
889 	}
890 	/*
891 	 * Deal with the "normal" writebacks.
892 	 *
893 	 * XXX writeback2 is known to reflect a LINE size writeback after
894 	 * a MOVE16 was already dealt with above.  Ignore it.
895 	 */
896 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
897 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
898 #ifdef DEBUG
899 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
900 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
901 		wbstats.wb2s++;
902 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
903 #endif
904 		switch (f->f_wb2s & SSW4_SZMASK) {
905 		case SSW4_SZLW:
906 			if (KDFAULT(f->f_wb2s))
907 				*(long *)f->f_wb2a = f->f_wb2d;
908 			else
909 				err = suword((void *)f->f_wb2a, f->f_wb2d);
910 			break;
911 		case SSW4_SZB:
912 			if (KDFAULT(f->f_wb2s))
913 				*(char *)f->f_wb2a = f->f_wb2d;
914 			else
915 				err = subyte((void *)f->f_wb2a, f->f_wb2d);
916 			break;
917 		case SSW4_SZW:
918 			if (KDFAULT(f->f_wb2s))
919 				*(short *)f->f_wb2a = f->f_wb2d;
920 			else
921 				err = susword((void *)f->f_wb2a, f->f_wb2d);
922 			break;
923 		}
924 		if (err) {
925 			fa = f->f_wb2a;
926 #ifdef DEBUG
927 			if (mmudebug & MDB_WBFAILED) {
928 				printf(wberrstr, p->p_pid, p->p_comm,
929 				       "#2", fp->f_pc, f->f_fa,
930 				       f->f_wb2a, f->f_wb2d);
931 				dumpssw(f->f_ssw);
932 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
933 			}
934 #endif
935 		}
936 	}
937 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
938 #ifdef DEBUG
939 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
940 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
941 		wbstats.wb3s++;
942 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
943 #endif
944 		switch (f->f_wb3s & SSW4_SZMASK) {
945 		case SSW4_SZLW:
946 			if (KDFAULT(f->f_wb3s))
947 				*(long *)f->f_wb3a = f->f_wb3d;
948 			else
949 				err = suword((void *)f->f_wb3a, f->f_wb3d);
950 			break;
951 		case SSW4_SZB:
952 			if (KDFAULT(f->f_wb3s))
953 				*(char *)f->f_wb3a = f->f_wb3d;
954 			else
955 				err = subyte((void *)f->f_wb3a, f->f_wb3d);
956 			break;
957 		case SSW4_SZW:
958 			if (KDFAULT(f->f_wb3s))
959 				*(short *)f->f_wb3a = f->f_wb3d;
960 			else
961 				err = susword((void *)f->f_wb3a, f->f_wb3d);
962 			break;
963 #ifdef DEBUG
964 		case SSW4_SZLN:
965 			panic("writeback: wb3s indicates LINE write");
966 #endif
967 		}
968 		if (err) {
969 			fa = f->f_wb3a;
970 #ifdef DEBUG
971 			if (mmudebug & MDB_WBFAILED)
972 				printf(wberrstr, p->p_pid, p->p_comm,
973 				       "#3", fp->f_pc, f->f_fa,
974 				       f->f_wb3a, f->f_wb3d);
975 #endif
976 		}
977 	}
978 	pcb->pcb_onfault = oonfault;
979 	if (err)
980 		err = SIGSEGV;
981 	return(err);
982 }
983 
984 #ifdef DEBUG
985 static void
986 dumpssw(u_short ssw)
987 {
988 	printf(" SSW: %x: ", ssw);
989 	if (ssw & SSW4_CP)
990 		printf("CP,");
991 	if (ssw & SSW4_CU)
992 		printf("CU,");
993 	if (ssw & SSW4_CT)
994 		printf("CT,");
995 	if (ssw & SSW4_CM)
996 		printf("CM,");
997 	if (ssw & SSW4_MA)
998 		printf("MA,");
999 	if (ssw & SSW4_ATC)
1000 		printf("ATC,");
1001 	if (ssw & SSW4_LK)
1002 		printf("LK,");
1003 	if (ssw & SSW4_RW)
1004 		printf("RW,");
1005 	printf(" SZ=%s, TT=%s, TM=%s\n",
1006 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
1007 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
1008 	       f7tm[ssw & SSW4_TMMASK]);
1009 }
1010 
1011 static void
1012 dumpwb(int num, u_short s, u_int a, u_int d)
1013 {
1014 	struct proc *p = curproc;
1015 	paddr_t pa;
1016 
1017 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
1018 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
1019 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
1020 	printf("               PA ");
1021 	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
1022 		printf("<invalid address>");
1023 	else
1024 		printf("%lx, current value %lx", pa, fuword((void *)a));
1025 	printf("\n");
1026 }
1027 #endif /* DEBUG  */
1028 #endif /* M68040 */
1029