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