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