xref: /openbsd/sys/arch/hppa/hppa/trap.c (revision e494c7cf)
1*e494c7cfSmickey /*	$OpenBSD: trap.c,v 1.17 2000/01/17 00:30:17 mickey Exp $	*/
2556d2ba7Smickey 
3556d2ba7Smickey /*
48de28e3eSmickey  * Copyright (c) 1998-2000 Michael Shalayeff
5556d2ba7Smickey  * All rights reserved.
6556d2ba7Smickey  *
7556d2ba7Smickey  * Redistribution and use in source and binary forms, with or without
8556d2ba7Smickey  * modification, are permitted provided that the following conditions
9556d2ba7Smickey  * are met:
10556d2ba7Smickey  * 1. Redistributions of source code must retain the above copyright
11556d2ba7Smickey  *    notice, this list of conditions and the following disclaimer.
12556d2ba7Smickey  * 2. Redistributions in binary form must reproduce the above copyright
13556d2ba7Smickey  *    notice, this list of conditions and the following disclaimer in the
14556d2ba7Smickey  *    documentation and/or other materials provided with the distribution.
15556d2ba7Smickey  * 3. All advertising materials mentioning features or use of this software
16556d2ba7Smickey  *    must display the following acknowledgement:
17556d2ba7Smickey  *	This product includes software developed by Michael Shalayeff.
18556d2ba7Smickey  * 4. The name of the author may not be used to endorse or promote products
19556d2ba7Smickey  *    derived from this software without specific prior written permission.
20556d2ba7Smickey  *
21556d2ba7Smickey  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22556d2ba7Smickey  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23556d2ba7Smickey  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24556d2ba7Smickey  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25556d2ba7Smickey  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26556d2ba7Smickey  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27556d2ba7Smickey  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28556d2ba7Smickey  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29556d2ba7Smickey  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30556d2ba7Smickey  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31556d2ba7Smickey  */
32556d2ba7Smickey 
33a24c0b7aSmickey #undef INTRDEBUG
34af7386c3Smickey #define TRAPDEBUG
35556d2ba7Smickey 
36556d2ba7Smickey #include <sys/param.h>
37556d2ba7Smickey #include <sys/systm.h>
38d412f1c2Smickey #include <sys/kernel.h>
39b9b95e0dSmickey #include <sys/syscall.h>
40b9b95e0dSmickey #include <sys/ktrace.h>
41d412f1c2Smickey #include <sys/proc.h>
42d412f1c2Smickey #include <sys/user.h>
43d412f1c2Smickey #include <sys/acct.h>
44d412f1c2Smickey #include <sys/signal.h>
45688a8060Smickey #include <sys/device.h>
46556d2ba7Smickey 
47af7386c3Smickey #include <net/netisr.h>
48af7386c3Smickey 
49556d2ba7Smickey #include <vm/vm.h>
508de28e3eSmickey #include <vm/vm_kern.h>
51b9b95e0dSmickey #include <uvm/uvm.h>
52556d2ba7Smickey 
53556d2ba7Smickey #include <machine/iomod.h>
54556d2ba7Smickey #include <machine/cpufunc.h>
55556d2ba7Smickey #include <machine/reg.h>
56556d2ba7Smickey #include <machine/autoconf.h>
57556d2ba7Smickey 
58137d3021Smickey #ifdef DDB
59137d3021Smickey #include <machine/db_machdep.h>
60137d3021Smickey #endif
61137d3021Smickey 
62137d3021Smickey #if defined(INTRDEBUG) || defined(TRAPDEBUG)
63137d3021Smickey #include <ddb/db_output.h>
64137d3021Smickey #endif
65137d3021Smickey 
66137d3021Smickey #define	FAULT_TYPE(op)	(VM_PROT_READ|(inst_store(op) ? VM_PROT_WRITE : 0))
67556d2ba7Smickey 
68556d2ba7Smickey const char *trap_type[] = {
69*e494c7cfSmickey 	"invalid",
70*e494c7cfSmickey 	"HPMC",
71556d2ba7Smickey 	"power failure",
72137d3021Smickey 	"recovery counter",
73556d2ba7Smickey 	"external interrupt",
74*e494c7cfSmickey 	"LPMC",
75*e494c7cfSmickey 	"ITLB miss fault",
76137d3021Smickey 	"instruction protection",
77137d3021Smickey 	"Illegal instruction",
78137d3021Smickey 	"break instruction",
79137d3021Smickey 	"privileged operation",
80137d3021Smickey 	"privileged register",
81137d3021Smickey 	"overflow",
82137d3021Smickey 	"conditional",
83137d3021Smickey 	"assist exception",
84*e494c7cfSmickey 	"DTLB miss",
85137d3021Smickey 	"ITLB non-access miss",
86137d3021Smickey 	"DTLB non-access miss",
87137d3021Smickey 	"data protection/rights/alignment",
88137d3021Smickey 	"data break",
89*e494c7cfSmickey 	"TLB dirty",
90137d3021Smickey 	"page reference",
91137d3021Smickey 	"assist emulation",
92*e494c7cfSmickey 	"higher-priv transfer",
93*e494c7cfSmickey 	"lower-priv transfer",
94137d3021Smickey 	"taken branch",
95137d3021Smickey 	"data access rights",
96*e494c7cfSmickey 	"data protection",
97137d3021Smickey 	"unaligned data ref",
98556d2ba7Smickey };
99556d2ba7Smickey int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);
100556d2ba7Smickey 
101556d2ba7Smickey u_int32_t sir;
102b9b95e0dSmickey int want_resched;
103556d2ba7Smickey 
104556d2ba7Smickey void pmap_hptdump __P((void));
105a24c0b7aSmickey void cpu_intr __P((struct trapframe *frame));
106b9b95e0dSmickey void syscall __P((struct trapframe *frame, int *args));
107556d2ba7Smickey 
108d412f1c2Smickey static __inline void
109d412f1c2Smickey userret (struct proc *p, register_t pc, u_quad_t oticks)
110d412f1c2Smickey {
111d412f1c2Smickey 	int sig;
112af7386c3Smickey 
113d412f1c2Smickey 	/* take pending signals */
114d412f1c2Smickey 	while ((sig = CURSIG(p)) != 0)
115d412f1c2Smickey 		postsig(sig);
116d412f1c2Smickey 
117d412f1c2Smickey 	p->p_priority = p->p_usrpri;
118d412f1c2Smickey 	if (want_resched) {
119d412f1c2Smickey 		register int s;
120d412f1c2Smickey 		/*
121d412f1c2Smickey 		 * Since we are curproc, a clock interrupt could
122d412f1c2Smickey 		 * change our priority without changing run queues
123d412f1c2Smickey 		 * (the running process is not kept on a run queue).
124d412f1c2Smickey 		 * If this happened after we setrunqueue ourselves but
125d412f1c2Smickey 		 * before we switch()'ed, we might not be on the queue
126d412f1c2Smickey 		 * indicated by our priority.
127d412f1c2Smickey 		 */
128d412f1c2Smickey 		s = splstatclock();
129d412f1c2Smickey 		setrunqueue(p);
130d412f1c2Smickey 		p->p_stats->p_ru.ru_nivcsw++;
131d412f1c2Smickey 		mi_switch();
132d412f1c2Smickey 		splx(s);
133d412f1c2Smickey 		while ((sig = CURSIG(p)) != 0)
134d412f1c2Smickey 			postsig(sig);
135d412f1c2Smickey 	}
136d412f1c2Smickey 
137d412f1c2Smickey 	/*
138d412f1c2Smickey 	 * If profiling, charge recent system time to the trapped pc.
139d412f1c2Smickey 	 */
140d412f1c2Smickey 	if (p->p_flag & P_PROFIL) {
141d412f1c2Smickey 		extern int psratio;
142d412f1c2Smickey 
143d412f1c2Smickey 		addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
144d412f1c2Smickey 	}
145d412f1c2Smickey 
146d412f1c2Smickey 	curpriority = p->p_priority;
147d412f1c2Smickey }
148d412f1c2Smickey 
149556d2ba7Smickey void
150556d2ba7Smickey trap(type, frame)
151556d2ba7Smickey 	int type;
152556d2ba7Smickey 	struct trapframe *frame;
153556d2ba7Smickey {
154556d2ba7Smickey 	struct proc *p = curproc;
155137d3021Smickey 	struct pcb *pcbp;
156137d3021Smickey 	register vaddr_t va;
157556d2ba7Smickey 	register vm_map_t map;
158f17fa196Smickey 	struct vmspace *vm;
159af7386c3Smickey 	register vm_prot_t vftype;
160556d2ba7Smickey 	register pa_space_t space;
161a24c0b7aSmickey 	u_int opcode;
162556d2ba7Smickey 	int ret;
163af7386c3Smickey 	union sigval sv;
164a24c0b7aSmickey 	int s, si;
165137d3021Smickey 	const char *tts;
166556d2ba7Smickey 
167137d3021Smickey 	opcode = frame->tf_iir;
168a24c0b7aSmickey 	if (type == T_ITLBMISS || type == T_ITLBMISSNA) {
169a24c0b7aSmickey 		va = frame->tf_iioq_head;
170a24c0b7aSmickey 		space = frame->tf_iisq_head;
171137d3021Smickey 		vftype = VM_PROT_EXECUTE;
172a24c0b7aSmickey 	} else {
173b9b95e0dSmickey 		va = frame->tf_ior;
174a24c0b7aSmickey 		space = frame->tf_isr;
175af7386c3Smickey 		vftype = FAULT_TYPE(opcode);
176556d2ba7Smickey 	}
177137d3021Smickey 
178137d3021Smickey 	if (frame->tf_flags & TFF_LAST)
179137d3021Smickey 		p->p_md.md_regs = frame;
180137d3021Smickey 
181af7386c3Smickey #ifdef TRAPDEBUG
182137d3021Smickey 	if ((type & ~T_USER) > trap_types)
183137d3021Smickey 		tts = "reserved";
184137d3021Smickey 	else
185137d3021Smickey 		tts = trap_type[type & ~T_USER];
186137d3021Smickey 
187*e494c7cfSmickey 	if (type != T_INTERRUPT && (type & ~T_USER) != T_IBREAK)
188137d3021Smickey 		db_printf("trap: %d, %s for %x:%x at %x:%x, fl=%x, fp=%p\n",
189137d3021Smickey 		    type, tts, space, va, frame->tf_iisq_head,
190137d3021Smickey 		    frame->tf_iioq_head, frame->tf_flags, frame);
191a24c0b7aSmickey 	else if ((type & ~T_USER) == T_IBREAK)
192137d3021Smickey 		db_printf("trap: break instruction %x:%x at %x:%x, fp=%p\n",
193a24c0b7aSmickey 		    break5(opcode), break13(opcode),
194137d3021Smickey 		    frame->tf_iisq_head, frame->tf_iioq_head, frame);
195*e494c7cfSmickey 
196*e494c7cfSmickey 	{
197*e494c7cfSmickey 		extern int etext;
198*e494c7cfSmickey 		if (frame < (struct trapframe *)&etext)
199*e494c7cfSmickey 			goto dead_end;
200*e494c7cfSmickey 	}
201d412f1c2Smickey #endif
202556d2ba7Smickey 	switch (type) {
203556d2ba7Smickey 	case T_NONEXIST:
204556d2ba7Smickey 	case T_NONEXIST|T_USER:
205137d3021Smickey #ifndef DDB
206af7386c3Smickey 		/* we've got screwed up by the central scrutinizer */
207137d3021Smickey 		panic ("trap: elvis has just left the building!");
208556d2ba7Smickey 		break;
209137d3021Smickey #endif
210556d2ba7Smickey 	case T_RECOVERY:
211556d2ba7Smickey 	case T_RECOVERY|T_USER:
212137d3021Smickey #ifndef DDB
213af7386c3Smickey 		/* XXX will implement later */
214556d2ba7Smickey 		printf ("trap: handicapped");
215556d2ba7Smickey 		break;
216d412f1c2Smickey #endif
21766d1ab7aSmickey 
21866d1ab7aSmickey #ifdef DIAGNOSTIC
21966d1ab7aSmickey 	case T_EXCEPTION:
22066d1ab7aSmickey 		panic("FPU/SFU emulation botch");
22166d1ab7aSmickey 
22266d1ab7aSmickey 		/* these just can't happen ever */
22366d1ab7aSmickey 	case T_PRIV_OP:
22466d1ab7aSmickey 	case T_PRIV_REG:
22566d1ab7aSmickey 		/* these just can't make it to the trap() ever */
22666d1ab7aSmickey 	case T_HPMC:      case T_HPMC | T_USER:
22766d1ab7aSmickey 	case T_EMULATION: case T_EMULATION | T_USER:
22866d1ab7aSmickey 	case T_TLB_DIRTY: case T_TLB_DIRTY | T_USER:
22966d1ab7aSmickey #endif
230f4daacd8Smickey 	case T_IBREAK:
231a24c0b7aSmickey 	case T_DATALIGN:
232a24c0b7aSmickey 	case T_DBREAK:
2338de28e3eSmickey 	dead_end:
234a24c0b7aSmickey #ifdef DDB
235a24c0b7aSmickey 		if (kdb_trap (type, 0, frame)) {
236a24c0b7aSmickey 			if (type == T_IBREAK) {
237f4daacd8Smickey 				/* skip break instruction */
2388de28e3eSmickey 				frame->tf_iioq_head = frame->tf_iioq_tail;
239f4daacd8Smickey 				frame->tf_iioq_tail += 4;
240a24c0b7aSmickey 			}
241556d2ba7Smickey 			return;
242a24c0b7aSmickey 		}
243137d3021Smickey #else
244137d3021Smickey 		if (type == T_DATALIGN)
245137d3021Smickey 			panic ("trap: %s at 0x%x", tts, va);
246137d3021Smickey 		else
247137d3021Smickey 			panic ("trap: no debugger for \"%s\" (%d)", tts, type);
248a24c0b7aSmickey #endif
249556d2ba7Smickey 		break;
250556d2ba7Smickey 
251af7386c3Smickey 	case T_IBREAK | T_USER:
252af7386c3Smickey 	case T_DBREAK | T_USER:
253af7386c3Smickey 		/* pass to user debugger */
254d412f1c2Smickey 		break;
255d412f1c2Smickey 
256af7386c3Smickey 	case T_EXCEPTION | T_USER:	/* co-proc assist trap */
257137d3021Smickey 		sv.sival_int = va;
258af7386c3Smickey 		trapsignal(p, SIGFPE, type &~ T_USER, FPE_FLTINV, sv);
259d412f1c2Smickey 		break;
260d412f1c2Smickey 
261af7386c3Smickey 	case T_OVERFLOW | T_USER:
262137d3021Smickey 		sv.sival_int = va;
263af7386c3Smickey 		trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
264d412f1c2Smickey 		break;
265d412f1c2Smickey 
266af7386c3Smickey 	case T_CONDITION | T_USER:
267af7386c3Smickey 		break;
268af7386c3Smickey 
269af7386c3Smickey 	case T_ILLEGAL | T_USER:
270137d3021Smickey 		sv.sival_int = va;
271af7386c3Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv);
272af7386c3Smickey 		break;
273af7386c3Smickey 
274af7386c3Smickey 	case T_PRIV_OP | T_USER:
275137d3021Smickey 		sv.sival_int = va;
276af7386c3Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv);
277af7386c3Smickey 		break;
278af7386c3Smickey 
279af7386c3Smickey 	case T_PRIV_REG | T_USER:
280137d3021Smickey 		sv.sival_int = va;
281af7386c3Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv);
282af7386c3Smickey 		break;
283af7386c3Smickey 
284af7386c3Smickey 		/* these should never got here */
285af7386c3Smickey 	case T_HIGHERPL | T_USER:
286af7386c3Smickey 	case T_LOWERPL | T_USER:
287137d3021Smickey 		sv.sival_int = va;
288af7386c3Smickey 		trapsignal(p, SIGSEGV, type &~ T_USER, SEGV_ACCERR, sv);
289af7386c3Smickey 		break;
290af7386c3Smickey 
291af7386c3Smickey 	case T_IPROT | T_USER:
292af7386c3Smickey 	case T_DPROT | T_USER:
293af7386c3Smickey 		sv.sival_int = va;
294af7386c3Smickey 		trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
295af7386c3Smickey 		break;
296af7386c3Smickey 
297af7386c3Smickey 	case T_DPROT:
298137d3021Smickey 	case T_IPROT:
299137d3021Smickey 	case T_DATACC:   	case T_DATACC   | T_USER:
300137d3021Smickey 	case T_ITLBMISS:	case T_ITLBMISS | T_USER:
301137d3021Smickey 	case T_DTLBMISS:	case T_DTLBMISS | T_USER:
302137d3021Smickey 	case T_ITLBMISSNA:	case T_ITLBMISSNA | T_USER:
303137d3021Smickey 	case T_DTLBMISSNA:	case T_DTLBMISSNA | T_USER:
304556d2ba7Smickey 		va = trunc_page(va);
305f17fa196Smickey 		vm = p->p_vmspace;
3068de28e3eSmickey 
3078de28e3eSmickey 		if (!vm)
3088de28e3eSmickey 			goto dead_end;
3098de28e3eSmickey 
3108de28e3eSmickey 		/*
311*e494c7cfSmickey 		 * it could be a kernel map for exec_map faults
3128de28e3eSmickey 		 */
3138de28e3eSmickey 		if (!(type & T_USER) && space == HPPA_SID_KERNEL)
3148de28e3eSmickey 			map = kernel_map;
3158de28e3eSmickey 		else
316f17fa196Smickey 			map = &vm->vm_map;
317556d2ba7Smickey 
318137d3021Smickey 		ret = uvm_fault(map, va, 0, vftype);
319f17fa196Smickey 
320f17fa196Smickey 		/*
321f17fa196Smickey 		 * If this was a stack access we keep track of the maximum
322f17fa196Smickey 		 * accessed stack size.  Also, if uvm_fault gets a protection
323f17fa196Smickey 		 * failure it is due to accessing the stack region outside
324f17fa196Smickey 		 * the current limit and we need to reflect that as an access
325f17fa196Smickey 		 * error.
326f17fa196Smickey 		 */
327f17fa196Smickey 		if (va >= (vaddr_t)vm->vm_maxsaddr + vm->vm_ssize) {
328f17fa196Smickey 			if (ret == KERN_SUCCESS) {
329f17fa196Smickey 				vsize_t nss = clrnd(btoc(va - USRSTACK + NBPG));
330f17fa196Smickey 				if (nss > vm->vm_ssize)
331f17fa196Smickey 					vm->vm_ssize = nss;
332f17fa196Smickey 			} else if (ret == KERN_PROTECTION_FAILURE)
333f17fa196Smickey 				ret = KERN_INVALID_ADDRESS;
334f17fa196Smickey 		}
335f17fa196Smickey 
336af7386c3Smickey 		if (ret != KERN_SUCCESS) {
337af7386c3Smickey 			if (type & T_USER) {
338137d3021Smickey printf("trapsignal: uvm_fault\n");
339af7386c3Smickey 				sv.sival_int = frame->tf_ior;
340af7386c3Smickey 				trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv);
341137d3021Smickey 			} else {
3428de28e3eSmickey 				if (p && p->p_addr->u_pcb.pcb_onfault) {
3438de28e3eSmickey #ifdef PMAPDEBUG
3448de28e3eSmickey 					printf("trap: copyin/out %d\n",ret);
345137d3021Smickey #endif
3468de28e3eSmickey 					pcbp = &p->p_addr->u_pcb;
3478de28e3eSmickey 					frame->tf_iioq_tail = 4 +
3488de28e3eSmickey 					    (frame->tf_iioq_head =
3498de28e3eSmickey 						pcbp->pcb_onfault);
350137d3021Smickey 					pcbp->pcb_onfault = 0;
351137d3021Smickey 					break;
352af7386c3Smickey 				}
353137d3021Smickey #if 1
354137d3021Smickey if (kdb_trap (type, 0, frame))
355137d3021Smickey 	return;
356137d3021Smickey #else
357137d3021Smickey 				panic("trap: uvm_fault(%p, %x, %d, %d): %d",
3582191603aSmickey 				    map, va, 0, vftype, ret);
359137d3021Smickey #endif
360137d3021Smickey 			}
361137d3021Smickey 		}
362137d3021Smickey if (type == (T_DATACC|T_USER) && kdb_trap (type, 0, frame))
363137d3021Smickey 	return;
364556d2ba7Smickey 		break;
365d412f1c2Smickey 
366af7386c3Smickey 	case T_DATALIGN | T_USER:
367137d3021Smickey 		sv.sival_int = va;
368af7386c3Smickey 		trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv);
369af7386c3Smickey 		break;
370af7386c3Smickey 
371a24c0b7aSmickey 	case T_INTERRUPT:
372a24c0b7aSmickey 	case T_INTERRUPT|T_USER:
373a24c0b7aSmickey 		cpu_intr(frame);
374137d3021Smickey #if 0
375137d3021Smickey if (kdb_trap (type, 0, frame))
376137d3021Smickey return;
377137d3021Smickey #endif
378a24c0b7aSmickey 		/* FALLTHROUGH */
379af7386c3Smickey 	case T_LOWERPL:
380a24c0b7aSmickey 		__asm __volatile ("ldcws 0(%1), %0"
381a24c0b7aSmickey 				  : "=r" (si) : "r" (&sir));
382af7386c3Smickey 		s = spl0();
383a24c0b7aSmickey 		if (si & SIR_CLOCK) {
384af7386c3Smickey 			splclock();
385af7386c3Smickey 			softclock();
386af7386c3Smickey 			spl0();
387af7386c3Smickey 		}
388af7386c3Smickey 
389a24c0b7aSmickey 		if (si & SIR_NET) {
390af7386c3Smickey 			register int ni;
391af7386c3Smickey 			/* use atomic "load & clear" */
392af7386c3Smickey 			__asm __volatile ("ldcws 0(%1), %0"
393af7386c3Smickey 					  : "=r" (ni) : "r" (&netisr));
394af7386c3Smickey 			splnet();
395a24c0b7aSmickey #define	DONET(m,c) if (ni & (1 << (m))) c()
396a24c0b7aSmickey #include "ether.h"
397af7386c3Smickey #if NETHER > 0
398af7386c3Smickey 			DONET(NETISR_ARP, arpintr);
399af7386c3Smickey #endif
400af7386c3Smickey #ifdef INET
401af7386c3Smickey 			DONET(NETISR_IP, ipintr);
402af7386c3Smickey #endif
403af7386c3Smickey #ifdef INET6
4040f823a0bSmickey 			DONET(NETISR_IPV6, ip6intr);
405af7386c3Smickey #endif
406af7386c3Smickey #ifdef NETATALK
407af7386c3Smickey 			DONET(NETISR_ATALK, atintr);
408af7386c3Smickey #endif
409af7386c3Smickey #ifdef IMP
410af7386c3Smickey 			DONET(NETISR_IMP, impintr);
411af7386c3Smickey #endif
412af7386c3Smickey #ifdef IPX
413af7386c3Smickey 			DONET(NETISR_IPX, ipxintr);
414af7386c3Smickey #endif
415af7386c3Smickey #ifdef NS
416af7386c3Smickey 			DONET(NETISR_NS, nsintr);
417af7386c3Smickey #endif
418af7386c3Smickey #ifdef ISO
419af7386c3Smickey 			DONET(NETISR_ISO, clnlintr);
420af7386c3Smickey #endif
421af7386c3Smickey #ifdef CCITT
422af7386c3Smickey 			DONET(NETISR_CCITT, ccittintr);
423af7386c3Smickey #endif
424af7386c3Smickey #ifdef NATM
425af7386c3Smickey 			DONET(NETISR_NATM, natmintr);
426af7386c3Smickey #endif
427af7386c3Smickey #include "ppp.h"
428af7386c3Smickey #if NPPP > 0
429af7386c3Smickey 			DONET(NETISR_PPP, pppintr);
430af7386c3Smickey #endif
431af7386c3Smickey #include "bridge.h"
432af7386c3Smickey #if NBRIDGE > 0
433af7386c3Smickey 			DONET(NETISR_BRIDGE, bridgeintr)
434af7386c3Smickey #endif
435af7386c3Smickey 		}
436af7386c3Smickey 		splx(s);
437af7386c3Smickey 		break;
438af7386c3Smickey 
439af7386c3Smickey 	case T_OVERFLOW:
440af7386c3Smickey 	case T_CONDITION:
441af7386c3Smickey 	case T_ILLEGAL:
442af7386c3Smickey 	case T_HIGHERPL:
443af7386c3Smickey 	case T_TAKENBR:
444af7386c3Smickey 	case T_POWERFAIL:
445af7386c3Smickey 	case T_LPMC:
446af7386c3Smickey 	case T_PAGEREF:
447d412f1c2Smickey 	case T_DATAPID:  	case T_DATAPID  | T_USER:
448d412f1c2Smickey 		if (0 /* T-chip */) {
449d412f1c2Smickey 			break;
450556d2ba7Smickey 		}
451d412f1c2Smickey 		/* FALLTHROUGH to unimplemented */
452d412f1c2Smickey 	default:
453137d3021Smickey #if 1
454137d3021Smickey if (kdb_trap (type, 0, frame))
455137d3021Smickey 	return;
456137d3021Smickey #endif
457137d3021Smickey 		panic ("trap: unimplemented \'%s\' (%d)", tts, type);
458d412f1c2Smickey 	}
459af7386c3Smickey 
460af7386c3Smickey 	if (type & T_USER)
461af7386c3Smickey 		userret(p, p->p_md.md_regs->tf_iioq_head, 0);
462d412f1c2Smickey }
463d412f1c2Smickey 
464d412f1c2Smickey void
465d412f1c2Smickey child_return(p)
466d412f1c2Smickey 	struct proc *p;
467d412f1c2Smickey {
468d412f1c2Smickey 	userret(p, p->p_md.md_regs->tf_iioq_head, 0);
469d412f1c2Smickey #ifdef KTRACE
470d412f1c2Smickey 	if (KTRPOINT(p, KTR_SYSRET))
471d412f1c2Smickey 		ktrsysret(p->p_tracep, SYS_fork, 0, 0);
472d412f1c2Smickey #endif
473556d2ba7Smickey }
474556d2ba7Smickey 
475b9b95e0dSmickey /*
476b9b95e0dSmickey  * call actual syscall routine
477b9b95e0dSmickey  * from the low-level syscall handler:
478b9b95e0dSmickey  * - all HPPA_FRAME_NARGS syscall's arguments supposed to be copied onto
479b9b95e0dSmickey  *   our stack, this wins compared to copyin just needed amount anyway
480b9b95e0dSmickey  * - register args are copied onto stack too
481b9b95e0dSmickey  */
482b9b95e0dSmickey void
483b9b95e0dSmickey syscall(frame, args)
484b9b95e0dSmickey 	struct trapframe *frame;
485b9b95e0dSmickey 	int *args;
486b9b95e0dSmickey {
487b9b95e0dSmickey 	register struct proc *p;
488b9b95e0dSmickey 	register const struct sysent *callp;
489b9b95e0dSmickey 	int nsys, code, argsize, error;
490b9b95e0dSmickey 	int rval[2];
491b9b95e0dSmickey 
492b9b95e0dSmickey 	uvmexp.syscalls++;
493b9b95e0dSmickey 
494b9b95e0dSmickey 	if (!USERMODE(frame->tf_iioq_head))
495b9b95e0dSmickey 		panic("syscall");
496b9b95e0dSmickey 
497b9b95e0dSmickey 	p = curproc;
498137d3021Smickey 	p->p_md.md_regs = frame;
499b9b95e0dSmickey 	nsys = p->p_emul->e_nsysent;
500b9b95e0dSmickey 	callp = p->p_emul->e_sysent;
501137d3021Smickey 	code = frame->tf_t1;
502b9b95e0dSmickey 	switch (code) {
503b9b95e0dSmickey 	case SYS_syscall:
504137d3021Smickey 		code = frame->tf_arg0;
505b9b95e0dSmickey 		args += 1;
506b9b95e0dSmickey 		break;
507b9b95e0dSmickey 	case SYS___syscall:
508b9b95e0dSmickey 		if (callp != sysent)
509b9b95e0dSmickey 			break;
510137d3021Smickey 		code = frame->tf_arg0; /* XXX or arg1? */
511b9b95e0dSmickey 		args += 2;
512b9b95e0dSmickey 	}
513b9b95e0dSmickey 
514b9b95e0dSmickey 	if (code < 0 || code >= nsys)
515b9b95e0dSmickey 		callp += p->p_emul->e_nosys;	/* bad syscall # */
516b9b95e0dSmickey 	else
517b9b95e0dSmickey 		callp += code;
518b9b95e0dSmickey 	argsize = callp->sy_argsize;
519b9b95e0dSmickey 
520b9b95e0dSmickey #ifdef SYSCALL_DEBUG
521b9b95e0dSmickey 	scdebug_call(p, code, args);
522b9b95e0dSmickey #endif
523b9b95e0dSmickey #ifdef KTRACE
524b9b95e0dSmickey 	if (KTRPOINT(p, KTR_SYSCALL))
525b9b95e0dSmickey 		ktrsyscall(p->p_tracep, code, argsize, args);
526b9b95e0dSmickey #endif
527b9b95e0dSmickey 
528b9b95e0dSmickey 	rval[0] = 0;
529b9b95e0dSmickey 	rval[1] = 0;
530b9b95e0dSmickey 	switch (error = (*callp->sy_call)(p, args, rval)) {
531b9b95e0dSmickey 	case 0:
532137d3021Smickey 		/* curproc may change inside the fork() */
533b9b95e0dSmickey 		frame->tf_ret0 = rval[0];
534b9b95e0dSmickey 		frame->tf_ret1 = rval[1];
535137d3021Smickey 		frame->tf_t1 = 0;
536b9b95e0dSmickey 		break;
537b9b95e0dSmickey 	case ERESTART:
538b9b95e0dSmickey 		frame->tf_iioq_head -= 4; /* right? XXX */
539b9b95e0dSmickey 		break;
540b9b95e0dSmickey 	case EJUSTRETURN:
541b9b95e0dSmickey 		break;
542b9b95e0dSmickey 	default:
543b9b95e0dSmickey 		if (p->p_emul->e_errno)
544b9b95e0dSmickey 			error = p->p_emul->e_errno[error];
545137d3021Smickey 		frame->tf_t1 = error;
546b9b95e0dSmickey 		break;
547b9b95e0dSmickey 	}
548137d3021Smickey 	p = curproc;
549b9b95e0dSmickey #ifdef SYSCALL_DEBUG
550b9b95e0dSmickey 	scdebug_ret(p, code, error, rval);
551b9b95e0dSmickey #endif
552137d3021Smickey 	userret(p, p->p_md.md_regs->tf_iioq_head, 0);
553b9b95e0dSmickey #ifdef KTRACE
554b9b95e0dSmickey 	if (KTRPOINT(p, KTR_SYSRET))
555b9b95e0dSmickey 		ktrsysret(p->p_tracep, code, error, rval[0]);
556b9b95e0dSmickey #endif
557b9b95e0dSmickey }
558b9b95e0dSmickey 
559556d2ba7Smickey /* all the interrupts, minus cpu clock, which is the last */
560556d2ba7Smickey struct cpu_intr_vector {
5613a81311eSmickey 	struct evcnt evcnt;
562556d2ba7Smickey 	int pri;
563556d2ba7Smickey 	int (*handler) __P((void *));
564556d2ba7Smickey 	void *arg;
565a24c0b7aSmickey } cpu_intr_vectors[CPU_NINTS];
566556d2ba7Smickey 
567b9b95e0dSmickey void *
5683a81311eSmickey cpu_intr_establish(pri, irq, handler, arg, dv)
569b9b95e0dSmickey 	int pri, irq;
570556d2ba7Smickey 	int (*handler) __P((void *));
571556d2ba7Smickey 	void *arg;
5723a81311eSmickey 	struct device *dv;
573556d2ba7Smickey {
5743a81311eSmickey 	register struct cpu_intr_vector *iv;
575556d2ba7Smickey 
576a24c0b7aSmickey 	if (0 <= irq && irq < CPU_NINTS && cpu_intr_vectors[irq].handler)
577b9b95e0dSmickey 		return NULL;
578556d2ba7Smickey 
5793a81311eSmickey 	iv = &cpu_intr_vectors[irq];
5803a81311eSmickey 	iv->pri = pri;
5813a81311eSmickey 	iv->handler = handler;
5823a81311eSmickey 	iv->arg = arg;
583688a8060Smickey 	evcnt_attach(dv, dv->dv_xname, &iv->evcnt);
584556d2ba7Smickey 
585688a8060Smickey 	return iv;
586556d2ba7Smickey }
587556d2ba7Smickey 
588556d2ba7Smickey void
589a24c0b7aSmickey cpu_intr(frame)
590556d2ba7Smickey 	struct trapframe *frame;
591556d2ba7Smickey {
592b9b95e0dSmickey 	u_int32_t eirr;
5933a81311eSmickey 	register struct cpu_intr_vector *iv;
594556d2ba7Smickey 	register int bit;
595556d2ba7Smickey 
596556d2ba7Smickey 	do {
597b9b95e0dSmickey 		mfctl(CR_EIRR, eirr);
598a24c0b7aSmickey 		eirr &= frame->tf_eiem;
599b9b95e0dSmickey 		bit = ffs(eirr) - 1;
600556d2ba7Smickey 		if (bit >= 0) {
601556d2ba7Smickey 			mtctl(1 << bit, CR_EIRR);
602b9b95e0dSmickey 			eirr &= ~(1 << bit);
603b9b95e0dSmickey 			/* ((struct iomod *)cpu_gethpa(0))->io_eir = 0; */
604556d2ba7Smickey #ifdef INTRDEBUG
605a24c0b7aSmickey 			if (bit != 31)
606137d3021Smickey 				db_printf ("cpu_intr: 0x%08x\n", (1 << bit));
607556d2ba7Smickey #endif
6083a81311eSmickey 			iv = &cpu_intr_vectors[bit];
6093a81311eSmickey 			if (iv->handler) {
610688a8060Smickey 				register int s, r;
6113a81311eSmickey 
6123a81311eSmickey 				iv->evcnt.ev_count++;
613688a8060Smickey 				s = splx(iv->pri);
6147cd4d71fSmickey 				/* no arg means pass the frame */
615688a8060Smickey 				r = (iv->handler)(iv->arg? iv->arg:frame);
616688a8060Smickey 				splx(s);
6177cd4d71fSmickey #ifdef DEBUG
618688a8060Smickey 				if (!r)
619137d3021Smickey 					db_printf ("%s: can't handle interrupt\n",
620688a8060Smickey 						   iv->evcnt.ev_name);
621b9b95e0dSmickey #endif
6227cd4d71fSmickey 			} else
623137d3021Smickey 				db_printf ("cpu_intr: stray interrupt %d\n", bit);
624b9b95e0dSmickey 		}
625b9b95e0dSmickey 	} while (eirr);
626556d2ba7Smickey }
627