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