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