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