trap.c revision 1.6
1/*	$NetBSD: trap.c,v 1.6 1998/10/01 02:53:55 thorpej 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. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *	This product includes software developed by the University of
23 *	California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 *    may be used to endorse or promote products derived from this software
26 *    without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Utah $Hdr: trap.c 1.37 92/12/20$
41 *
42 *	@(#)trap.c	8.5 (Berkeley) 1/4/94
43 */
44
45#include "opt_ddb.h"
46#include "opt_ktrace.h"
47#include "opt_compat_netbsd.h"
48#include "opt_compat_sunos.h"
49#include "opt_compat_hpux.h"
50
51#if 0
52#include <machine/hp300spu.h>	/* XXX param.h includes cpu.h */
53#endif
54
55#include <sys/param.h>
56#include <sys/systm.h>
57#include <sys/proc.h>
58#include <sys/acct.h>
59#include <sys/kernel.h>
60#include <sys/signalvar.h>
61#include <sys/resourcevar.h>
62#include <sys/syscall.h>
63#include <sys/syslog.h>
64#include <sys/user.h>
65#ifdef KTRACE
66#include <sys/ktrace.h>
67#endif
68
69#include <m68k/frame.h>
70
71#include <machine/db_machdep.h>
72#include <machine/psl.h>
73#include <machine/trap.h>
74#include <machine/cpu.h>
75#include <machine/reg.h>
76#include <machine/intr.h>
77
78#include <vm/vm.h>
79#include <vm/pmap.h>
80
81#include <dev/cons.h>
82
83#ifdef COMPAT_HPUX
84#include <compat/hpux/hpux.h>
85extern struct emul emul_hpux;
86#endif
87
88#ifdef COMPAT_SUNOS
89#include <compat/sunos/sunos_syscall.h>
90extern struct emul emul_sunos;
91#endif
92
93int	writeback __P((struct frame *fp, int docachepush));
94void	trap __P((int type, u_int code, u_int v, struct frame frame));
95void	syscall __P((register_t code, struct frame frame));
96void	child_return __P((struct proc *, struct frame));
97
98#ifdef DEBUG
99void	dumpssw __P((u_short));
100void	dumpwb __P((int, u_short, u_int, u_int));
101#endif
102
103static inline void userret __P((struct proc *p, struct frame *fp,
104	    u_quad_t oticks, u_int faultaddr, int fromtrap));
105
106char	*trap_type[] = {
107	"Bus error",
108	"Address error",
109	"Illegal instruction",
110	"Zero divide",
111	"CHK instruction",
112	"TRAPV instruction",
113	"Privilege violation",
114	"Trace trap",
115	"MMU fault",
116	"SSIR trap",
117	"Format error",
118	"68881 exception",
119	"Coprocessor violation",
120	"Async system trap"
121};
122int	trap_types = sizeof trap_type / sizeof trap_type[0];
123
124/*
125 * Size of various exception stack frames (minus the standard 8 bytes)
126 */
127short	exframesize[] = {
128	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
129	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
130	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
131	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
132	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
133	-1, -1,		/* type 5-6 - undefined */
134	FMT7SIZE,	/* type 7 - access error (68040) */
135	58,		/* type 8 - bus fault (68010) */
136	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
137	FMTASIZE,	/* type A - short bus fault (68020/030) */
138	FMTBSIZE,	/* type B - long bus fault (68020/030) */
139	-1, -1, -1, -1	/* type C-F - undefined */
140};
141
142#ifdef M68060
143#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
144#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
145#else
146#define	KDFAULT_060(c)	0
147#define	WRFAULT_060(c)	0
148#endif
149
150#ifdef M68040
151#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
152			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
153#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
154			 ((c) & SSW4_RW) == 0)
155#else
156#define	KDFAULT_040(c)	0
157#define	WRFAULT_040(c)	0
158#endif
159
160#if defined(M68030) || defined(M68020)
161#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
162			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
163#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
164			 ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
165#else
166#define	KDFAULT_OTH(c)	0
167#define	WRFAULT_OTH(c)	0
168#endif
169
170#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
171#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
172
173#ifdef DEBUG
174int mmudebug = 0;
175int mmupid = -1;
176#define MDB_FOLLOW	1
177#define MDB_WBFOLLOW	2
178#define MDB_WBFAILED	4
179#define MDB_ISPID(p)	((p) == mmupid)
180#endif
181
182#define NSIR	32
183void (*sir_routines[NSIR])();
184void *sir_args[NSIR];
185int next_sir;
186
187/*
188 * trap and syscall both need the following work done before returning
189 * to user mode.
190 */
191static inline void
192userret(p, fp, oticks, faultaddr, fromtrap)
193	struct proc *p;
194	struct frame *fp;
195	u_quad_t oticks;
196	u_int faultaddr;
197	int fromtrap;
198{
199	int sig, s;
200#ifdef M68040
201	int beenhere = 0;
202
203again:
204#endif
205	/* take pending signals */
206	while ((sig = CURSIG(p)) != 0)
207		postsig(sig);
208	p->p_priority = p->p_usrpri;
209	if (want_resched) {
210		/*
211		 * Since we are curproc, clock will normally just change
212		 * our priority without moving us from one queue to another
213		 * (since the running process is not on a queue.)
214		 * If that happened after we put ourselves on the run queue
215		 * but before we mi_switch()'ed, we might not be on the queue
216		 * indicated by our priority.
217		 */
218		s = splstatclock();
219		setrunqueue(p);
220		p->p_stats->p_ru.ru_nivcsw++;
221		mi_switch();
222		splx(s);
223		while ((sig = CURSIG(p)) != 0)
224			postsig(sig);
225	}
226
227	/*
228	 * If profiling, charge system time to the trapped pc.
229	 */
230	if (p->p_flag & P_PROFIL) {
231		extern int psratio;
232
233		addupc_task(p, fp->f_pc,
234			    (int)(p->p_sticks - oticks) * psratio);
235	}
236#ifdef M68040
237	/*
238	 * Deal with user mode writebacks (from trap, or from sigreturn).
239	 * If any writeback fails, go back and attempt signal delivery.
240	 * unless we have already been here and attempted the writeback
241	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
242	 * we just return to the user without sucessfully completing
243	 * the writebacks.  Maybe we should just drop the sucker?
244	 */
245	if (cputype == CPU_68040 && fp->f_format == FMT7) {
246		if (beenhere) {
247#ifdef DEBUG
248			if (mmudebug & MDB_WBFAILED)
249				printf(fromtrap ?
250		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
251		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
252				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
253#endif
254		} else if ((sig = writeback(fp, fromtrap))) {
255			beenhere = 1;
256			oticks = p->p_sticks;
257			trapsignal(p, sig, faultaddr);
258			goto again;
259		}
260	}
261#endif
262	curpriority = p->p_priority;
263}
264
265/*
266 * Trap is called from locore to handle most types of processor traps,
267 * including events such as simulated software interrupts/AST's.
268 * System calls are broken out for efficiency.
269 */
270/*ARGSUSED*/
271void
272trap(type, code, v, frame)
273	int type;
274	unsigned code;
275	unsigned v;
276	struct frame frame;
277{
278	extern char fubail[], subail[];
279	struct proc *p;
280	int i, s;
281        int bit;
282	u_int ucode;
283	u_quad_t sticks = 0 /* XXX initializer works around compiler bug */;
284
285	cnt.v_trap++;
286	p = curproc;
287	ucode = 0;
288
289	/* I have verified that this DOES happen! -gwr */
290	if (p == NULL)
291		p = &proc0;
292#ifdef DIAGNOSTIC
293	if (p->p_addr == NULL)
294		panic("trap: no pcb");
295#endif
296
297	if (USERMODE(frame.f_sr)) {
298		type |= T_USER;
299		sticks = p->p_sticks;
300		p->p_md.md_regs = frame.f_regs;
301	}
302	switch (type) {
303
304	default:
305	dopanic:
306		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
307		printf("%s program counter = 0x%x\n",
308		    (type & T_USER) ? "user" : "kernel", frame.f_pc);
309		/*
310		 * Let the kernel debugger see the trap frame that
311		 * caused us to panic.  This is a convenience so
312		 * one can see registers at the point of failure.
313		 */
314		s = splhigh();
315#ifdef KGDB
316		/* If connected, step or cont returns 1 */
317		if (kgdb_trap(type, &frame))
318			goto kgdb_cont;
319#endif
320#ifdef DDB
321		(void)kdb_trap(type, (db_regs_t *)&frame);
322#endif
323#ifdef KGDB
324	kgdb_cont:
325#endif
326		splx(s);
327		if (panicstr) {
328			printf("trap during panic!\n");
329#ifdef DEBUG
330			/* XXX should be a machine-dependent hook */
331			printf("(press a key)\n"); (void)cngetc();
332#endif
333		}
334		regdump((struct trapframe *)&frame, 128);
335		type &= ~T_USER;
336		if ((u_int)type < trap_types)
337			panic(trap_type[type]);
338		panic("trap");
339
340	case T_BUSERR:		/* kernel bus error */
341		if (p->p_addr->u_pcb.pcb_onfault == 0)
342			goto dopanic;
343		/* FALLTHROUGH */
344
345	copyfault:
346		/*
347		 * If we have arranged to catch this fault in any of the
348		 * copy to/from user space routines, set PC to return to
349		 * indicated location and set flag informing buserror code
350		 * that it may need to clean up stack frame.
351		 */
352		frame.f_stackadj = exframesize[frame.f_format];
353		frame.f_format = frame.f_vector = 0;
354		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
355		return;
356
357	case T_BUSERR|T_USER:	/* bus error */
358	case T_ADDRERR|T_USER:	/* address error */
359		ucode = v;
360		i = SIGBUS;
361		break;
362
363	case T_COPERR:		/* kernel coprocessor violation */
364	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
365	case T_FMTERR:		/* ...just in case... */
366	/*
367	 * The user has most likely trashed the RTE or FP state info
368	 * in the stack frame of a signal handler.
369	 */
370		printf("pid %d: kernel %s exception\n", p->p_pid,
371		       type==T_COPERR ? "coprocessor" : "format");
372		type |= T_USER;
373		p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL;
374		sigdelset(&p->p_sigignore, SIGILL);
375		sigdelset(&p->p_sigcatch, SIGILL);
376		sigdelset(&p->p_sigmask, SIGILL);
377		i = SIGILL;
378		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
379		break;
380
381	case T_COPERR|T_USER:	/* user coprocessor violation */
382	/* What is a proper response here? */
383		ucode = 0;
384		i = SIGFPE;
385		break;
386
387	case T_FPERR|T_USER:	/* 68881 exceptions */
388	/*
389	 * We pass along the 68881 status which locore stashed
390	 * in code for us.  Note that there is a possibility that the
391	 * bit pattern of this will conflict with one of the
392	 * FPE_* codes defined in signal.h.  Fortunately for us, the
393	 * only such codes we use are all in the range 1-7 and the low
394	 * 3 bits of the status are defined as 0 so there is
395	 * no clash.
396	 */
397		ucode = code;
398		i = SIGFPE;
399		break;
400
401#ifdef M68040
402	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
403	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
404		/* XXX need to FSAVE */
405		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
406		       p->p_pid, p->p_comm,
407		       frame.f_format == 2 ? "instruction" : "data type",
408		       frame.f_pc, frame.f_fmt2.f_iaddr);
409		/* XXX need to FRESTORE */
410		i = SIGFPE;
411		break;
412#endif
413
414	case T_ILLINST|T_USER:	/* illegal instruction fault */
415#ifdef COMPAT_HPUX
416		if (p->p_emul == &emul_hpux) {
417			ucode = HPUX_ILL_ILLINST_TRAP;
418			i = SIGILL;
419			break;
420		}
421		/* fall through */
422#endif
423	case T_PRIVINST|T_USER:	/* privileged instruction fault */
424#ifdef COMPAT_HPUX
425		if (p->p_emul == &emul_hpux)
426			ucode = HPUX_ILL_PRIV_TRAP;
427		else
428#endif
429		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
430		i = SIGILL;
431		break;
432
433	case T_ZERODIV|T_USER:	/* Divide by zero */
434#ifdef COMPAT_HPUX
435		if (p->p_emul == &emul_hpux)
436			ucode = HPUX_FPE_INTDIV_TRAP;
437		else
438#endif
439		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
440		i = SIGFPE;
441		break;
442
443	case T_CHKINST|T_USER:	/* CHK instruction trap */
444#ifdef COMPAT_HPUX
445		if (p->p_emul == &emul_hpux) {
446			/* handled differently under hp-ux */
447			i = SIGILL;
448			ucode = HPUX_ILL_CHK_TRAP;
449			break;
450		}
451#endif
452		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
453		i = SIGFPE;
454		break;
455
456	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
457#ifdef COMPAT_HPUX
458		if (p->p_emul == &emul_hpux) {
459			/* handled differently under hp-ux */
460			i = SIGILL;
461			ucode = HPUX_ILL_TRAPV_TRAP;
462			break;
463		}
464#endif
465		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
466		i = SIGFPE;
467		break;
468
469	/*
470	 * XXX: Trace traps are a nightmare.
471	 *
472	 *	HP-UX uses trap #1 for breakpoints,
473	 *	NetBSD/m68k uses trap #2,
474	 *	SUN 3.x uses trap #15,
475	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
476	 *	handled elsewhere).
477	 *
478	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
479	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
480	 * supported yet.
481	 *
482	 * XXX: We should never get kernel-mode T_TRACE or T_TRAP15
483	 * XXX: because locore.s now gives them special treatment.
484	 */
485	case T_TRACE:		/* kernel trace trap */
486	case T_TRAP15:		/* kernel breakpoint */
487#ifdef DEBUG
488		printf("unexpected kernel trace trap, type = %d\n", type);
489		printf("program counter = 0x%x\n", frame.f_pc);
490#endif
491		frame.f_sr &= ~PSL_T;
492		return;
493
494	case T_TRACE|T_USER:	/* user trace trap */
495	case T_TRAP15|T_USER:	/* SUN user trace trap */
496#ifdef COMPAT_SUNOS
497		/*
498		 * SunOS uses Trap #2 for a "CPU cache flush".
499		 * Just flush the on-chip caches and return.
500		 */
501		if (p->p_emul == &emul_sunos) {
502			ICIA();
503			DCIU();
504			return;
505		}
506#endif
507		frame.f_sr &= ~PSL_T;
508		i = SIGTRAP;
509		break;
510
511	case T_ASTFLT:		/* system async trap, cannot happen */
512		goto dopanic;
513
514	case T_ASTFLT|T_USER:	/* user async trap */
515		astpending = 0;
516		/*
517		 * We check for software interrupts first.  This is because
518		 * they are at a higher level than ASTs, and on a VAX would
519		 * interrupt the AST.  We assume that if we are processing
520		 * an AST that we must be at IPL0 so we don't bother to
521		 * check.  Note that we ensure that we are at least at SIR
522		 * IPL while processing the SIR.
523		 */
524		spl1();
525		/* fall into... */
526
527	case T_SSIR:		/* software interrupt */
528	case T_SSIR|T_USER:
529		while (bit = ffs(ssir)) {
530			--bit;
531			ssir &= ~(1 << bit);
532			cnt.v_soft++;
533			if (sir_routines[bit])
534				sir_routines[bit](sir_args[bit]);
535		}
536
537		/*
538		 * If this was not an AST trap, we are all done.
539		 */
540		if (type != (T_ASTFLT|T_USER)) {
541			cnt.v_trap--;
542			return;
543		}
544		spl0();
545		if (p->p_flag & P_OWEUPC) {
546			p->p_flag &= ~P_OWEUPC;
547			ADDUPROF(p);
548		}
549		goto out;
550
551	case T_MMUFLT:		/* kernel mode page fault */
552		/*
553		 * If we were doing profiling ticks or other user mode
554		 * stuff from interrupt code, Just Say No.
555		 */
556		if (p->p_addr->u_pcb.pcb_onfault == fubail ||
557		    p->p_addr->u_pcb.pcb_onfault == subail)
558			goto copyfault;
559		/* fall into ... */
560
561	case T_MMUFLT|T_USER:	/* page fault */
562	    {
563		vm_offset_t va;
564		struct vmspace *vm = p->p_vmspace;
565		vm_map_t map;
566		int rv;
567		vm_prot_t ftype;
568		extern vm_map_t kernel_map;
569
570#ifdef DEBUG
571		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
572		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
573		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
574#endif
575		/*
576		 * It is only a kernel address space fault iff:
577		 * 	1. (type & T_USER) == 0  and
578		 * 	2. pcb_onfault not set or
579		 *	3. pcb_onfault set but supervisor space data fault
580		 * The last can occur during an exec() copyin where the
581		 * argument space is lazy-allocated.
582		 */
583		if ((type & T_USER) == 0 &&
584		    ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
585			map = kernel_map;
586		else
587			map = vm ? &vm->vm_map : kernel_map;
588
589		if (WRFAULT(code))
590			ftype = VM_PROT_READ | VM_PROT_WRITE;
591		else
592			ftype = VM_PROT_READ;
593
594		va = trunc_page((vm_offset_t)v);
595
596		if (map == kernel_map && va == 0) {
597			printf("trap: bad kernel %s access at 0x%x\n",
598			    (ftype & VM_PROT_WRITE) ? "read/write" :
599			    "read", v);
600			goto dopanic;
601		}
602
603#ifdef COMPAT_HPUX
604		if (ISHPMMADDR(va)) {
605			int pmap_mapmulti __P((pmap_t, vm_offset_t));
606			vm_offset_t bva;
607
608			rv = pmap_mapmulti(map->pmap, va);
609			if (rv != KERN_SUCCESS) {
610				bva = HPMMBASEADDR(va);
611				rv = vm_fault(map, bva, ftype, FALSE);
612				if (rv == KERN_SUCCESS)
613					(void) pmap_mapmulti(map->pmap, va);
614			}
615		} else
616#endif
617		rv = vm_fault(map, va, ftype, FALSE);
618#ifdef DEBUG
619		if (rv && MDB_ISPID(p->p_pid))
620			printf("vm_fault(%p, %lx, %x, 0) -> %x\n",
621			       map, va, ftype, rv);
622#endif
623		/*
624		 * If this was a stack access we keep track of the maximum
625		 * accessed stack size.  Also, if vm_fault gets a protection
626		 * failure it is due to accessing the stack region outside
627		 * the current limit and we need to reflect that as an access
628		 * error.
629		 */
630		if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
631		    && map != kernel_map) {
632			if (rv == KERN_SUCCESS) {
633				unsigned nss;
634
635				nss = clrnd(btoc(USRSTACK-(unsigned)va));
636				if (nss > vm->vm_ssize)
637					vm->vm_ssize = nss;
638			} else if (rv == KERN_PROTECTION_FAILURE)
639				rv = KERN_INVALID_ADDRESS;
640		}
641		if (rv == KERN_SUCCESS) {
642			if (type == T_MMUFLT) {
643#ifdef M68040
644				if (cputype == CPU_68040)
645					(void) writeback(&frame, 1);
646#endif
647				return;
648			}
649			goto out;
650		}
651		if (type == T_MMUFLT) {
652			if (p->p_addr->u_pcb.pcb_onfault)
653				goto copyfault;
654			printf("vm_fault(%p, %lx, %x, 0) -> %x\n",
655			       map, va, ftype, rv);
656			printf("  type %x, code [mmu,,ssw]: %x\n",
657			       type, code);
658			goto dopanic;
659		}
660		ucode = v;
661		i = SIGSEGV;
662		break;
663	    }
664	}
665	trapsignal(p, i, ucode);
666	if ((type & T_USER) == 0)
667		return;
668out:
669	userret(p, &frame, sticks, v, 1);
670}
671
672#ifdef M68040
673#ifdef DEBUG
674struct writebackstats {
675	int calls;
676	int cpushes;
677	int move16s;
678	int wb1s, wb2s, wb3s;
679	int wbsize[4];
680} wbstats;
681
682char *f7sz[] = { "longword", "byte", "word", "line" };
683char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
684char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
685		 "M-code", "k-data", "k-code", "RES" };
686char wberrstr[] =
687    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
688#endif
689
690int
691writeback(fp, docachepush)
692	struct frame *fp;
693	int docachepush;
694{
695	struct fmt7 *f = &fp->f_fmt7;
696	struct proc *p = curproc;
697	int err = 0;
698	u_int fa;
699	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
700
701#ifdef DEBUG
702	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
703		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
704		dumpssw(f->f_ssw);
705	}
706	wbstats.calls++;
707#endif
708	/*
709	 * Deal with special cases first.
710	 */
711	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
712		/*
713		 * Dcache push fault.
714		 * Line-align the address and write out the push data to
715		 * the indicated physical address.
716		 */
717#ifdef DEBUG
718		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
719			printf(" pushing %s to PA %x, data %x",
720			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
721			       f->f_fa, f->f_pd0);
722			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
723				printf("/%x/%x/%x",
724				       f->f_pd1, f->f_pd2, f->f_pd3);
725			printf("\n");
726		}
727		if (f->f_wb1s & SSW4_WBSV)
728			panic("writeback: cache push with WB1S valid");
729		wbstats.cpushes++;
730#endif
731		/*
732		 * XXX there are security problems if we attempt to do a
733		 * cache push after a signal handler has been called.
734		 */
735		if (docachepush) {
736			pmap_enter(pmap_kernel(), (vm_offset_t)vmmap,
737				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
738			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
739			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
740			DCFL(pmap_extract(pmap_kernel(), (vm_offset_t)fa));
741			pmap_remove(pmap_kernel(), (vm_offset_t)vmmap,
742				    (vm_offset_t)&vmmap[NBPG]);
743		} else
744			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
745			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
746	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
747		/*
748		 * MOVE16 fault.
749		 * Line-align the address and write out the push data to
750		 * the indicated virtual address.
751		 */
752#ifdef DEBUG
753		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
754			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
755			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
756			       f->f_pd2, f->f_pd3);
757		if (f->f_wb1s & SSW4_WBSV)
758			panic("writeback: MOVE16 with WB1S valid");
759		wbstats.move16s++;
760#endif
761		if (KDFAULT(f->f_wb1s))
762			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
763		else
764			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
765		if (err) {
766			fa = f->f_fa & ~0xF;
767#ifdef DEBUG
768			if (mmudebug & MDB_WBFAILED)
769				printf(wberrstr, p->p_pid, p->p_comm,
770				       "MOVE16", fp->f_pc, f->f_fa,
771				       f->f_fa & ~0xF, f->f_pd0);
772#endif
773		}
774	} else if (f->f_wb1s & SSW4_WBSV) {
775		/*
776		 * Writeback #1.
777		 * Position the "memory-aligned" data and write it out.
778		 */
779		u_int wb1d = f->f_wb1d;
780		int off;
781
782#ifdef DEBUG
783		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
784			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
785		wbstats.wb1s++;
786		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
787#endif
788		off = (f->f_wb1a & 3) * 8;
789		switch (f->f_wb1s & SSW4_SZMASK) {
790		case SSW4_SZLW:
791			if (off)
792				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
793			if (KDFAULT(f->f_wb1s))
794				*(long *)f->f_wb1a = wb1d;
795			else
796				err = suword((caddr_t)f->f_wb1a, wb1d);
797			break;
798		case SSW4_SZB:
799			off = 24 - off;
800			if (off)
801				wb1d >>= off;
802			if (KDFAULT(f->f_wb1s))
803				*(char *)f->f_wb1a = wb1d;
804			else
805				err = subyte((caddr_t)f->f_wb1a, wb1d);
806			break;
807		case SSW4_SZW:
808			off = (off + 16) % 32;
809			if (off)
810				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
811			if (KDFAULT(f->f_wb1s))
812				*(short *)f->f_wb1a = wb1d;
813			else
814				err = susword((caddr_t)f->f_wb1a, wb1d);
815			break;
816		}
817		if (err) {
818			fa = f->f_wb1a;
819#ifdef DEBUG
820			if (mmudebug & MDB_WBFAILED)
821				printf(wberrstr, p->p_pid, p->p_comm,
822				       "#1", fp->f_pc, f->f_fa,
823				       f->f_wb1a, f->f_wb1d);
824#endif
825		}
826	}
827	/*
828	 * Deal with the "normal" writebacks.
829	 *
830	 * XXX writeback2 is known to reflect a LINE size writeback after
831	 * a MOVE16 was already dealt with above.  Ignore it.
832	 */
833	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
834	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
835#ifdef DEBUG
836		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
837			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
838		wbstats.wb2s++;
839		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
840#endif
841		switch (f->f_wb2s & SSW4_SZMASK) {
842		case SSW4_SZLW:
843			if (KDFAULT(f->f_wb2s))
844				*(long *)f->f_wb2a = f->f_wb2d;
845			else
846				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
847			break;
848		case SSW4_SZB:
849			if (KDFAULT(f->f_wb2s))
850				*(char *)f->f_wb2a = f->f_wb2d;
851			else
852				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
853			break;
854		case SSW4_SZW:
855			if (KDFAULT(f->f_wb2s))
856				*(short *)f->f_wb2a = f->f_wb2d;
857			else
858				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
859			break;
860		}
861		if (err) {
862			fa = f->f_wb2a;
863#ifdef DEBUG
864			if (mmudebug & MDB_WBFAILED) {
865				printf(wberrstr, p->p_pid, p->p_comm,
866				       "#2", fp->f_pc, f->f_fa,
867				       f->f_wb2a, f->f_wb2d);
868				dumpssw(f->f_ssw);
869				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
870			}
871#endif
872		}
873	}
874	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
875#ifdef DEBUG
876		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
877			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
878		wbstats.wb3s++;
879		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
880#endif
881		switch (f->f_wb3s & SSW4_SZMASK) {
882		case SSW4_SZLW:
883			if (KDFAULT(f->f_wb3s))
884				*(long *)f->f_wb3a = f->f_wb3d;
885			else
886				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
887			break;
888		case SSW4_SZB:
889			if (KDFAULT(f->f_wb3s))
890				*(char *)f->f_wb3a = f->f_wb3d;
891			else
892				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
893			break;
894		case SSW4_SZW:
895			if (KDFAULT(f->f_wb3s))
896				*(short *)f->f_wb3a = f->f_wb3d;
897			else
898				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
899			break;
900#ifdef DEBUG
901		case SSW4_SZLN:
902			panic("writeback: wb3s indicates LINE write");
903#endif
904		}
905		if (err) {
906			fa = f->f_wb3a;
907#ifdef DEBUG
908			if (mmudebug & MDB_WBFAILED)
909				printf(wberrstr, p->p_pid, p->p_comm,
910				       "#3", fp->f_pc, f->f_fa,
911				       f->f_wb3a, f->f_wb3d);
912#endif
913		}
914	}
915	p->p_addr->u_pcb.pcb_onfault = oonfault;
916	if (err)
917		err = SIGSEGV;
918	return (err);
919}
920
921#ifdef DEBUG
922void
923dumpssw(ssw)
924	u_short ssw;
925{
926	printf(" SSW: %x: ", ssw);
927	if (ssw & SSW4_CP)
928		printf("CP,");
929	if (ssw & SSW4_CU)
930		printf("CU,");
931	if (ssw & SSW4_CT)
932		printf("CT,");
933	if (ssw & SSW4_CM)
934		printf("CM,");
935	if (ssw & SSW4_MA)
936		printf("MA,");
937	if (ssw & SSW4_ATC)
938		printf("ATC,");
939	if (ssw & SSW4_LK)
940		printf("LK,");
941	if (ssw & SSW4_RW)
942		printf("RW,");
943	printf(" SZ=%s, TT=%s, TM=%s\n",
944	       f7sz[(ssw & SSW4_SZMASK) >> 5],
945	       f7tt[(ssw & SSW4_TTMASK) >> 3],
946	       f7tm[ssw & SSW4_TMMASK]);
947}
948
949void
950dumpwb(num, s, a, d)
951	int num;
952	u_short s;
953	u_int a, d;
954{
955	struct proc *p = curproc;
956	vm_offset_t pa;
957
958	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
959	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
960	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
961	printf("               PA ");
962	pa = pmap_extract(p->p_vmspace->vm_map.pmap, (vm_offset_t)a);
963	if (pa == 0)
964		printf("<invalid address>");
965	else
966		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
967	printf("\n");
968}
969#endif
970#endif
971
972/*
973 * Process a system call.
974 */
975void
976syscall(code, frame)
977	register_t code;
978	struct frame frame;
979{
980	caddr_t params;
981	struct sysent *callp;
982	struct proc *p;
983	int error, opc, nsys;
984	size_t argsize;
985	register_t args[8], rval[2];
986	u_quad_t sticks;
987
988	cnt.v_syscall++;
989	if (!USERMODE(frame.f_sr))
990		panic("syscall");
991	p = curproc;
992	sticks = p->p_sticks;
993	p->p_md.md_regs = frame.f_regs;
994	opc = frame.f_pc;
995
996	nsys = p->p_emul->e_nsysent;
997	callp = p->p_emul->e_sysent;
998
999#ifdef COMPAT_SUNOS
1000	if (p->p_emul == &emul_sunos) {
1001		/*
1002		 * SunOS passes the syscall-number on the stack, whereas
1003		 * BSD passes it in D0. So, we have to get the real "code"
1004		 * from the stack, and clean up the stack, as SunOS glue
1005		 * code assumes the kernel pops the syscall argument the
1006		 * glue pushed on the stack. Sigh...
1007		 */
1008		code = fuword((caddr_t)frame.f_regs[SP]);
1009
1010		/*
1011		 * XXX
1012		 * Don't do this for sunos_sigreturn, as there's no stored pc
1013		 * on the stack to skip, the argument follows the syscall
1014		 * number without a gap.
1015		 */
1016		if (code != SUNOS_SYS_sigreturn) {
1017			frame.f_regs[SP] += sizeof (int);
1018			/*
1019			 * remember that we adjusted the SP,
1020			 * might have to undo this if the system call
1021			 * returns ERESTART.
1022			 */
1023			p->p_md.md_flags |= MDP_STACKADJ;
1024		} else
1025			p->p_md.md_flags &= ~MDP_STACKADJ;
1026	}
1027#endif
1028
1029	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
1030
1031	switch (code) {
1032	case SYS_syscall:
1033		/*
1034		 * Code is first argument, followed by actual args.
1035		 */
1036		code = fuword(params);
1037		params += sizeof(int);
1038		/*
1039		 * XXX sigreturn requires special stack manipulation
1040		 * that is only done if entered via the sigreturn
1041		 * trap.  Cannot allow it here so make sure we fail.
1042		 */
1043		switch (code) {
1044#ifdef COMPAT_13
1045		case SYS_compat_13_sigreturn13:
1046#endif
1047		case SYS___sigreturn14:
1048			code = nsys;
1049			break;
1050		}
1051		break;
1052	case SYS___syscall:
1053		/*
1054		 * Like syscall, but code is a quad, so as to maintain
1055		 * quad alignment for the rest of the arguments.
1056		 */
1057		if (callp != sysent)
1058			break;
1059		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
1060		params += sizeof(quad_t);
1061		break;
1062	default:
1063		break;
1064	}
1065	if (code < 0 || code >= nsys)
1066		callp += p->p_emul->e_nosys;		/* illegal */
1067	else
1068		callp += code;
1069	argsize = callp->sy_argsize;
1070	if (argsize)
1071		error = copyin(params, (caddr_t)args, argsize);
1072	else
1073		error = 0;
1074#ifdef SYSCALL_DEBUG
1075	scdebug_call(p, code, args);
1076#endif
1077#ifdef KTRACE
1078	if (KTRPOINT(p, KTR_SYSCALL))
1079		ktrsyscall(p->p_tracep, code, argsize, args);
1080#endif
1081	if (error)
1082		goto bad;
1083	rval[0] = 0;
1084	rval[1] = frame.f_regs[D1];
1085	error = (*callp->sy_call)(p, args, rval);
1086	switch (error) {
1087	case 0:
1088		frame.f_regs[D0] = rval[0];
1089		frame.f_regs[D1] = rval[1];
1090		frame.f_sr &= ~PSL_C;	/* carry bit */
1091		break;
1092	case ERESTART:
1093		/*
1094		 * We always enter through a `trap' instruction, which is 2
1095		 * bytes, so adjust the pc by that amount.
1096		 */
1097		frame.f_pc = opc - 2;
1098		break;
1099	case EJUSTRETURN:
1100		/* nothing to do */
1101		break;
1102	default:
1103	bad:
1104		if (p->p_emul->e_errno)
1105			error = p->p_emul->e_errno[error];
1106		frame.f_regs[D0] = error;
1107		frame.f_sr |= PSL_C;	/* carry bit */
1108		break;
1109	}
1110
1111#ifdef SYSCALL_DEBUG
1112	scdebug_ret(p, code, error, rval);
1113#endif
1114#ifdef COMPAT_SUNOS
1115	/* need new p-value for this */
1116	if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ))
1117		frame.f_regs[SP] -= sizeof (int);
1118#endif
1119	userret(p, &frame, sticks, (u_int)0, 0);
1120#ifdef KTRACE
1121	if (KTRPOINT(p, KTR_SYSRET))
1122		ktrsysret(p->p_tracep, code, error, rval[0]);
1123#endif
1124}
1125
1126void
1127child_return(p, frame)
1128	struct proc *p;
1129	struct frame frame;
1130{
1131
1132	frame.f_regs[D0] = 0;
1133	frame.f_sr &= ~PSL_C;
1134	frame.f_format = FMT0;
1135
1136	userret(p, &frame, 0, (u_int)0, 0);
1137#ifdef KTRACE
1138	if (KTRPOINT(p, KTR_SYSRET))
1139		ktrsysret(p->p_tracep, SYS_fork, 0, 0);
1140#endif
1141}
1142
1143/*
1144 * Allocation routines for software interrupts.
1145 */
1146u_long
1147allocate_sir(proc, arg)
1148	void (*proc)();
1149	void *arg;
1150{
1151	int bit;
1152
1153	if( next_sir >= NSIR )
1154		panic("allocate_sir: none left");
1155	bit = next_sir++;
1156	sir_routines[bit] = proc;
1157	sir_args[bit] = arg;
1158	return (1 << bit);
1159}
1160
1161void
1162init_sir()
1163{
1164	extern void netintr();
1165
1166	sir_routines[0] = netintr;
1167	sir_routines[1] = softclock;
1168	next_sir = 2;
1169}
1170