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