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