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