trap.c revision 1.44
1/*	$NetBSD: trap.c,v 1.44 2003/09/17 23:17:45 cl 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.44 2003/09/17 23:17:45 cl 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			if (l->l_flag & L_SA) {
646				KDASSERT(p != NULL && p->p_sa != NULL);
647				p->p_sa->sa_vp_faultaddr = (vaddr_t)v;
648				l->l_flag |= L_SA_PAGEFAULT;
649			}
650		}
651
652		if (WRFAULT(code))
653			ftype = VM_PROT_WRITE;
654		else
655			ftype = VM_PROT_READ;
656
657		va = trunc_page((vaddr_t)v);
658
659		if (map == kernel_map && va == 0) {
660			printf("trap: bad kernel %s access at 0x%x\n",
661			    (ftype & VM_PROT_WRITE) ? "read/write" :
662			    "read", v);
663			goto dopanic;
664		}
665
666#ifdef DIAGNOSTIC
667		if (interrupt_depth && !panicing) {
668			printf("trap: calling uvm_fault() from interrupt!\n");
669			goto dopanic;
670		}
671#endif
672
673#ifdef COMPAT_HPUX
674		if (ISHPMMADDR(va)) {
675			int pmap_mapmulti __P((pmap_t, vaddr_t));
676			vaddr_t bva;
677
678			rv = pmap_mapmulti(map->pmap, va);
679			if (rv != 0) {
680				bva = HPMMBASEADDR(va);
681				rv = uvm_fault(map, bva, 0, ftype);
682				if (rv == 0)
683					(void) pmap_mapmulti(map->pmap, va);
684			}
685		} else
686#endif
687		rv = uvm_fault(map, va, 0, ftype);
688#ifdef DEBUG
689		if (rv && MDB_ISPID(p->p_pid))
690			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
691			    map, va, ftype, rv);
692#endif
693		/*
694		 * If this was a stack access we keep track of the maximum
695		 * accessed stack size.  Also, if vm_fault gets a protection
696		 * failure it is due to accessing the stack region outside
697		 * the current limit and we need to reflect that as an access
698		 * error.
699		 */
700		if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
701		    && map != kernel_map) {
702			if (rv == 0) {
703				unsigned nss;
704
705				nss = btoc(USRSTACK-(unsigned)va);
706				if (nss > vm->vm_ssize)
707					vm->vm_ssize = nss;
708			} else if (rv == EACCES)
709				rv = EFAULT;
710		}
711		if (rv == 0) {
712			if (type == T_MMUFLT) {
713#ifdef M68040
714				if (cputype == CPU_68040)
715					(void) writeback(&frame, 1);
716#endif
717				return;
718			}
719			l->l_flag &= ~L_SA_PAGEFAULT;
720			goto out;
721		}
722		if (type == T_MMUFLT) {
723			if (l->l_addr->u_pcb.pcb_onfault)
724				goto copyfault;
725			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
726			    map, va, ftype, rv);
727			printf("  type %x, code [mmu,,ssw]: %x\n",
728			       type, code);
729			goto dopanic;
730		}
731		l->l_flag &= ~L_SA_PAGEFAULT;
732		ucode = v;
733		if (rv == ENOMEM) {
734			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
735			       p->p_pid, p->p_comm,
736			       p->p_cred && p->p_ucred ?
737			       p->p_ucred->cr_uid : -1);
738			i = SIGKILL;
739		} else {
740			i = SIGSEGV;
741		}
742		break;
743	    }
744	}
745	trapsignal(l, i, ucode);
746	if ((type & T_USER) == 0)
747		return;
748out:
749	userret(l, &frame, sticks, v, 1);
750}
751
752#ifdef M68040
753#ifdef DEBUG
754struct writebackstats {
755	int calls;
756	int cpushes;
757	int move16s;
758	int wb1s, wb2s, wb3s;
759	int wbsize[4];
760} wbstats;
761
762char *f7sz[] = { "longword", "byte", "word", "line" };
763char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
764char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
765		 "M-code", "k-data", "k-code", "RES" };
766char wberrstr[] =
767    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
768#endif
769
770int
771writeback(fp, docachepush)
772	struct frame *fp;
773	int docachepush;
774{
775	struct fmt7 *f = &fp->f_fmt7;
776	struct lwp *l = curlwp;
777	struct proc *p = l->l_proc;
778	int err = 0;
779	u_int fa;
780	caddr_t oonfault = l->l_addr->u_pcb.pcb_onfault;
781	paddr_t pa;
782
783#ifdef DEBUG
784	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
785		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
786		dumpssw(f->f_ssw);
787	}
788	wbstats.calls++;
789#endif
790	/*
791	 * Deal with special cases first.
792	 */
793	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
794		/*
795		 * Dcache push fault.
796		 * Line-align the address and write out the push data to
797		 * the indicated physical address.
798		 */
799#ifdef DEBUG
800		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
801			printf(" pushing %s to PA %x, data %x",
802			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
803			       f->f_fa, f->f_pd0);
804			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
805				printf("/%x/%x/%x",
806				       f->f_pd1, f->f_pd2, f->f_pd3);
807			printf("\n");
808		}
809		if (f->f_wb1s & SSW4_WBSV)
810			panic("writeback: cache push with WB1S valid");
811		wbstats.cpushes++;
812#endif
813		/*
814		 * XXX there are security problems if we attempt to do a
815		 * cache push after a signal handler has been called.
816		 */
817		if (docachepush) {
818			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
819			    trunc_page(f->f_fa), VM_PROT_WRITE,
820			    VM_PROT_WRITE|PMAP_WIRED);
821			pmap_update(pmap_kernel());
822			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
823			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
824			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
825			DCFL(pa);
826			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
827				    (vaddr_t)&vmmap[PAGE_SIZE]);
828			pmap_update(pmap_kernel());
829		} else
830			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
831			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
832	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
833		/*
834		 * MOVE16 fault.
835		 * Line-align the address and write out the push data to
836		 * the indicated virtual address.
837		 */
838#ifdef DEBUG
839		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
840			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
841			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
842			       f->f_pd2, f->f_pd3);
843		if (f->f_wb1s & SSW4_WBSV)
844			panic("writeback: MOVE16 with WB1S valid");
845		wbstats.move16s++;
846#endif
847		if (KDFAULT(f->f_wb1s))
848			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
849		else
850			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
851		if (err) {
852			fa = f->f_fa & ~0xF;
853#ifdef DEBUG
854			if (mmudebug & MDB_WBFAILED)
855				printf(wberrstr, p->p_pid, p->p_comm,
856				       "MOVE16", fp->f_pc, f->f_fa,
857				       f->f_fa & ~0xF, f->f_pd0);
858#endif
859		}
860	} else if (f->f_wb1s & SSW4_WBSV) {
861		/*
862		 * Writeback #1.
863		 * Position the "memory-aligned" data and write it out.
864		 */
865		u_int wb1d = f->f_wb1d;
866		int off;
867
868#ifdef DEBUG
869		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
870			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
871		wbstats.wb1s++;
872		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
873#endif
874		off = (f->f_wb1a & 3) * 8;
875		switch (f->f_wb1s & SSW4_SZMASK) {
876		case SSW4_SZLW:
877			if (off)
878				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
879			if (KDFAULT(f->f_wb1s))
880				*(long *)f->f_wb1a = wb1d;
881			else
882				err = suword((caddr_t)f->f_wb1a, wb1d);
883			break;
884		case SSW4_SZB:
885			off = 24 - off;
886			if (off)
887				wb1d >>= off;
888			if (KDFAULT(f->f_wb1s))
889				*(char *)f->f_wb1a = wb1d;
890			else
891				err = subyte((caddr_t)f->f_wb1a, wb1d);
892			break;
893		case SSW4_SZW:
894			off = (off + 16) % 32;
895			if (off)
896				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
897			if (KDFAULT(f->f_wb1s))
898				*(short *)f->f_wb1a = wb1d;
899			else
900				err = susword((caddr_t)f->f_wb1a, wb1d);
901			break;
902		}
903		if (err) {
904			fa = f->f_wb1a;
905#ifdef DEBUG
906			if (mmudebug & MDB_WBFAILED)
907				printf(wberrstr, p->p_pid, p->p_comm,
908				       "#1", fp->f_pc, f->f_fa,
909				       f->f_wb1a, f->f_wb1d);
910#endif
911		}
912	}
913	/*
914	 * Deal with the "normal" writebacks.
915	 *
916	 * XXX writeback2 is known to reflect a LINE size writeback after
917	 * a MOVE16 was already dealt with above.  Ignore it.
918	 */
919	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
920	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
921#ifdef DEBUG
922		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
923			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
924		wbstats.wb2s++;
925		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
926#endif
927		switch (f->f_wb2s & SSW4_SZMASK) {
928		case SSW4_SZLW:
929			if (KDFAULT(f->f_wb2s))
930				*(long *)f->f_wb2a = f->f_wb2d;
931			else
932				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
933			break;
934		case SSW4_SZB:
935			if (KDFAULT(f->f_wb2s))
936				*(char *)f->f_wb2a = f->f_wb2d;
937			else
938				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
939			break;
940		case SSW4_SZW:
941			if (KDFAULT(f->f_wb2s))
942				*(short *)f->f_wb2a = f->f_wb2d;
943			else
944				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
945			break;
946		}
947		if (err) {
948			fa = f->f_wb2a;
949#ifdef DEBUG
950			if (mmudebug & MDB_WBFAILED) {
951				printf(wberrstr, p->p_pid, p->p_comm,
952				       "#2", fp->f_pc, f->f_fa,
953				       f->f_wb2a, f->f_wb2d);
954				dumpssw(f->f_ssw);
955				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
956			}
957#endif
958		}
959	}
960	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
961#ifdef DEBUG
962		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
963			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
964		wbstats.wb3s++;
965		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
966#endif
967		switch (f->f_wb3s & SSW4_SZMASK) {
968		case SSW4_SZLW:
969			if (KDFAULT(f->f_wb3s))
970				*(long *)f->f_wb3a = f->f_wb3d;
971			else
972				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
973			break;
974		case SSW4_SZB:
975			if (KDFAULT(f->f_wb3s))
976				*(char *)f->f_wb3a = f->f_wb3d;
977			else
978				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
979			break;
980		case SSW4_SZW:
981			if (KDFAULT(f->f_wb3s))
982				*(short *)f->f_wb3a = f->f_wb3d;
983			else
984				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
985			break;
986#ifdef DEBUG
987		case SSW4_SZLN:
988			panic("writeback: wb3s indicates LINE write");
989#endif
990		}
991		if (err) {
992			fa = f->f_wb3a;
993#ifdef DEBUG
994			if (mmudebug & MDB_WBFAILED)
995				printf(wberrstr, p->p_pid, p->p_comm,
996				       "#3", fp->f_pc, f->f_fa,
997				       f->f_wb3a, f->f_wb3d);
998#endif
999		}
1000	}
1001	l->l_addr->u_pcb.pcb_onfault = oonfault;
1002	if (err)
1003		err = SIGSEGV;
1004	return (err);
1005}
1006
1007#ifdef DEBUG
1008void
1009dumpssw(ssw)
1010	u_short ssw;
1011{
1012	printf(" SSW: %x: ", ssw);
1013	if (ssw & SSW4_CP)
1014		printf("CP,");
1015	if (ssw & SSW4_CU)
1016		printf("CU,");
1017	if (ssw & SSW4_CT)
1018		printf("CT,");
1019	if (ssw & SSW4_CM)
1020		printf("CM,");
1021	if (ssw & SSW4_MA)
1022		printf("MA,");
1023	if (ssw & SSW4_ATC)
1024		printf("ATC,");
1025	if (ssw & SSW4_LK)
1026		printf("LK,");
1027	if (ssw & SSW4_RW)
1028		printf("RW,");
1029	printf(" SZ=%s, TT=%s, TM=%s\n",
1030	       f7sz[(ssw & SSW4_SZMASK) >> 5],
1031	       f7tt[(ssw & SSW4_TTMASK) >> 3],
1032	       f7tm[ssw & SSW4_TMMASK]);
1033}
1034
1035void
1036dumpwb(num, s, a, d)
1037	int num;
1038	u_short s;
1039	u_int a, d;
1040{
1041	struct proc *p = curproc;
1042	paddr_t pa;
1043
1044	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
1045	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
1046	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
1047	printf("               PA ");
1048	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
1049		printf("<invalid address>");
1050	else
1051		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
1052	printf("\n");
1053}
1054#endif
1055#endif
1056
1057/*
1058 * Allocation routines for software interrupts.
1059 */
1060u_long
1061allocate_sir(proc, arg)
1062	void (*proc)(void *);
1063	void *arg;
1064{
1065	int bit;
1066
1067	if( next_sir >= NSIR )
1068		panic("allocate_sir: none left");
1069	bit = next_sir++;
1070	sir_routines[bit] = proc;
1071	sir_args[bit] = arg;
1072	return (1 << bit);
1073}
1074
1075void
1076init_sir()
1077{
1078	extern void netintr(void);
1079
1080	sir_routines[0] = (void (*)(void *))netintr;
1081	sir_routines[1] = softclock;
1082	next_sir = 2;
1083}
1084