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