xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 41475)
1*41475Smckusick /*
2*41475Smckusick  * Copyright (c) 1988 University of Utah.
3*41475Smckusick  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4*41475Smckusick  * All rights reserved.
5*41475Smckusick  *
6*41475Smckusick  * This code is derived from software contributed to Berkeley by
7*41475Smckusick  * the Systems Programming Group of the University of Utah Computer
8*41475Smckusick  * Science Department.
9*41475Smckusick  *
10*41475Smckusick  * %sccs.include.redist.c%
11*41475Smckusick  *
12*41475Smckusick  * from: Utah $Hdr: trap.c 1.28 89/09/25$
13*41475Smckusick  *
14*41475Smckusick  *	@(#)trap.c	7.1 (Berkeley) 05/08/90
15*41475Smckusick  */
16*41475Smckusick 
17*41475Smckusick #include "cpu.h"
18*41475Smckusick #include "psl.h"
19*41475Smckusick #include "reg.h"
20*41475Smckusick #include "pte.h"
21*41475Smckusick #include "mtpr.h"
22*41475Smckusick 
23*41475Smckusick #include "param.h"
24*41475Smckusick #include "systm.h"
25*41475Smckusick #include "user.h"
26*41475Smckusick #include "proc.h"
27*41475Smckusick #include "seg.h"
28*41475Smckusick #include "trap.h"
29*41475Smckusick #include "acct.h"
30*41475Smckusick #include "kernel.h"
31*41475Smckusick #include "vm.h"
32*41475Smckusick #include "cmap.h"
33*41475Smckusick #include "syslog.h"
34*41475Smckusick #ifdef KTRACE
35*41475Smckusick #include "ktrace.h"
36*41475Smckusick #endif
37*41475Smckusick 
38*41475Smckusick #ifdef HPUXCOMPAT
39*41475Smckusick #include "../hpux/hpux.h"
40*41475Smckusick #endif
41*41475Smckusick 
42*41475Smckusick #define	USER	040		/* user-mode flag added to type */
43*41475Smckusick 
44*41475Smckusick struct	sysent	sysent[];
45*41475Smckusick int	nsysent;
46*41475Smckusick 
47*41475Smckusick char	*trap_type[] = {
48*41475Smckusick 	"Bus error",
49*41475Smckusick 	"Address error",
50*41475Smckusick 	"Illegal instruction",
51*41475Smckusick 	"Zero divide",
52*41475Smckusick 	"CHK instruction",
53*41475Smckusick 	"TRAPV instruction",
54*41475Smckusick 	"Privilege violation",
55*41475Smckusick 	"Trace trap",
56*41475Smckusick 	"MMU fault",
57*41475Smckusick 	"SSIR trap",
58*41475Smckusick 	"Format error",
59*41475Smckusick 	"68881 exception",
60*41475Smckusick 	"Coprocessor violation",
61*41475Smckusick 	"Async system trap"
62*41475Smckusick };
63*41475Smckusick #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
64*41475Smckusick 
65*41475Smckusick #ifdef DEBUG
66*41475Smckusick int mmudebug = 0;
67*41475Smckusick #endif
68*41475Smckusick 
69*41475Smckusick /*
70*41475Smckusick  * Called from the trap handler when a processor trap occurs.
71*41475Smckusick  */
72*41475Smckusick /*ARGSUSED*/
73*41475Smckusick trap(type, code, v, frame)
74*41475Smckusick 	int type;
75*41475Smckusick 	unsigned code;
76*41475Smckusick 	register unsigned v;
77*41475Smckusick 	struct frame frame;
78*41475Smckusick {
79*41475Smckusick 	register int i;
80*41475Smckusick 	unsigned ucode = 0;
81*41475Smckusick 	register struct proc *p = u.u_procp;
82*41475Smckusick 	struct timeval syst;
83*41475Smckusick 	unsigned ncode;
84*41475Smckusick 
85*41475Smckusick 	cnt.v_trap++;
86*41475Smckusick 	syst = u.u_ru.ru_stime;
87*41475Smckusick 	if (USERMODE(frame.f_sr)) {
88*41475Smckusick 		type |= USER;
89*41475Smckusick 		u.u_ar0 = frame.f_regs;
90*41475Smckusick 	}
91*41475Smckusick 	switch (type) {
92*41475Smckusick 
93*41475Smckusick 	default:
94*41475Smckusick dopanic:
95*41475Smckusick #ifdef KGDB
96*41475Smckusick 		if (!panicstr && kgdb_trap(type, code, v, &frame))
97*41475Smckusick 			return;
98*41475Smckusick #endif
99*41475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
100*41475Smckusick 		regdump(frame.f_regs, 128);
101*41475Smckusick 		type &= ~USER;
102*41475Smckusick 		if ((unsigned)type < TRAP_TYPES)
103*41475Smckusick 			panic(trap_type[type]);
104*41475Smckusick 		panic("trap");
105*41475Smckusick 
106*41475Smckusick 	case T_BUSERR:		/* kernel bus error */
107*41475Smckusick 		if (!u.u_pcb.pcb_onfault)
108*41475Smckusick 			goto dopanic;
109*41475Smckusick 		/*
110*41475Smckusick 		 * If we have arranged to catch this fault in any of the
111*41475Smckusick 		 * copy to/from user space routines, set PC to return to
112*41475Smckusick 		 * indicated location and set flag informing buserror code
113*41475Smckusick 		 * that it may need to clean up stack frame.
114*41475Smckusick 		 */
115*41475Smckusick copyfault:
116*41475Smckusick 		frame.f_pc = (int) u.u_pcb.pcb_onfault;
117*41475Smckusick 		frame.f_stackadj = -1;
118*41475Smckusick 		return;
119*41475Smckusick 
120*41475Smckusick 	case T_BUSERR+USER:	/* bus error */
121*41475Smckusick 	case T_ADDRERR+USER:	/* address error */
122*41475Smckusick 		i = SIGBUS;
123*41475Smckusick 		break;
124*41475Smckusick 
125*41475Smckusick #ifdef FPCOPROC
126*41475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
127*41475Smckusick #endif
128*41475Smckusick 	case T_FMTERR:		/* kernel format error */
129*41475Smckusick 	/*
130*41475Smckusick 	 * The user has most likely trashed the RTE or FP state info
131*41475Smckusick 	 * in the stack frame of a signal handler.
132*41475Smckusick 	 */
133*41475Smckusick 		printf("pid %d: kernel %s exception\n", u.u_procp->p_pid,
134*41475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
135*41475Smckusick 		u.u_signal[SIGILL] = SIG_DFL;
136*41475Smckusick 		i = sigmask(SIGILL);
137*41475Smckusick 		p->p_sigignore &= ~i;
138*41475Smckusick 		p->p_sigcatch &= ~i;
139*41475Smckusick 		p->p_sigmask &= ~i;
140*41475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
141*41475Smckusick 		psignal(u.u_procp, SIGILL);
142*41475Smckusick 		goto out;
143*41475Smckusick 
144*41475Smckusick #ifdef FPCOPROC
145*41475Smckusick 	case T_COPERR+USER:	/* user coprocessor violation */
146*41475Smckusick 	/* What is a proper response here? */
147*41475Smckusick 		ucode = 0;
148*41475Smckusick 		i = SIGFPE;
149*41475Smckusick 		break;
150*41475Smckusick 
151*41475Smckusick 	case T_FPERR+USER:		/* 68881 exceptions */
152*41475Smckusick 	/*
153*41475Smckusick 	 * We pass along the 68881 status register which locore stashed
154*41475Smckusick 	 * in code for us.  Note that there is a possibility that the
155*41475Smckusick 	 * bit pattern of this register will conflict with one of the
156*41475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
157*41475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
158*41475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
159*41475Smckusick 	 * no clash.
160*41475Smckusick 	 */
161*41475Smckusick 		ucode = code;
162*41475Smckusick 		i = SIGFPE;
163*41475Smckusick 		break;
164*41475Smckusick #endif
165*41475Smckusick 
166*41475Smckusick 	case T_ILLINST+USER:	/* illegal instruction fault */
167*41475Smckusick #ifdef HPUXCOMPAT
168*41475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
169*41475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
170*41475Smckusick 			i = SIGILL;
171*41475Smckusick 			break;
172*41475Smckusick 		}
173*41475Smckusick 		/* fall through */
174*41475Smckusick #endif
175*41475Smckusick 	case T_PRIVINST+USER:	/* privileged instruction fault */
176*41475Smckusick #ifdef HPUXCOMPAT
177*41475Smckusick 		if (u.u_procp->p_flag & SHPUX)
178*41475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
179*41475Smckusick 		else
180*41475Smckusick #endif
181*41475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
182*41475Smckusick 		i = SIGILL;
183*41475Smckusick 		break;
184*41475Smckusick 
185*41475Smckusick 	case T_ZERODIV+USER:	/* Divide by zero */
186*41475Smckusick #ifdef HPUXCOMPAT
187*41475Smckusick 		if (u.u_procp->p_flag & SHPUX)
188*41475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
189*41475Smckusick 		else
190*41475Smckusick #endif
191*41475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
192*41475Smckusick 		i = SIGFPE;
193*41475Smckusick 		break;
194*41475Smckusick 
195*41475Smckusick 	case T_CHKINST+USER:	/* CHK instruction trap */
196*41475Smckusick #ifdef HPUXCOMPAT
197*41475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
198*41475Smckusick 			/* handled differently under hp-ux */
199*41475Smckusick 			i = SIGILL;
200*41475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
201*41475Smckusick 			break;
202*41475Smckusick 		}
203*41475Smckusick #endif
204*41475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
205*41475Smckusick 		i = SIGFPE;
206*41475Smckusick 		break;
207*41475Smckusick 
208*41475Smckusick 	case T_TRAPVINST+USER:	/* TRAPV instruction trap */
209*41475Smckusick #ifdef HPUXCOMPAT
210*41475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
211*41475Smckusick 			/* handled differently under hp-ux */
212*41475Smckusick 			i = SIGILL;
213*41475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
214*41475Smckusick 			break;
215*41475Smckusick 		}
216*41475Smckusick #endif
217*41475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
218*41475Smckusick 		i = SIGFPE;
219*41475Smckusick 		break;
220*41475Smckusick 
221*41475Smckusick 	/*
222*41475Smckusick 	 * XXX: Trace traps are a nightmare.
223*41475Smckusick 	 *
224*41475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
225*41475Smckusick 	 *	HPBSD uses trap #2,
226*41475Smckusick 	 *	SUN 3.x uses trap #15,
227*41475Smckusick 	 *	KGDB uses trap #15 (for kernel breakpoints).
228*41475Smckusick 	 *
229*41475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
230*41475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
231*41475Smckusick 	 * supported yet.  KGDB traps are also passed through as T_TRAP15
232*41475Smckusick 	 * and are not used yet.
233*41475Smckusick 	 */
234*41475Smckusick 	case T_TRACE:		/* kernel trace trap */
235*41475Smckusick 	case T_TRAP15:		/* SUN (or KGDB) kernel trace trap */
236*41475Smckusick #ifdef KGDB
237*41475Smckusick 		if (kgdb_trap(type, code, v, &frame))
238*41475Smckusick 			return;
239*41475Smckusick #endif
240*41475Smckusick 		frame.f_sr &= ~PSL_T;
241*41475Smckusick 		i = SIGTRAP;
242*41475Smckusick 		break;
243*41475Smckusick 
244*41475Smckusick 	case T_TRACE+USER:	/* user trace trap */
245*41475Smckusick 	case T_TRAP15+USER:	/* SUN user trace trap */
246*41475Smckusick #ifdef SUNCOMPAT
247*41475Smckusick 		/*
248*41475Smckusick 		 * Trap #2 is used to signal a cache flush.
249*41475Smckusick 		 * Should we also flush data cache?
250*41475Smckusick 		 */
251*41475Smckusick 		if (type == T_TRACE+USER && (p->p_flag & SSUN)) {
252*41475Smckusick 			ICIA();
253*41475Smckusick 			goto out;
254*41475Smckusick 		}
255*41475Smckusick #endif
256*41475Smckusick 		frame.f_sr &= ~PSL_T;
257*41475Smckusick 		i = SIGTRAP;
258*41475Smckusick 		break;
259*41475Smckusick 
260*41475Smckusick 	case T_AST:		/* system async trap, cannot happen */
261*41475Smckusick 		goto dopanic;
262*41475Smckusick 
263*41475Smckusick 	case T_AST+USER:	/* user async trap */
264*41475Smckusick 		astoff();
265*41475Smckusick 		/*
266*41475Smckusick 		 * We check for software interrupts first.  This is because
267*41475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
268*41475Smckusick 		 * interrupt the AST.  We assume that if we are processing
269*41475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
270*41475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
271*41475Smckusick 		 * IPL while processing the SIR.
272*41475Smckusick 		 */
273*41475Smckusick 		spl1();
274*41475Smckusick 		/* fall into... */
275*41475Smckusick 
276*41475Smckusick 	case T_SSIR:		/* software interrupt */
277*41475Smckusick 	case T_SSIR+USER:
278*41475Smckusick 		if (ssir & SIR_NET) {
279*41475Smckusick 			siroff(SIR_NET);
280*41475Smckusick 			cnt.v_soft++;
281*41475Smckusick 			netintr();
282*41475Smckusick 		}
283*41475Smckusick 		if (ssir & SIR_CLOCK) {
284*41475Smckusick 			siroff(SIR_CLOCK);
285*41475Smckusick 			cnt.v_soft++;
286*41475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
287*41475Smckusick 		}
288*41475Smckusick 		/*
289*41475Smckusick 		 * If this was not an AST trap, we are all done.
290*41475Smckusick 		 */
291*41475Smckusick 		if (type != T_AST+USER) {
292*41475Smckusick 			cnt.v_trap--;
293*41475Smckusick 			return;
294*41475Smckusick 		}
295*41475Smckusick 		spl0();
296*41475Smckusick #ifndef PROFTIMER
297*41475Smckusick 		if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) {
298*41475Smckusick 			addupc(frame.f_pc, &u.u_prof, 1);
299*41475Smckusick 			u.u_procp->p_flag &= ~SOWEUPC;
300*41475Smckusick 		}
301*41475Smckusick #endif
302*41475Smckusick 		goto out;
303*41475Smckusick 
304*41475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
305*41475Smckusick 		/*
306*41475Smckusick 		 * Could be caused by a page fault in one of the copy to/from
307*41475Smckusick 		 * user space routines.  If so, we will have a catch address.
308*41475Smckusick 		 */
309*41475Smckusick 		if (!u.u_pcb.pcb_onfault)
310*41475Smckusick 			goto dopanic;
311*41475Smckusick 		/* fall into ... */
312*41475Smckusick 
313*41475Smckusick 	case T_MMUFLT+USER:	/* page fault */
314*41475Smckusick /*
315*41475Smckusick 		printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n",
316*41475Smckusick 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
317*41475Smckusick */
318*41475Smckusick 		if (v >= USRSTACK) {
319*41475Smckusick 			if (type == T_MMUFLT)
320*41475Smckusick 				goto copyfault;
321*41475Smckusick 			i = SIGSEGV;
322*41475Smckusick 			break;
323*41475Smckusick 		}
324*41475Smckusick 		ncode = code >> 16;
325*41475Smckusick #if defined(HP330) || defined(HP360) || defined(HP370)
326*41475Smckusick 		/*
327*41475Smckusick 		 * Crudely map PMMU faults into HP MMU faults.
328*41475Smckusick 		 */
329*41475Smckusick 		if (mmutype != MMU_HP) {
330*41475Smckusick 			int ocode = ncode;
331*41475Smckusick 			ncode = 0;
332*41475Smckusick 			if (ocode & PMMU_WP)
333*41475Smckusick 				ncode |= MMU_WPF;
334*41475Smckusick 			else if (ocode & PMMU_INV) {
335*41475Smckusick 				if ((ocode & PMMU_LVLMASK) == 2)
336*41475Smckusick 					ncode |= MMU_PF;
337*41475Smckusick 				else
338*41475Smckusick 					ncode |= MMU_PTF;
339*41475Smckusick 			}
340*41475Smckusick 			/*
341*41475Smckusick 			 * RMW cycle, must load ATC by hand
342*41475Smckusick 			 */
343*41475Smckusick 			else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) {
344*41475Smckusick #ifdef DEBUG
345*41475Smckusick 				log(LOG_WARNING,
346*41475Smckusick 				    "RMW fault at %x: MMUSR %x SSW %x\n",
347*41475Smckusick 				    v, ocode, code & 0xFFFF);
348*41475Smckusick #endif
349*41475Smckusick 				ploadw((caddr_t)v);
350*41475Smckusick 				return;
351*41475Smckusick 			}
352*41475Smckusick 			/*
353*41475Smckusick 			 * Fault with no fault bits, should indicate bad
354*41475Smckusick 			 * hardware but we see this on 340s using starbase
355*41475Smckusick 			 * sometimes (faults accessing catseye registers)
356*41475Smckusick 			 */
357*41475Smckusick 			else {
358*41475Smckusick 				log(LOG_WARNING,
359*41475Smckusick 				    "Bad PMMU fault at %x: MMUSR %x SSW %x\n",
360*41475Smckusick 				    v, ocode, code & 0xFFFF);
361*41475Smckusick 				return;
362*41475Smckusick 			}
363*41475Smckusick #ifdef DEBUG
364*41475Smckusick 			if (mmudebug && mmudebug == p->p_pid)
365*41475Smckusick 				printf("MMU %d: v%x, os%x, ns%x\n",
366*41475Smckusick 				       p->p_pid, v, ocode, ncode);
367*41475Smckusick #endif
368*41475Smckusick 		}
369*41475Smckusick #endif
370*41475Smckusick #ifdef DEBUG
371*41475Smckusick 		if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) {
372*41475Smckusick 			printf("T_MMUFLT with no fault bits\n");
373*41475Smckusick 			goto dopanic;
374*41475Smckusick 		}
375*41475Smckusick #endif
376*41475Smckusick 		if (ncode & MMU_PTF) {
377*41475Smckusick #ifdef DEBUG
378*41475Smckusick 			/*
379*41475Smckusick 			 * NOTE: we use a u_int instead of an ste since the
380*41475Smckusick 			 * current compiler generates bogus code for some
381*41475Smckusick 			 * bitfield operations (i.e. attempts to access last
382*41475Smckusick 			 * word of a page as a longword causing fault).
383*41475Smckusick 			 */
384*41475Smckusick 			extern struct ste *vtoste();
385*41475Smckusick 			u_int *ste = (u_int *)vtoste(p, v);
386*41475Smckusick 
387*41475Smckusick 			if (*ste & SG_V) {
388*41475Smckusick 				if (ncode & MMU_WPF) {
389*41475Smckusick 					printf("PTF|WPF...\n");
390*41475Smckusick 					if (type == T_MMUFLT)
391*41475Smckusick 						goto copyfault;
392*41475Smckusick 					i = SIGBUS;
393*41475Smckusick 					break;
394*41475Smckusick 				}
395*41475Smckusick 				printf("MMU_PTF with sg_v, ste@%x = %x\n",
396*41475Smckusick 				       ste, *ste);
397*41475Smckusick 				goto dopanic;
398*41475Smckusick 			}
399*41475Smckusick #endif
400*41475Smckusick #ifdef HPUXCOMPAT
401*41475Smckusick 			if (ISHPMMADDR(v)) {
402*41475Smckusick 				extern struct ste *vtoste();
403*41475Smckusick 				u_int *bste, *nste;
404*41475Smckusick 
405*41475Smckusick 				bste = (u_int *)vtoste(p, HPMMBASEADDR(v));
406*41475Smckusick 				nste = (u_int *)vtoste(p, v);
407*41475Smckusick 				if ((*bste & SG_V) && *nste == SG_NV) {
408*41475Smckusick 					*nste = *bste;
409*41475Smckusick 					TBIAU();
410*41475Smckusick 					return;
411*41475Smckusick 				}
412*41475Smckusick 			}
413*41475Smckusick #endif
414*41475Smckusick 		growit:
415*41475Smckusick 			if (type == T_MMUFLT)
416*41475Smckusick 				goto copyfault;
417*41475Smckusick 			if (grow((unsigned)frame.f_regs[SP]) || grow(v))
418*41475Smckusick 				goto out;
419*41475Smckusick 			i = SIGSEGV;
420*41475Smckusick 			break;
421*41475Smckusick 		}
422*41475Smckusick #ifdef HPUXCOMPAT
423*41475Smckusick 		if (ISHPMMADDR(v)) {
424*41475Smckusick 			TBIS(v);
425*41475Smckusick 			v = HPMMBASEADDR(v);
426*41475Smckusick 		}
427*41475Smckusick #endif
428*41475Smckusick 		/*
429*41475Smckusick 		 * NOTE: WPF without PG_V is possible
430*41475Smckusick 		 * (e.g. attempt to write shared text which is paged out)
431*41475Smckusick 		 */
432*41475Smckusick 		if (ncode & MMU_WPF) {
433*41475Smckusick #ifdef DEBUG
434*41475Smckusick 			extern struct ste *vtoste();
435*41475Smckusick 			u_int *ste = (u_int *)vtoste(p, v);
436*41475Smckusick 
437*41475Smckusick 			if (!(*ste & SG_V)) {
438*41475Smckusick 				printf("MMU_WPF without sg_v, ste@%x = %x\n",
439*41475Smckusick 				       ste, *ste);
440*41475Smckusick 				goto dopanic;
441*41475Smckusick 			}
442*41475Smckusick #endif
443*41475Smckusick 			if (type == T_MMUFLT)
444*41475Smckusick 				goto copyfault;
445*41475Smckusick 			i = SIGBUS;
446*41475Smckusick 			break;
447*41475Smckusick 		}
448*41475Smckusick 		if (ncode & MMU_PF) {
449*41475Smckusick 			register u_int vp;
450*41475Smckusick #ifdef DEBUG
451*41475Smckusick 			extern struct ste *vtoste();
452*41475Smckusick 			u_int *ste = (u_int *)vtoste(p, v);
453*41475Smckusick 			struct pte *pte;
454*41475Smckusick 
455*41475Smckusick 			if (!(*ste & SG_V)) {
456*41475Smckusick 				printf("MMU_PF without sg_v, ste@%x = %x\n",
457*41475Smckusick 				       ste, *ste);
458*41475Smckusick 				goto dopanic;
459*41475Smckusick 			}
460*41475Smckusick #endif
461*41475Smckusick 			vp = btop(v);
462*41475Smckusick 			if (vp >= dptov(p, p->p_dsize) &&
463*41475Smckusick 			    vp < sptov(p, p->p_ssize-1))
464*41475Smckusick 				goto growit;
465*41475Smckusick #ifdef DEBUG
466*41475Smckusick 			pte = vtopte(p, vp);
467*41475Smckusick 			if (*(u_int *)pte & PG_V) {
468*41475Smckusick 				printf("MMU_PF with pg_v, pte = %x\n",
469*41475Smckusick 				       *(u_int *)pte);
470*41475Smckusick 				goto dopanic;
471*41475Smckusick 			}
472*41475Smckusick #endif
473*41475Smckusick 			i = u.u_error;
474*41475Smckusick 			pagein(v, 0);
475*41475Smckusick 			u.u_error = i;
476*41475Smckusick 			if (type == T_MMUFLT)
477*41475Smckusick 				return;
478*41475Smckusick 			goto out;
479*41475Smckusick 		}
480*41475Smckusick #ifdef DEBUG
481*41475Smckusick 		printf("T_MMUFLT: unrecognized scenerio\n");
482*41475Smckusick 		goto dopanic;
483*41475Smckusick #endif
484*41475Smckusick 	}
485*41475Smckusick 	trapsignal(i, ucode);
486*41475Smckusick 	if ((type & USER) == 0)
487*41475Smckusick 		return;
488*41475Smckusick out:
489*41475Smckusick 	p = u.u_procp;
490*41475Smckusick 	if (p->p_cursig || ISSIG(p))
491*41475Smckusick 		psig();
492*41475Smckusick 	p->p_pri = p->p_usrpri;
493*41475Smckusick 	if (runrun) {
494*41475Smckusick 		/*
495*41475Smckusick 		 * Since we are u.u_procp, clock will normally just change
496*41475Smckusick 		 * our priority without moving us from one queue to another
497*41475Smckusick 		 * (since the running process is not on a queue.)
498*41475Smckusick 		 * If that happened after we setrq ourselves but before we
499*41475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
500*41475Smckusick 		 * our priority.
501*41475Smckusick 		 */
502*41475Smckusick 		(void) splclock();
503*41475Smckusick 		setrq(p);
504*41475Smckusick 		u.u_ru.ru_nivcsw++;
505*41475Smckusick 		swtch();
506*41475Smckusick 		if (ISSIG(p))
507*41475Smckusick 			psig();
508*41475Smckusick 	}
509*41475Smckusick 	if (u.u_prof.pr_scale) {
510*41475Smckusick 		int ticks;
511*41475Smckusick 		struct timeval *tv = &u.u_ru.ru_stime;
512*41475Smckusick 
513*41475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
514*41475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
515*41475Smckusick 		if (ticks) {
516*41475Smckusick #ifdef PROFTIMER
517*41475Smckusick 			extern int profscale;
518*41475Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks * profscale);
519*41475Smckusick #else
520*41475Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks);
521*41475Smckusick #endif
522*41475Smckusick 		}
523*41475Smckusick 	}
524*41475Smckusick 	curpri = p->p_pri;
525*41475Smckusick }
526*41475Smckusick 
527*41475Smckusick /*
528*41475Smckusick  * Called from the trap handler when a system call occurs
529*41475Smckusick  */
530*41475Smckusick /*ARGSUSED*/
531*41475Smckusick syscall(code, frame)
532*41475Smckusick 	volatile int code;
533*41475Smckusick 	struct frame frame;
534*41475Smckusick {
535*41475Smckusick 	register caddr_t params;
536*41475Smckusick 	register int i;
537*41475Smckusick 	register struct sysent *callp;
538*41475Smckusick 	register struct proc *p;
539*41475Smckusick 	register struct user *up;
540*41475Smckusick 	int opc, numsys;
541*41475Smckusick 	struct timeval syst;
542*41475Smckusick 	struct sysent *systab;
543*41475Smckusick #ifdef HPUXCOMPAT
544*41475Smckusick 	extern struct sysent hpuxsysent[];
545*41475Smckusick 	extern int hpuxnsysent, notimp();
546*41475Smckusick #endif
547*41475Smckusick 
548*41475Smckusick 	/*
549*41475Smckusick 	 * We assign &u to a local variable for GCC.  This ensures that
550*41475Smckusick 	 * we can explicitly reload it after the call to qsetjmp below.
551*41475Smckusick 	 * If we don't do this, GCC may itself have assigned &u to a
552*41475Smckusick 	 * register variable which will not be properly reloaded, since
553*41475Smckusick 	 * GCC knows nothing of the funky semantics of qsetjmp.
554*41475Smckusick 	 */
555*41475Smckusick 	up = &u;
556*41475Smckusick 
557*41475Smckusick 	cnt.v_syscall++;
558*41475Smckusick 	syst = up->u_ru.ru_stime;
559*41475Smckusick 	if (!USERMODE(frame.f_sr))
560*41475Smckusick 		panic("syscall");
561*41475Smckusick 	up->u_ar0 = frame.f_regs;
562*41475Smckusick 	up->u_error = 0;
563*41475Smckusick 	opc = frame.f_pc - 2;
564*41475Smckusick 	systab = sysent;
565*41475Smckusick 	numsys = nsysent;
566*41475Smckusick #ifdef HPUXCOMPAT
567*41475Smckusick 	if (up->u_procp->p_flag & SHPUX) {
568*41475Smckusick 		systab = hpuxsysent;
569*41475Smckusick 		numsys = hpuxnsysent;
570*41475Smckusick 	}
571*41475Smckusick #endif
572*41475Smckusick 	params = (caddr_t)frame.f_regs[SP] + NBPW;
573*41475Smckusick 	/*
574*41475Smckusick 	 * We use entry 0 instead of 63 to signify an invalid syscall because
575*41475Smckusick 	 * HPUX uses 63 and 0 works just as well for our purposes.
576*41475Smckusick 	 */
577*41475Smckusick 	if (code == 0) {
578*41475Smckusick 		i = fuword(params);
579*41475Smckusick 		params += NBPW;
580*41475Smckusick 		callp = ((unsigned)i >= numsys) ? &systab[0] : &systab[i];
581*41475Smckusick 	} else
582*41475Smckusick 		callp = (code >= numsys) ? &systab[0] : &systab[code];
583*41475Smckusick 	p = up->u_procp;
584*41475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
585*41475Smckusick 	    (up->u_error = copyin(params, (caddr_t)up->u_arg, (u_int)i))) {
586*41475Smckusick #ifdef HPUXCOMPAT
587*41475Smckusick 		if (p->p_flag & SHPUX)
588*41475Smckusick 			up->u_error = bsdtohpuxerrno(up->u_error);
589*41475Smckusick #endif
590*41475Smckusick 		frame.f_regs[D0] = (u_char) up->u_error;
591*41475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
592*41475Smckusick #ifdef KTRACE
593*41475Smckusick                 if (KTRPOINT(p, KTR_SYSCALL))
594*41475Smckusick                         ktrsyscall(p->p_tracep, code, callp->sy_narg);
595*41475Smckusick #endif
596*41475Smckusick 		goto done;
597*41475Smckusick 	}
598*41475Smckusick #ifdef KTRACE
599*41475Smckusick         if (KTRPOINT(p, KTR_SYSCALL))
600*41475Smckusick                 ktrsyscall(p->p_tracep, code, callp->sy_narg);
601*41475Smckusick #endif
602*41475Smckusick 	up->u_r.r_val1 = 0;
603*41475Smckusick 	up->u_r.r_val2 = frame.f_regs[D0];
604*41475Smckusick 	/*
605*41475Smckusick 	 * qsetjmp only saves a6/a7.  This speeds things up in the common
606*41475Smckusick 	 * case (where saved values are never used).  There is a side effect
607*41475Smckusick 	 * however.  Namely, if we do return via longjmp() we must restore
608*41475Smckusick 	 * our own register variables.
609*41475Smckusick 	 */
610*41475Smckusick 	if (qsetjmp(&up->u_qsave)) {
611*41475Smckusick 		up = &u;
612*41475Smckusick 		if (up->u_error == 0 && up->u_eosys != RESTARTSYS)
613*41475Smckusick 			up->u_error = EINTR;
614*41475Smckusick #ifdef HPUXCOMPAT
615*41475Smckusick 		/* there are some HPUX calls where we change u_ap */
616*41475Smckusick 		if (up->u_ap != up->u_arg) {
617*41475Smckusick 			up->u_ap = up->u_arg;
618*41475Smckusick 			printf("syscall(%d): u_ap changed\n", code);
619*41475Smckusick 		}
620*41475Smckusick #endif
621*41475Smckusick 	} else {
622*41475Smckusick 		up->u_eosys = NORMALRETURN;
623*41475Smckusick #ifdef HPUXCOMPAT
624*41475Smckusick 		/* debug kludge */
625*41475Smckusick 		if (callp->sy_call == notimp)
626*41475Smckusick 			notimp(code, callp->sy_narg);
627*41475Smckusick 		else
628*41475Smckusick #endif
629*41475Smckusick 		(*(callp->sy_call))(up);
630*41475Smckusick 	}
631*41475Smckusick 	/*
632*41475Smckusick 	 * Need to reinit p for two reason.  One, it is a register var
633*41475Smckusick 	 * and is not saved in the qsetjmp so a EINTR return will leave
634*41475Smckusick 	 * it with garbage.  Two, even on a normal return, it will be
635*41475Smckusick 	 * wrong for the child process of a fork (it will point to the
636*41475Smckusick 	 * parent).
637*41475Smckusick 	 */
638*41475Smckusick 	p = up->u_procp;
639*41475Smckusick 	if (up->u_eosys == NORMALRETURN) {
640*41475Smckusick 		if (up->u_error) {
641*41475Smckusick #ifdef HPUXCOMPAT
642*41475Smckusick 			if (p->p_flag & SHPUX)
643*41475Smckusick 				up->u_error = bsdtohpuxerrno(up->u_error);
644*41475Smckusick #endif
645*41475Smckusick 			frame.f_regs[D0] = (u_char) up->u_error;
646*41475Smckusick 			frame.f_sr |= PSL_C;	/* carry bit */
647*41475Smckusick 		} else {
648*41475Smckusick 			frame.f_regs[D0] = up->u_r.r_val1;
649*41475Smckusick 			frame.f_regs[D1] = up->u_r.r_val2;
650*41475Smckusick 			frame.f_sr &= ~PSL_C;
651*41475Smckusick 		}
652*41475Smckusick 	} else if (up->u_eosys == RESTARTSYS)
653*41475Smckusick 		frame.f_pc = opc;
654*41475Smckusick 	/* else if (up->u_eosys == JUSTRETURN) */
655*41475Smckusick 		/* nothing to do */
656*41475Smckusick done:
657*41475Smckusick 	/*
658*41475Smckusick 	 * The check for sigreturn (code 103) ensures that we don't
659*41475Smckusick 	 * attempt to set up a call to a signal handler (sendsig) before
660*41475Smckusick 	 * we have cleaned up the stack from the last call (sigreturn).
661*41475Smckusick 	 * Allowing this seems to lock up the machine in certain scenarios.
662*41475Smckusick 	 * What should really be done is to clean up the signal handling
663*41475Smckusick 	 * so that this is not a problem.
664*41475Smckusick 	 */
665*41475Smckusick 	if (code != 103 && (p->p_cursig || ISSIG(p)))
666*41475Smckusick 		psig();
667*41475Smckusick 	p->p_pri = p->p_usrpri;
668*41475Smckusick 	if (runrun) {
669*41475Smckusick 		/*
670*41475Smckusick 		 * Since we are u.u_procp, clock will normally just change
671*41475Smckusick 		 * our priority without moving us from one queue to another
672*41475Smckusick 		 * (since the running process is not on a queue.)
673*41475Smckusick 		 * If that happened after we setrq ourselves but before we
674*41475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
675*41475Smckusick 		 * our priority.
676*41475Smckusick 		 */
677*41475Smckusick 		(void) splclock();
678*41475Smckusick 		setrq(p);
679*41475Smckusick 		up->u_ru.ru_nivcsw++;
680*41475Smckusick 		swtch();
681*41475Smckusick 	}
682*41475Smckusick 	if (up->u_prof.pr_scale) {
683*41475Smckusick 		int ticks;
684*41475Smckusick 		struct timeval *tv = &up->u_ru.ru_stime;
685*41475Smckusick 
686*41475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
687*41475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
688*41475Smckusick 		if (ticks) {
689*41475Smckusick #ifdef PROFTIMER
690*41475Smckusick 			extern int profscale;
691*41475Smckusick 			addupc(frame.f_pc, &up->u_prof, ticks * profscale);
692*41475Smckusick #else
693*41475Smckusick 			addupc(frame.f_pc, &up->u_prof, ticks);
694*41475Smckusick #endif
695*41475Smckusick 		}
696*41475Smckusick 	}
697*41475Smckusick 	curpri = p->p_pri;
698*41475Smckusick #ifdef KTRACE
699*41475Smckusick         if (KTRPOINT(p, KTR_SYSRET))
700*41475Smckusick                 ktrsysret(p->p_tracep, code);
701*41475Smckusick #endif
702*41475Smckusick }
703