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