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