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