xref: /original-bsd/sys/news3400/news3400/trap.c (revision 56185310)
1b2535c44Smckusick /*
2b2535c44Smckusick  * Copyright (c) 1988 University of Utah.
3408b3329Sbostic  * Copyright (c) 1992, 1993
4408b3329Sbostic  *	The Regents of the University of California.  All rights reserved.
5b2535c44Smckusick  *
6b2535c44Smckusick  * This code is derived from software contributed to Berkeley by
7b2535c44Smckusick  * the Systems Programming Group of the University of Utah Computer
8b2535c44Smckusick  * Science Department, Ralph Campbell, Sony Corp. and Kazumasa Utashiro
9b2535c44Smckusick  * of Software Research Associates, Inc.
10b2535c44Smckusick  *
11b2535c44Smckusick  * %sccs.include.redist.c%
12b2535c44Smckusick  *
13b2535c44Smckusick  * from: Utah $Hdr: trap.c 1.32 91/04/06$
14b2535c44Smckusick  *
15*56185310Sbostic  *	@(#)trap.c	8.4 (Berkeley) 09/23/93
16b2535c44Smckusick  */
17b2535c44Smckusick 
18a4eab072Sutashiro #include <sys/param.h>
19a4eab072Sutashiro #include <sys/systm.h>
20a4eab072Sutashiro #include <sys/proc.h>
21a4eab072Sutashiro #include <sys/kernel.h>
22a4eab072Sutashiro #include <sys/signalvar.h>
23a4eab072Sutashiro #include <sys/syscall.h>
24a4eab072Sutashiro #include <sys/user.h>
25a4eab072Sutashiro #include <sys/buf.h>
26b2535c44Smckusick #ifdef KTRACE
27a4eab072Sutashiro #include <sys/ktrace.h>
28b2535c44Smckusick #endif
29a4eab072Sutashiro #include <net/netisr.h>
30b2535c44Smckusick 
31a4eab072Sutashiro #include <machine/trap.h>
32a4eab072Sutashiro #include <machine/psl.h>
33a4eab072Sutashiro #include <machine/reg.h>
34a4eab072Sutashiro #include <machine/cpu.h>
35a4eab072Sutashiro #include <machine/pte.h>
36a4eab072Sutashiro #include <machine/mips_opcode.h>
37a4eab072Sutashiro #include <machine/adrsmap.h>
38b2535c44Smckusick 
39a4eab072Sutashiro #include <vm/vm.h>
40a4eab072Sutashiro #include <vm/vm_kern.h>
41a4eab072Sutashiro #include <vm/vm_page.h>
42b2535c44Smckusick 
43b2535c44Smckusick #include "lp.h"
44b2535c44Smckusick #include "bm.h"
45b2535c44Smckusick #include "ms.h"
46b2535c44Smckusick #include "en.h"
47a4eab072Sutashiro #include <news3400/hbdev/dmac_0448.h>
48a4eab072Sutashiro #include <news3400/sio/scc.h>
49b2535c44Smckusick 
50b2535c44Smckusick struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */
51b2535c44Smckusick 
52b2535c44Smckusick extern void MachKernGenException();
53b2535c44Smckusick extern void MachUserGenException();
54b2535c44Smckusick extern void MachKernIntr();
55b2535c44Smckusick extern void MachUserIntr();
56b2535c44Smckusick extern void MachTLBModException();
57b2535c44Smckusick extern void MachTLBMissException();
58b2535c44Smckusick extern unsigned MachEmulateBranch();
59b2535c44Smckusick 
60b2535c44Smckusick void (*machExceptionTable[])() = {
61b2535c44Smckusick /*
62b2535c44Smckusick  * The kernel exception handlers.
63b2535c44Smckusick  */
64b2535c44Smckusick 	MachKernIntr,			/* external interrupt */
65b2535c44Smckusick 	MachKernGenException,		/* TLB modification */
66b2535c44Smckusick 	MachTLBMissException,		/* TLB miss (load or instr. fetch) */
67b2535c44Smckusick 	MachTLBMissException,		/* TLB miss (store) */
68b2535c44Smckusick 	MachKernGenException,		/* address error (load or I-fetch) */
69b2535c44Smckusick 	MachKernGenException,		/* address error (store) */
70b2535c44Smckusick 	MachKernGenException,		/* bus error (I-fetch) */
71b2535c44Smckusick 	MachKernGenException,		/* bus error (load or store) */
72b2535c44Smckusick 	MachKernGenException,		/* system call */
73b2535c44Smckusick 	MachKernGenException,		/* breakpoint */
74b2535c44Smckusick 	MachKernGenException,		/* reserved instruction */
75b2535c44Smckusick 	MachKernGenException,		/* coprocessor unusable */
76b2535c44Smckusick 	MachKernGenException,		/* arithmetic overflow */
77b2535c44Smckusick 	MachKernGenException,		/* reserved */
78b2535c44Smckusick 	MachKernGenException,		/* reserved */
79b2535c44Smckusick 	MachKernGenException,		/* reserved */
80b2535c44Smckusick /*
81b2535c44Smckusick  * The user exception handlers.
82b2535c44Smckusick  */
83b2535c44Smckusick 	MachUserIntr,
84b2535c44Smckusick 	MachUserGenException,
85b2535c44Smckusick 	MachUserGenException,
86b2535c44Smckusick 	MachUserGenException,
87b2535c44Smckusick 	MachUserGenException,
88b2535c44Smckusick 	MachUserGenException,
89b2535c44Smckusick 	MachUserGenException,
90b2535c44Smckusick 	MachUserGenException,
91b2535c44Smckusick 	MachUserGenException,
92b2535c44Smckusick 	MachUserGenException,
93b2535c44Smckusick 	MachUserGenException,
94b2535c44Smckusick 	MachUserGenException,
95b2535c44Smckusick 	MachUserGenException,
96b2535c44Smckusick 	MachUserGenException,
97b2535c44Smckusick 	MachUserGenException,
98b2535c44Smckusick 	MachUserGenException,
99b2535c44Smckusick };
100b2535c44Smckusick 
101b2535c44Smckusick char	*trap_type[] = {
102b2535c44Smckusick 	"external interrupt",
103b2535c44Smckusick 	"TLB modification",
104b2535c44Smckusick 	"TLB miss (load or instr. fetch)",
105b2535c44Smckusick 	"TLB miss (store)",
106b2535c44Smckusick 	"address error (load or I-fetch)",
107b2535c44Smckusick 	"address error (store)",
108b2535c44Smckusick 	"bus error (I-fetch)",
109b2535c44Smckusick 	"bus error (load or store)",
110b2535c44Smckusick 	"system call",
111b2535c44Smckusick 	"breakpoint",
112b2535c44Smckusick 	"reserved instruction",
113b2535c44Smckusick 	"coprocessor unusable",
114b2535c44Smckusick 	"arithmetic overflow",
115b2535c44Smckusick 	"reserved 13",
116b2535c44Smckusick 	"reserved 14",
117b2535c44Smckusick 	"reserved 15",
118b2535c44Smckusick };
119b2535c44Smckusick 
120b2535c44Smckusick #ifdef DEBUG
121b2535c44Smckusick #define TRAPSIZE	10
122b2535c44Smckusick struct trapdebug {		/* trap history buffer for debugging */
123b2535c44Smckusick 	u_int	status;
124b2535c44Smckusick 	u_int	cause;
125b2535c44Smckusick 	u_int	vadr;
126b2535c44Smckusick 	u_int	pc;
127b2535c44Smckusick 	u_int	ra;
128b2535c44Smckusick 	u_int	code;
129b2535c44Smckusick } trapdebug[TRAPSIZE], *trp = trapdebug;
130b2535c44Smckusick #endif
131b2535c44Smckusick 
132b2535c44Smckusick /*
133b2535c44Smckusick  * Handle an exception.
134b2535c44Smckusick  * Called from MachKernGenException() or MachUserGenException()
135b2535c44Smckusick  * when a processor trap occurs.
136b2535c44Smckusick  * In the case of a kernel trap, we return the pc where to resume if
137b2535c44Smckusick  * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
138b2535c44Smckusick  */
139b2535c44Smckusick unsigned
trap(statusReg,causeReg,vadr,pc,args)140b2535c44Smckusick trap(statusReg, causeReg, vadr, pc, args)
141b2535c44Smckusick 	unsigned statusReg;	/* status register at time of the exception */
142b2535c44Smckusick 	unsigned causeReg;	/* cause register at time of exception */
143b2535c44Smckusick 	unsigned vadr;		/* address (if any) the fault occured on */
144b2535c44Smckusick 	unsigned pc;		/* program counter where to continue */
145b2535c44Smckusick {
146b2535c44Smckusick 	register int type, i;
147b2535c44Smckusick 	unsigned ucode = 0;
148b2535c44Smckusick 	register struct proc *p = curproc;
14918e6ce8eSbostic 	u_quad_t sticks;
150b2535c44Smckusick 	vm_prot_t ftype;
151b2535c44Smckusick 	extern unsigned onfault_table[];
152b2535c44Smckusick 
153b2535c44Smckusick #ifdef DEBUG
154b2535c44Smckusick 	trp->status = statusReg;
155b2535c44Smckusick 	trp->cause = causeReg;
156b2535c44Smckusick 	trp->vadr = vadr;
157b2535c44Smckusick 	trp->pc = pc;
158b2535c44Smckusick 	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
159b2535c44Smckusick 		p->p_md.md_regs[RA];
160b2535c44Smckusick 	trp->code = 0;
161b2535c44Smckusick 	if (++trp == &trapdebug[TRAPSIZE])
162b2535c44Smckusick 		trp = trapdebug;
163b2535c44Smckusick #endif
164b2535c44Smckusick 
165b2535c44Smckusick 	cnt.v_trap++;
166b2535c44Smckusick 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
167b2535c44Smckusick 	if (USERMODE(statusReg)) {
168b2535c44Smckusick 		type |= T_USER;
16918e6ce8eSbostic 		sticks = p->p_sticks;
170b2535c44Smckusick 	}
171b2535c44Smckusick 
172b2535c44Smckusick 	/*
173b2535c44Smckusick 	 * Enable hardware interrupts if they were on before.
174b2535c44Smckusick 	 * We only respond to software interrupts when returning to user mode.
175b2535c44Smckusick 	 */
176b2535c44Smckusick 	if (statusReg & MACH_SR_INT_ENA_PREV)
177b2535c44Smckusick 		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);
178b2535c44Smckusick 
179b2535c44Smckusick 	switch (type) {
180b2535c44Smckusick 	case T_TLB_MOD:
18118e6ce8eSbostic 		/* check for kernel address */
182b2535c44Smckusick 		if ((int)vadr < 0) {
183b2535c44Smckusick 			register pt_entry_t *pte;
184b2535c44Smckusick 			register unsigned entry;
185b2535c44Smckusick 			register vm_offset_t pa;
186b2535c44Smckusick 
187b2535c44Smckusick 			pte = kvtopte(vadr);
188b2535c44Smckusick 			entry = pte->pt_entry;
1896f8a06d4Sutashiro #ifdef DIAGNOSTIC
1906f8a06d4Sutashiro 			if (!(entry & PG_V) || (entry & PG_M))
1916f8a06d4Sutashiro 				panic("trap: ktlbmod: invalid pte");
1926f8a06d4Sutashiro #endif
193b2535c44Smckusick 			if (entry & PG_RO) {
194b2535c44Smckusick 				/* write to read only page in the kernel */
195b2535c44Smckusick 				ftype = VM_PROT_WRITE;
196b2535c44Smckusick 				goto kernel_fault;
197b2535c44Smckusick 			}
198b2535c44Smckusick 			entry |= PG_M;
199b2535c44Smckusick 			pte->pt_entry = entry;
2006f8a06d4Sutashiro 			vadr &= ~PGOFSET;
201df2ccf6eSutashiro 			MachTLBUpdate(vadr, entry);
202b2535c44Smckusick 			pa = entry & PG_FRAME;
2036f8a06d4Sutashiro #ifdef ATTR
2046f8a06d4Sutashiro 			pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
2056f8a06d4Sutashiro #else
206b2535c44Smckusick 			if (!IS_VM_PHYSADDR(pa))
2076f8a06d4Sutashiro 				panic("trap: ktlbmod: unmanaged page");
208f6d95f34Sutashiro 			PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
209b2535c44Smckusick #endif
210b2535c44Smckusick 			return (pc);
211b2535c44Smckusick 		}
212b2535c44Smckusick 		/* FALLTHROUGH */
213b2535c44Smckusick 
214b2535c44Smckusick 	case T_TLB_MOD+T_USER:
215b2535c44Smckusick 	    {
2166f8a06d4Sutashiro 		register pt_entry_t *pte;
2176f8a06d4Sutashiro 		register unsigned entry;
2186f8a06d4Sutashiro 		register vm_offset_t pa;
2196f8a06d4Sutashiro 		pmap_t pmap = &p->p_vmspace->vm_pmap;
220b2535c44Smckusick 
2216f8a06d4Sutashiro 		if (!(pte = pmap_segmap(pmap, vadr)))
2226f8a06d4Sutashiro 			panic("trap: utlbmod: invalid segmap");
2236f8a06d4Sutashiro 		pte += (vadr >> PGSHIFT) & (NPTEPG - 1);
2246f8a06d4Sutashiro 		entry = pte->pt_entry;
2256f8a06d4Sutashiro #ifdef DIAGNOSTIC
2266f8a06d4Sutashiro 		if (!(entry & PG_V) || (entry & PG_M))
2276f8a06d4Sutashiro 			panic("trap: utlbmod: invalid pte");
228b2535c44Smckusick #endif
2296f8a06d4Sutashiro 		if (entry & PG_RO) {
2306f8a06d4Sutashiro 			/* write to read only page */
231b2535c44Smckusick 			ftype = VM_PROT_WRITE;
232b2535c44Smckusick 			goto dofault;
233b2535c44Smckusick 		}
2346f8a06d4Sutashiro 		entry |= PG_M;
2356f8a06d4Sutashiro 		pte->pt_entry = entry;
2366f8a06d4Sutashiro 		vadr = (vadr & ~PGOFSET) |
2376f8a06d4Sutashiro 			(pmap->pm_tlbpid << VMMACH_TLB_PID_SHIFT);
238df2ccf6eSutashiro 		MachTLBUpdate(vadr, entry);
2396f8a06d4Sutashiro 		pa = entry & PG_FRAME;
240b2535c44Smckusick #ifdef ATTR
2416f8a06d4Sutashiro 		pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
242b2535c44Smckusick #else
243b2535c44Smckusick 		if (!IS_VM_PHYSADDR(pa))
2446f8a06d4Sutashiro 			panic("trap: utlbmod: unmanaged page");
245f6d95f34Sutashiro 		PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
246b2535c44Smckusick #endif
247b2535c44Smckusick 		if (!USERMODE(statusReg))
248b2535c44Smckusick 			return (pc);
249b2535c44Smckusick 		goto out;
250b2535c44Smckusick 	    }
251b2535c44Smckusick 
252b2535c44Smckusick 	case T_TLB_LD_MISS:
253b2535c44Smckusick 	case T_TLB_ST_MISS:
254b2535c44Smckusick 		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
25518e6ce8eSbostic 		/* check for kernel address */
256b2535c44Smckusick 		if ((int)vadr < 0) {
257b2535c44Smckusick 			register vm_offset_t va;
258b2535c44Smckusick 			int rv;
259b2535c44Smckusick 
260b2535c44Smckusick 		kernel_fault:
261b2535c44Smckusick 			va = trunc_page((vm_offset_t)vadr);
262b2535c44Smckusick 			rv = vm_fault(kernel_map, va, ftype, FALSE);
263b2535c44Smckusick 			if (rv == KERN_SUCCESS)
264b2535c44Smckusick 				return (pc);
265b2535c44Smckusick 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
266b2535c44Smckusick 				((struct pcb *)UADDR)->pcb_onfault = 0;
267b2535c44Smckusick 				return (onfault_table[i]);
268b2535c44Smckusick 			}
269b2535c44Smckusick 			goto err;
270b2535c44Smckusick 		}
271f6d95f34Sutashiro 		/*
272f6d95f34Sutashiro 		 * It is an error for the kernel to access user space except
273f6d95f34Sutashiro 		 * through the copyin/copyout routines.
274f6d95f34Sutashiro 		 */
275f6d95f34Sutashiro 		if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)
276f6d95f34Sutashiro 			goto err;
27718e6ce8eSbostic 		/* check for fuswintr() or suswintr() getting a page fault */
278f6d95f34Sutashiro 		if (i == 4)
27918e6ce8eSbostic 			return (onfault_table[i]);
280b2535c44Smckusick 		goto dofault;
281b2535c44Smckusick 
282b2535c44Smckusick 	case T_TLB_LD_MISS+T_USER:
283b2535c44Smckusick 		ftype = VM_PROT_READ;
284b2535c44Smckusick 		goto dofault;
285b2535c44Smckusick 
286b2535c44Smckusick 	case T_TLB_ST_MISS+T_USER:
287b2535c44Smckusick 		ftype = VM_PROT_WRITE;
288b2535c44Smckusick 	dofault:
289b2535c44Smckusick 	    {
290b2535c44Smckusick 		register vm_offset_t va;
2916f8a06d4Sutashiro 		register struct vmspace *vm;
2926f8a06d4Sutashiro 		register vm_map_t map;
293b2535c44Smckusick 		int rv;
294b2535c44Smckusick 
2956f8a06d4Sutashiro 		vm = p->p_vmspace;
2966f8a06d4Sutashiro 		map = &vm->vm_map;
297b2535c44Smckusick 		va = trunc_page((vm_offset_t)vadr);
298b2535c44Smckusick 		rv = vm_fault(map, va, ftype, FALSE);
299b2535c44Smckusick 		/*
300b2535c44Smckusick 		 * If this was a stack access we keep track of the maximum
301b2535c44Smckusick 		 * accessed stack size.  Also, if vm_fault gets a protection
302b2535c44Smckusick 		 * failure it is due to accessing the stack region outside
303b2535c44Smckusick 		 * the current limit and we need to reflect that as an access
304b2535c44Smckusick 		 * error.
305b2535c44Smckusick 		 */
306b2535c44Smckusick 		if ((caddr_t)va >= vm->vm_maxsaddr) {
307b2535c44Smckusick 			if (rv == KERN_SUCCESS) {
308b2535c44Smckusick 				unsigned nss;
309b2535c44Smckusick 
310b2535c44Smckusick 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
311b2535c44Smckusick 				if (nss > vm->vm_ssize)
312b2535c44Smckusick 					vm->vm_ssize = nss;
313b2535c44Smckusick 			} else if (rv == KERN_PROTECTION_FAILURE)
314b2535c44Smckusick 				rv = KERN_INVALID_ADDRESS;
315b2535c44Smckusick 		}
316b2535c44Smckusick 		if (rv == KERN_SUCCESS) {
317b2535c44Smckusick 			if (!USERMODE(statusReg))
318b2535c44Smckusick 				return (pc);
319b2535c44Smckusick 			goto out;
320b2535c44Smckusick 		}
321b2535c44Smckusick 		if (!USERMODE(statusReg)) {
322b2535c44Smckusick 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
323b2535c44Smckusick 				((struct pcb *)UADDR)->pcb_onfault = 0;
324b2535c44Smckusick 				return (onfault_table[i]);
325b2535c44Smckusick 			}
326b2535c44Smckusick 			goto err;
327b2535c44Smckusick 		}
328b2535c44Smckusick 		ucode = vadr;
329b2535c44Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
330b2535c44Smckusick 		break;
331b2535c44Smckusick 	    }
332b2535c44Smckusick 
333b2535c44Smckusick 	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
334b2535c44Smckusick 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
335b2535c44Smckusick 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
336b2535c44Smckusick 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
337b2535c44Smckusick 		i = SIGSEGV;
338b2535c44Smckusick 		break;
339b2535c44Smckusick 
340b2535c44Smckusick 	case T_SYSCALL+T_USER:
341b2535c44Smckusick 	    {
342b2535c44Smckusick 		register int *locr0 = p->p_md.md_regs;
343b2535c44Smckusick 		register struct sysent *callp;
344b2535c44Smckusick 		unsigned int code;
345b2535c44Smckusick 		int numsys;
346b2535c44Smckusick 		struct args {
347b2535c44Smckusick 			int i[8];
348b2535c44Smckusick 		} args;
349b2535c44Smckusick 		int rval[2];
350b2535c44Smckusick 		struct sysent *systab;
351b2535c44Smckusick 		extern int nsysent;
3526a898fb7Sutashiro #ifdef COMPAT_NEWSOS
3536a898fb7Sutashiro 		extern int nnewssys;
3546a898fb7Sutashiro 		extern struct sysent newssys[];
3556a898fb7Sutashiro #endif
356b2535c44Smckusick 
357b2535c44Smckusick 		cnt.v_syscall++;
358b2535c44Smckusick 		/* compute next PC after syscall instruction */
359b2535c44Smckusick 		if ((int)causeReg < 0)
360b2535c44Smckusick 			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
361b2535c44Smckusick 		else
362b2535c44Smckusick 			locr0[PC] += 4;
363b2535c44Smckusick 		systab = sysent;
364b2535c44Smckusick 		numsys = nsysent;
365b2535c44Smckusick 		code = locr0[V0];
366b2535c44Smckusick #ifdef COMPAT_NEWSOS
3676a898fb7Sutashiro 		if (code >= 1000) {
3686a898fb7Sutashiro 			code -= 1000;
3696a898fb7Sutashiro 			systab = newssys;
3706a898fb7Sutashiro 			numsys = nnewssys;
3716a898fb7Sutashiro 		}
372b2535c44Smckusick #endif
373d3d68664Sutashiro 		switch (code) {
3742c80d3daSmckusick 		case SYS_syscall:
375d3d68664Sutashiro 			/*
376d3d68664Sutashiro 			 * Code is first argument, followed by actual args.
377d3d68664Sutashiro 			 */
378b2535c44Smckusick 			code = locr0[A0];
379b2535c44Smckusick #ifdef COMPAT_NEWSOS
3806a898fb7Sutashiro 			if (code >= 1000) {
3816a898fb7Sutashiro 				code -= 1000;
3826a898fb7Sutashiro 				systab = newssys;
3836a898fb7Sutashiro 				numsys = nnewssys;
3846a898fb7Sutashiro 			}
385b2535c44Smckusick #endif
386b2535c44Smckusick 			if (code >= numsys)
3872c80d3daSmckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
388b2535c44Smckusick 			else
389b2535c44Smckusick 				callp = &systab[code];
390b2535c44Smckusick 			i = callp->sy_narg;
391b2535c44Smckusick 			args.i[0] = locr0[A1];
392b2535c44Smckusick 			args.i[1] = locr0[A2];
393b2535c44Smckusick 			args.i[2] = locr0[A3];
394b2535c44Smckusick 			if (i > 3) {
395b2535c44Smckusick 				i = copyin((caddr_t)(locr0[SP] +
396d3d68664Sutashiro 						4 * sizeof(int)),
397b2535c44Smckusick 					(caddr_t)&args.i[3],
398b2535c44Smckusick 					(u_int)(i - 3) * sizeof(int));
399b2535c44Smckusick 				if (i) {
400b2535c44Smckusick 					locr0[V0] = i;
401b2535c44Smckusick 					locr0[A3] = 1;
402b2535c44Smckusick #ifdef KTRACE
403b2535c44Smckusick 					if (KTRPOINT(p, KTR_SYSCALL))
404b2535c44Smckusick 						ktrsyscall(p->p_tracep, code,
405b2535c44Smckusick 							callp->sy_narg, args.i);
406b2535c44Smckusick #endif
407b2535c44Smckusick 					goto done;
408b2535c44Smckusick 				}
409b2535c44Smckusick 			}
410d3d68664Sutashiro 			break;
411d3d68664Sutashiro 
4122c80d3daSmckusick 		case SYS___syscall:
413d3d68664Sutashiro 			/*
4142c80d3daSmckusick 			 * Like syscall, but code is a quad, so as to maintain
415d3d68664Sutashiro 			 * quad alignment for the rest of the arguments.
416d3d68664Sutashiro 			 */
417d3d68664Sutashiro 			code = locr0[A0 + _QUAD_LOWWORD];
418b2535c44Smckusick 			if (code >= numsys)
4192c80d3daSmckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
420d3d68664Sutashiro 			else
421d3d68664Sutashiro 				callp = &systab[code];
422d3d68664Sutashiro 			i = callp->sy_narg;
423d3d68664Sutashiro 			args.i[0] = locr0[A2];
424d3d68664Sutashiro 			args.i[1] = locr0[A3];
425d3d68664Sutashiro 			if (i > 2) {
426d3d68664Sutashiro 				i = copyin((caddr_t)(locr0[SP] +
427d3d68664Sutashiro 						4 * sizeof(int)),
428d3d68664Sutashiro 					(caddr_t)&args.i[2],
429d3d68664Sutashiro 					(u_int)(i - 2) * sizeof(int));
430d3d68664Sutashiro 				if (i) {
431d3d68664Sutashiro 					locr0[V0] = i;
432d3d68664Sutashiro 					locr0[A3] = 1;
433d3d68664Sutashiro #ifdef KTRACE
434d3d68664Sutashiro 					if (KTRPOINT(p, KTR_SYSCALL))
435d3d68664Sutashiro 						ktrsyscall(p->p_tracep, code,
436d3d68664Sutashiro 							callp->sy_narg, args.i);
437d3d68664Sutashiro #endif
438d3d68664Sutashiro 					goto done;
439d3d68664Sutashiro 				}
440d3d68664Sutashiro 			}
441d3d68664Sutashiro 			break;
442d3d68664Sutashiro 
443d3d68664Sutashiro 		default:
444d3d68664Sutashiro 			if (code >= numsys)
4452c80d3daSmckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
446b2535c44Smckusick 			else
447b2535c44Smckusick 				callp = &systab[code];
448b2535c44Smckusick 			i = callp->sy_narg;
449b2535c44Smckusick 			args.i[0] = locr0[A0];
450b2535c44Smckusick 			args.i[1] = locr0[A1];
451b2535c44Smckusick 			args.i[2] = locr0[A2];
452b2535c44Smckusick 			args.i[3] = locr0[A3];
453b2535c44Smckusick 			if (i > 4) {
454b2535c44Smckusick 				i = copyin((caddr_t)(locr0[SP] +
455b2535c44Smckusick 						4 * sizeof(int)),
456b2535c44Smckusick 					(caddr_t)&args.i[4],
457b2535c44Smckusick 					(u_int)(i - 4) * sizeof(int));
458b2535c44Smckusick 				if (i) {
459b2535c44Smckusick 					locr0[V0] = i;
460b2535c44Smckusick 					locr0[A3] = 1;
461b2535c44Smckusick #ifdef KTRACE
462b2535c44Smckusick 					if (KTRPOINT(p, KTR_SYSCALL))
463b2535c44Smckusick 						ktrsyscall(p->p_tracep, code,
464b2535c44Smckusick 							callp->sy_narg, args.i);
465b2535c44Smckusick #endif
466b2535c44Smckusick 					goto done;
467b2535c44Smckusick 				}
468b2535c44Smckusick 			}
469b2535c44Smckusick 		}
470b2535c44Smckusick #ifdef KTRACE
471b2535c44Smckusick 		if (KTRPOINT(p, KTR_SYSCALL))
472b2535c44Smckusick 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
473b2535c44Smckusick #endif
474b2535c44Smckusick 		rval[0] = 0;
475b2535c44Smckusick 		rval[1] = locr0[V1];
476b2535c44Smckusick #ifdef DEBUG
477b2535c44Smckusick 		if (trp == trapdebug)
478b2535c44Smckusick 			trapdebug[TRAPSIZE - 1].code = code;
479b2535c44Smckusick 		else
480b2535c44Smckusick 			trp[-1].code = code;
481b2535c44Smckusick #endif
482b2535c44Smckusick 		i = (*callp->sy_call)(p, &args, rval);
483b2535c44Smckusick 		/*
484b2535c44Smckusick 		 * Reinitialize proc pointer `p' as it may be different
485b2535c44Smckusick 		 * if this is a child returning from fork syscall.
486b2535c44Smckusick 		 */
487b2535c44Smckusick 		p = curproc;
488b2535c44Smckusick 		locr0 = p->p_md.md_regs;
489b2535c44Smckusick #ifdef DEBUG
490b2535c44Smckusick 		{ int s;
491b2535c44Smckusick 		s = splhigh();
492b2535c44Smckusick 		trp->status = statusReg;
493b2535c44Smckusick 		trp->cause = causeReg;
494b2535c44Smckusick 		trp->vadr = locr0[SP];
495b2535c44Smckusick 		trp->pc = locr0[PC];
496b2535c44Smckusick 		trp->ra = locr0[RA];
497b2535c44Smckusick 		trp->code = -code;
498b2535c44Smckusick 		if (++trp == &trapdebug[TRAPSIZE])
499b2535c44Smckusick 			trp = trapdebug;
500b2535c44Smckusick 		splx(s);
501b2535c44Smckusick 		}
502b2535c44Smckusick #endif
503f6d95f34Sutashiro 		switch (i) {
504f6d95f34Sutashiro 		case 0:
505b2535c44Smckusick 			locr0[V0] = rval[0];
506b2535c44Smckusick 			locr0[V1] = rval[1];
507b2535c44Smckusick 			locr0[A3] = 0;
508f6d95f34Sutashiro 			break;
509f6d95f34Sutashiro 
510f6d95f34Sutashiro 		case ERESTART:
511f6d95f34Sutashiro 			locr0[PC] = pc;
512f6d95f34Sutashiro 			break;
513f6d95f34Sutashiro 
514f6d95f34Sutashiro 		case EJUSTRETURN:
515f6d95f34Sutashiro 			break;	/* nothing to do */
516f6d95f34Sutashiro 
517f6d95f34Sutashiro 		default:
518f6d95f34Sutashiro 			locr0[V0] = i;
519f6d95f34Sutashiro 			locr0[A3] = 1;
520b2535c44Smckusick 		}
521b2535c44Smckusick 	done:
522b2535c44Smckusick #ifdef KTRACE
523b2535c44Smckusick 		if (KTRPOINT(p, KTR_SYSRET))
524b2535c44Smckusick 			ktrsysret(p->p_tracep, code, i, rval[0]);
525b2535c44Smckusick #endif
526b2535c44Smckusick 
527b2535c44Smckusick 		goto out;
528b2535c44Smckusick 	    }
529b2535c44Smckusick 
530b2535c44Smckusick 	case T_BREAK+T_USER:
531b2535c44Smckusick 	    {
532b2535c44Smckusick 		register unsigned va, instr;
533b2535c44Smckusick 
534b2535c44Smckusick 		/* compute address of break instruction */
535b2535c44Smckusick 		va = pc;
536b2535c44Smckusick 		if ((int)causeReg < 0)
537b2535c44Smckusick 			va += 4;
538b2535c44Smckusick 
539b2535c44Smckusick 		/* read break instruction */
5403a98b5ebSutashiro 		instr = fuiword((caddr_t)va);
541b2535c44Smckusick #ifdef KADB
542b2535c44Smckusick 		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)
543b2535c44Smckusick 			goto err;
544b2535c44Smckusick #endif
545b2535c44Smckusick 		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {
546b2535c44Smckusick 			i = SIGTRAP;
547b2535c44Smckusick 			break;
548b2535c44Smckusick 		}
549b2535c44Smckusick 
550b2535c44Smckusick 		/* restore original instruction and clear BP  */
551b2535c44Smckusick 		i = suiword((caddr_t)va, p->p_md.md_ss_instr);
552b2535c44Smckusick 		if (i < 0) {
553b2535c44Smckusick 			vm_offset_t sa, ea;
554b2535c44Smckusick 			int rv;
555b2535c44Smckusick 
556b2535c44Smckusick 			sa = trunc_page((vm_offset_t)va);
557b2535c44Smckusick 			ea = round_page((vm_offset_t)va+sizeof(int)-1);
558b2535c44Smckusick 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
559b2535c44Smckusick 				VM_PROT_DEFAULT, FALSE);
560b2535c44Smckusick 			if (rv == KERN_SUCCESS) {
561b2535c44Smckusick 				i = suiword((caddr_t)va, p->p_md.md_ss_instr);
562b2535c44Smckusick 				(void) vm_map_protect(&p->p_vmspace->vm_map,
563b2535c44Smckusick 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
564b2535c44Smckusick 					FALSE);
565b2535c44Smckusick 			}
566b2535c44Smckusick 		}
567b2535c44Smckusick 		if (i < 0) {
568b2535c44Smckusick 			i = SIGTRAP;
569b2535c44Smckusick 			break;
570b2535c44Smckusick 		}
571b2535c44Smckusick 		p->p_md.md_ss_addr = 0;
572b2535c44Smckusick 		goto out;
573b2535c44Smckusick 	    }
574b2535c44Smckusick 
575b2535c44Smckusick 	case T_RES_INST+T_USER:
576b2535c44Smckusick 		i = SIGILL;
577b2535c44Smckusick 		break;
578b2535c44Smckusick 
579b2535c44Smckusick 	case T_COP_UNUSABLE+T_USER:
580b2535c44Smckusick 		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {
581b2535c44Smckusick 			i = SIGILL;	/* only FPU instructions allowed */
582b2535c44Smckusick 			break;
583b2535c44Smckusick 		}
584b2535c44Smckusick 		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
585b2535c44Smckusick 		machFPCurProcPtr = p;
586b2535c44Smckusick 		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;
587b2535c44Smckusick 		p->p_md.md_flags |= MDP_FPUSED;
588b2535c44Smckusick 		goto out;
589b2535c44Smckusick 
590b2535c44Smckusick 	case T_OVFLOW+T_USER:
591b2535c44Smckusick 		i = SIGFPE;
592b2535c44Smckusick 		break;
593b2535c44Smckusick 
594b2535c44Smckusick 	case T_ADDR_ERR_LD:	/* misaligned access */
595b2535c44Smckusick 	case T_ADDR_ERR_ST:	/* misaligned access */
596b2535c44Smckusick 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
597b2535c44Smckusick 		if (i = ((struct pcb *)UADDR)->pcb_onfault) {
598b2535c44Smckusick 			((struct pcb *)UADDR)->pcb_onfault = 0;
599b2535c44Smckusick 			return (onfault_table[i]);
600b2535c44Smckusick 		}
601b2535c44Smckusick 		/* FALLTHROUGH */
602b2535c44Smckusick 
603b2535c44Smckusick 	default:
604b2535c44Smckusick 	err:
605b2535c44Smckusick #ifdef KADB
606b2535c44Smckusick 	    {
607b2535c44Smckusick 		extern struct pcb kdbpcb;
608b2535c44Smckusick 
609b2535c44Smckusick 		if (USERMODE(statusReg))
610b2535c44Smckusick 			kdbpcb = p->p_addr->u_pcb;
611b2535c44Smckusick 		else {
612b2535c44Smckusick 			kdbpcb.pcb_regs[ZERO] = 0;
613b2535c44Smckusick 			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];
614b2535c44Smckusick 			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];
615b2535c44Smckusick 			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];
616b2535c44Smckusick 			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];
617b2535c44Smckusick 			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];
618b2535c44Smckusick 			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];
619b2535c44Smckusick 			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];
620b2535c44Smckusick 			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];
621b2535c44Smckusick 			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];
622b2535c44Smckusick 			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];
623b2535c44Smckusick 			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];
624b2535c44Smckusick 			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];
625b2535c44Smckusick 			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];
626b2535c44Smckusick 			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];
627b2535c44Smckusick 			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];
628b2535c44Smckusick 			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];
629b2535c44Smckusick 			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];
630b2535c44Smckusick 			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];
631b2535c44Smckusick 			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
632b2535c44Smckusick 			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
633b2535c44Smckusick 			kdbpcb.pcb_regs[PC] = pc;
634b2535c44Smckusick 			kdbpcb.pcb_regs[SR] = statusReg;
635b2535c44Smckusick 			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));
636b2535c44Smckusick 		}
637b2535c44Smckusick 		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))
638b2535c44Smckusick 			return (kdbpcb.pcb_regs[PC]);
639b2535c44Smckusick 	    }
6403a98b5ebSutashiro #else
6413a98b5ebSutashiro #ifdef DEBUG
6426a898fb7Sutashiro 		printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid,
6436a898fb7Sutashiro 			p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */
6443a98b5ebSutashiro 		trapDump("trap");
645b2535c44Smckusick #endif
6463a98b5ebSutashiro #endif
647b2535c44Smckusick 		panic("trap");
648b2535c44Smckusick 	}
649b2535c44Smckusick 	trapsignal(p, i, ucode);
650b2535c44Smckusick out:
651b2535c44Smckusick 	/*
652b2535c44Smckusick 	 * Note: we should only get here if returning to user mode.
653b2535c44Smckusick 	 */
65418e6ce8eSbostic 	/* take pending signals */
65518e6ce8eSbostic 	while ((i = CURSIG(p)) != 0)
656*56185310Sbostic 		postsig(i);
657*56185310Sbostic 	p->p_priority = p->p_usrpri;
65818e6ce8eSbostic 	astpending = 0;
659b2535c44Smckusick 	if (want_resched) {
660b2535c44Smckusick 		int s;
661b2535c44Smckusick 
662b2535c44Smckusick 		/*
663b2535c44Smckusick 		 * Since we are curproc, clock will normally just change
664b2535c44Smckusick 		 * our priority without moving us from one queue to another
665b2535c44Smckusick 		 * (since the running process is not on a queue.)
666793bd282Sbostic 		 * If that happened after we put ourselves on the run queue
667*56185310Sbostic 		 * but before we switch()'ed, we might not be on the queue
668793bd282Sbostic 		 * indicated by our priority.
669b2535c44Smckusick 		 */
67018e6ce8eSbostic 		s = splstatclock();
671793bd282Sbostic 		setrunqueue(p);
672b2535c44Smckusick 		p->p_stats->p_ru.ru_nivcsw++;
673*56185310Sbostic 		mi_switch();
674b2535c44Smckusick 		splx(s);
67518e6ce8eSbostic 		while ((i = CURSIG(p)) != 0)
676*56185310Sbostic 			postsig(i);
677b2535c44Smckusick 	}
67818e6ce8eSbostic 	/*
67918e6ce8eSbostic 	 * If profiling, charge system time to the trapped pc.
68018e6ce8eSbostic 	 */
681*56185310Sbostic 	if (p->p_flag & P_PROFIL) {
682f6d95f34Sutashiro 		extern int psratio;
683f6d95f34Sutashiro 
684f6d95f34Sutashiro 		addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
685f6d95f34Sutashiro 	}
686*56185310Sbostic 	curpriority = p->p_priority;
687b2535c44Smckusick 	return (pc);
688b2535c44Smckusick }
689b2535c44Smckusick 
690ed18d738Sutashiro int	badaddr_flag;
691ed18d738Sutashiro 
692b2535c44Smckusick /*
693b2535c44Smckusick  * Handle an interrupt.
694b2535c44Smckusick  * Called from MachKernIntr() or MachUserIntr()
695b2535c44Smckusick  * Note: curproc might be NULL.
696b2535c44Smckusick  */
interrupt(statusReg,causeReg,pc)697b2535c44Smckusick interrupt(statusReg, causeReg, pc)
698b2535c44Smckusick 	unsigned statusReg;	/* status register at time of the exception */
699b2535c44Smckusick 	unsigned causeReg;	/* cause register at time of exception */
700b2535c44Smckusick 	unsigned pc;		/* program counter where to continue */
701b2535c44Smckusick {
702b2535c44Smckusick 	register unsigned mask;
70318e6ce8eSbostic 	struct clockframe cf;
7046a898fb7Sutashiro 	int oonfault = ((struct pcb *)UADDR)->pcb_onfault;
705b2535c44Smckusick 
706b2535c44Smckusick #ifdef DEBUG
707b2535c44Smckusick 	trp->status = statusReg;
708b2535c44Smckusick 	trp->cause = causeReg;
709b2535c44Smckusick 	trp->vadr = 0;
710b2535c44Smckusick 	trp->pc = pc;
711b2535c44Smckusick 	trp->ra = 0;
712b2535c44Smckusick 	trp->code = 0;
713b2535c44Smckusick 	if (++trp == &trapdebug[TRAPSIZE])
714b2535c44Smckusick 		trp = trapdebug;
715b2535c44Smckusick #endif
716b2535c44Smckusick 
717b2535c44Smckusick 	mask = causeReg & statusReg;	/* pending interrupts & enable mask */
718b2535c44Smckusick 	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */
719b2535c44Smckusick 		splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR);
720b2535c44Smckusick 		printf("level 5 interrupt: PC %x CR %x SR %x\n",
721b2535c44Smckusick 			pc, causeReg, statusReg);
722b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_5;
723b2535c44Smckusick 	}
724b2535c44Smckusick 	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */
725b2535c44Smckusick 		/*
726b2535c44Smckusick 		 * asynchronous bus error
727b2535c44Smckusick 		 */
728b2535c44Smckusick 		splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR);
729b2535c44Smckusick 		*(char *)INTCLR0 = INTCLR0_BERR;
730b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_4;
731ed18d738Sutashiro #define BADADDR 1
732ed18d738Sutashiro 		if (oonfault == BADADDR) {		/* XXX */
733ed18d738Sutashiro 			badaddr_flag = 1;
734ed18d738Sutashiro 		} else {
735ed18d738Sutashiro 			printf("level 4 interrupt: PC %x CR %x SR %x\n",
736ed18d738Sutashiro 				pc, causeReg, statusReg);
737ed18d738Sutashiro 		}
738b2535c44Smckusick 	}
739b2535c44Smckusick 	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */
740b2535c44Smckusick 		/*
741b2535c44Smckusick 		 * fp error
742b2535c44Smckusick 		 */
743b2535c44Smckusick 		splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR);
744b2535c44Smckusick 		if (!USERMODE(statusReg)) {
745b2535c44Smckusick #ifdef DEBUG
746b2535c44Smckusick 			trapDump("fpintr");
747b2535c44Smckusick #else
748b2535c44Smckusick 			printf("FPU interrupt: PC %x CR %x SR %x\n",
749b2535c44Smckusick 				pc, causeReg, statusReg);
750b2535c44Smckusick #endif
751b2535c44Smckusick 		} else
752b2535c44Smckusick 			MachFPInterrupt(statusReg, causeReg, pc);
753b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_3;
754b2535c44Smckusick 	}
755b2535c44Smckusick 	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */
756b2535c44Smckusick 		register int stat;
757b2535c44Smckusick 
758b2535c44Smckusick 		splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR);
759b2535c44Smckusick 		stat = *(volatile u_char *)INTST0;
760b2535c44Smckusick 		if (stat & INTST0_TIMINT) {	/* timer */
761b2535c44Smckusick 			static int led_count = 0;
762b2535c44Smckusick 
763b2535c44Smckusick 			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;
764b2535c44Smckusick 			cf.pc = pc;
76518e6ce8eSbostic 			cf.sr = statusReg;
76618e6ce8eSbostic 			hardclock(&cf);
767b2535c44Smckusick 			if (++led_count > hz) {
768b2535c44Smckusick 				led_count = 0;
769b2535c44Smckusick 				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;
770b2535c44Smckusick 			}
771b2535c44Smckusick 		}
772b2535c44Smckusick #if NBM > 0
773b2535c44Smckusick 		if (stat & INTST0_KBDINT)	/* keyboard */
774b2535c44Smckusick 			kbm_rint(SCC_KEYBOARD);
775b2535c44Smckusick #endif
776b2535c44Smckusick #if NMS > 0
777b2535c44Smckusick 		if (stat & INTST0_MSINT)	/* mouse */
778b2535c44Smckusick 			kbm_rint(SCC_MOUSE);
779b2535c44Smckusick #endif
780b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_2;
781b2535c44Smckusick 	}
782b2535c44Smckusick 	if (mask & MACH_INT_MASK_1) {		/* level 1 interrupt */
783b2535c44Smckusick 		splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR);
784b2535c44Smckusick 		level1_intr();
785b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_1;
786b2535c44Smckusick 	}
787b2535c44Smckusick 	if (mask & MACH_INT_MASK_0) {		/* level 0 interrupt */
788b2535c44Smckusick 		splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
789b2535c44Smckusick 		level0_intr();
790b2535c44Smckusick 		causeReg &= ~MACH_INT_MASK_0;
791b2535c44Smckusick 	}
792b2535c44Smckusick 	splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
793b2535c44Smckusick 
794b2535c44Smckusick 	if (mask & MACH_SOFT_INT_MASK_0) {
79518e6ce8eSbostic 		struct clockframe cf;
796b2535c44Smckusick 
797b2535c44Smckusick 		clearsoftclock();
7983a98b5ebSutashiro 		cnt.v_soft++;
799b2535c44Smckusick 		cf.pc = pc;
80018e6ce8eSbostic 		cf.sr = statusReg;
80118e6ce8eSbostic 		softclock();
802b2535c44Smckusick 	}
803b2535c44Smckusick 	/* process network interrupt if we trapped or will very soon */
804b2535c44Smckusick 	if ((mask & MACH_SOFT_INT_MASK_1) ||
805b2535c44Smckusick 	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
806b2535c44Smckusick 		clearsoftnet();
8073a98b5ebSutashiro 		cnt.v_soft++;
808b2535c44Smckusick #ifdef INET
809b2535c44Smckusick 		if (netisr & (1 << NETISR_ARP)) {
810b2535c44Smckusick 			netisr &= ~(1 << NETISR_ARP);
811b2535c44Smckusick 			arpintr();
812b2535c44Smckusick 		}
813b2535c44Smckusick 		if (netisr & (1 << NETISR_IP)) {
814b2535c44Smckusick 			netisr &= ~(1 << NETISR_IP);
815b2535c44Smckusick 			ipintr();
816b2535c44Smckusick 		}
817b2535c44Smckusick #endif
818b2535c44Smckusick #ifdef NS
819b2535c44Smckusick 		if (netisr & (1 << NETISR_NS)) {
820b2535c44Smckusick 			netisr &= ~(1 << NETISR_NS);
821b2535c44Smckusick 			nsintr();
822b2535c44Smckusick 		}
823b2535c44Smckusick #endif
824b2535c44Smckusick #ifdef ISO
825b2535c44Smckusick 		if (netisr & (1 << NETISR_ISO)) {
826b2535c44Smckusick 			netisr &= ~(1 << NETISR_ISO);
827b2535c44Smckusick 			clnlintr();
828b2535c44Smckusick 		}
829b2535c44Smckusick #endif
830b2535c44Smckusick 	}
8316a898fb7Sutashiro 	/* restore onfault flag */
8326a898fb7Sutashiro 	((struct pcb *)UADDR)->pcb_onfault = oonfault;
833b2535c44Smckusick }
834b2535c44Smckusick 
835b2535c44Smckusick /*
836b2535c44Smckusick  * This is called from MachUserIntr() if astpending is set.
837b2535c44Smckusick  * This is very similar to the tail of trap().
838b2535c44Smckusick  */
softintr(statusReg,pc)839b2535c44Smckusick softintr(statusReg, pc)
840b2535c44Smckusick 	unsigned statusReg;	/* status register at time of the exception */
841b2535c44Smckusick 	unsigned pc;		/* program counter where to continue */
842b2535c44Smckusick {
843b2535c44Smckusick 	register struct proc *p = curproc;
84418e6ce8eSbostic 	int sig;
845b2535c44Smckusick 
846b2535c44Smckusick 	cnt.v_soft++;
84718e6ce8eSbostic 	/* take pending signals */
84818e6ce8eSbostic 	while ((sig = CURSIG(p)) != 0)
849*56185310Sbostic 		postsig(sig);
850*56185310Sbostic 	p->p_priority = p->p_usrpri;
85118e6ce8eSbostic 	astpending = 0;
852*56185310Sbostic 	if (p->p_flag & P_OWEUPC) {
853*56185310Sbostic 		p->p_flag &= ~P_OWEUPC;
85418e6ce8eSbostic 		ADDUPROF(p);
85518e6ce8eSbostic 	}
856b2535c44Smckusick 	if (want_resched) {
857b2535c44Smckusick 		int s;
858b2535c44Smckusick 
859b2535c44Smckusick 		/*
860b2535c44Smckusick 		 * Since we are curproc, clock will normally just change
861b2535c44Smckusick 		 * our priority without moving us from one queue to another
862b2535c44Smckusick 		 * (since the running process is not on a queue.)
863793bd282Sbostic 		 * If that happened after we put ourselves on the run queue
864*56185310Sbostic 		 * but before we switch()'ed, we might not be on the queue
865793bd282Sbostic 		 * indicated by our priority.
866b2535c44Smckusick 		 */
86718e6ce8eSbostic 		s = splstatclock();
868793bd282Sbostic 		setrunqueue(p);
869b2535c44Smckusick 		p->p_stats->p_ru.ru_nivcsw++;
870*56185310Sbostic 		mi_switch();
871b2535c44Smckusick 		splx(s);
87218e6ce8eSbostic 		while ((sig = CURSIG(p)) != 0)
873*56185310Sbostic 			postsig(sig);
874b2535c44Smckusick 	}
875*56185310Sbostic 	curpriority = p->p_priority;
876b2535c44Smckusick }
877b2535c44Smckusick 
878b2535c44Smckusick #ifdef DEBUG
trapDump(msg)879b2535c44Smckusick trapDump(msg)
880b2535c44Smckusick 	char *msg;
881b2535c44Smckusick {
882b2535c44Smckusick 	register int i;
883b2535c44Smckusick 	int s;
884b2535c44Smckusick 
885b2535c44Smckusick 	s = splhigh();
886b2535c44Smckusick 	printf("trapDump(%s)\n", msg);
887b2535c44Smckusick 	for (i = 0; i < TRAPSIZE; i++) {
888b2535c44Smckusick 		if (trp == trapdebug)
889b2535c44Smckusick 			trp = &trapdebug[TRAPSIZE - 1];
890b2535c44Smckusick 		else
891b2535c44Smckusick 			trp--;
892b2535c44Smckusick 		if (trp->cause == 0)
893b2535c44Smckusick 			break;
894b2535c44Smckusick 		printf("%s: ADR %x PC %x CR %x SR %x\n",
895b2535c44Smckusick 			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>
896b2535c44Smckusick 				MACH_CR_EXC_CODE_SHIFT],
897b2535c44Smckusick 			trp->vadr, trp->pc, trp->cause, trp->status);
898b2535c44Smckusick 		printf("   RA %x code %d\n", trp->ra, trp->code);
899b2535c44Smckusick 	}
900b2535c44Smckusick 	bzero(trapdebug, sizeof(trapdebug));
901b2535c44Smckusick 	trp = trapdebug;
902b2535c44Smckusick 	splx(s);
903b2535c44Smckusick }
904b2535c44Smckusick #endif
905b2535c44Smckusick 
906b2535c44Smckusick /*
907b2535c44Smckusick  * Return the resulting PC as if the branch was executed.
908b2535c44Smckusick  */
909b2535c44Smckusick unsigned
MachEmulateBranch(regsPtr,instPC,fpcCSR,allowNonBranch)910b2535c44Smckusick MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
911b2535c44Smckusick 	unsigned *regsPtr;
912b2535c44Smckusick 	unsigned instPC;
913b2535c44Smckusick 	unsigned fpcCSR;
914b2535c44Smckusick 	int allowNonBranch;
915b2535c44Smckusick {
916b2535c44Smckusick 	InstFmt inst;
917b2535c44Smckusick 	unsigned retAddr;
918b2535c44Smckusick 	int condition;
919b2535c44Smckusick 	extern unsigned GetBranchDest();
920b2535c44Smckusick 
921b2535c44Smckusick #if 0
922b2535c44Smckusick 	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
923b2535c44Smckusick 		*(unsigned *)instPC, fpcCSR);
924b2535c44Smckusick #endif
925b2535c44Smckusick 
926b2535c44Smckusick 	inst = *(InstFmt *)instPC;
927b2535c44Smckusick 	switch ((int)inst.JType.op) {
928b2535c44Smckusick 	case OP_SPECIAL:
929b2535c44Smckusick 		switch ((int)inst.RType.func) {
930b2535c44Smckusick 		case OP_JR:
931b2535c44Smckusick 		case OP_JALR:
932b2535c44Smckusick 			retAddr = regsPtr[inst.RType.rs];
933b2535c44Smckusick 			break;
934b2535c44Smckusick 
935b2535c44Smckusick 		default:
936b2535c44Smckusick 			if (!allowNonBranch)
937b2535c44Smckusick 				panic("MachEmulateBranch: Non-branch");
938b2535c44Smckusick 			retAddr = instPC + 4;
939b2535c44Smckusick 			break;
940b2535c44Smckusick 		}
941b2535c44Smckusick 		break;
942b2535c44Smckusick 
943b2535c44Smckusick 	case OP_BCOND:
944b2535c44Smckusick 		switch ((int)inst.IType.rt) {
945b2535c44Smckusick 		case OP_BLTZ:
946b2535c44Smckusick 		case OP_BLTZAL:
947b2535c44Smckusick 			if ((int)(regsPtr[inst.RType.rs]) < 0)
948b2535c44Smckusick 				retAddr = GetBranchDest((InstFmt *)instPC);
949b2535c44Smckusick 			else
950b2535c44Smckusick 				retAddr = instPC + 8;
951b2535c44Smckusick 			break;
952b2535c44Smckusick 
953b2535c44Smckusick 		case OP_BGEZAL:
954b2535c44Smckusick 		case OP_BGEZ:
955b2535c44Smckusick 			if ((int)(regsPtr[inst.RType.rs]) >= 0)
956b2535c44Smckusick 				retAddr = GetBranchDest((InstFmt *)instPC);
957b2535c44Smckusick 			else
958b2535c44Smckusick 				retAddr = instPC + 8;
959b2535c44Smckusick 			break;
960b2535c44Smckusick 
961b2535c44Smckusick 		default:
962b2535c44Smckusick 			panic("MachEmulateBranch: Bad branch cond");
963b2535c44Smckusick 		}
964b2535c44Smckusick 		break;
965b2535c44Smckusick 
966b2535c44Smckusick 	case OP_J:
967b2535c44Smckusick 	case OP_JAL:
968b2535c44Smckusick 		retAddr = (inst.JType.target << 2) |
969b2535c44Smckusick 			((unsigned)instPC & 0xF0000000);
970b2535c44Smckusick 		break;
971b2535c44Smckusick 
972b2535c44Smckusick 	case OP_BEQ:
973b2535c44Smckusick 		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
974b2535c44Smckusick 			retAddr = GetBranchDest((InstFmt *)instPC);
975b2535c44Smckusick 		else
976b2535c44Smckusick 			retAddr = instPC + 8;
977b2535c44Smckusick 		break;
978b2535c44Smckusick 
979b2535c44Smckusick 	case OP_BNE:
980b2535c44Smckusick 		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
981b2535c44Smckusick 			retAddr = GetBranchDest((InstFmt *)instPC);
982b2535c44Smckusick 		else
983b2535c44Smckusick 			retAddr = instPC + 8;
984b2535c44Smckusick 		break;
985b2535c44Smckusick 
986b2535c44Smckusick 	case OP_BLEZ:
987b2535c44Smckusick 		if ((int)(regsPtr[inst.RType.rs]) <= 0)
988b2535c44Smckusick 			retAddr = GetBranchDest((InstFmt *)instPC);
989b2535c44Smckusick 		else
990b2535c44Smckusick 			retAddr = instPC + 8;
991b2535c44Smckusick 		break;
992b2535c44Smckusick 
993b2535c44Smckusick 	case OP_BGTZ:
994b2535c44Smckusick 		if ((int)(regsPtr[inst.RType.rs]) > 0)
995b2535c44Smckusick 			retAddr = GetBranchDest((InstFmt *)instPC);
996b2535c44Smckusick 		else
997b2535c44Smckusick 			retAddr = instPC + 8;
998b2535c44Smckusick 		break;
999b2535c44Smckusick 
1000b2535c44Smckusick 	case OP_COP1:
1001b2535c44Smckusick 		switch (inst.RType.rs) {
1002b2535c44Smckusick 		case OP_BCx:
1003b2535c44Smckusick 		case OP_BCy:
1004b2535c44Smckusick 			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1005b2535c44Smckusick 				condition = fpcCSR & MACH_FPC_COND_BIT;
1006b2535c44Smckusick 			else
1007b2535c44Smckusick 				condition = !(fpcCSR & MACH_FPC_COND_BIT);
1008b2535c44Smckusick 			if (condition)
1009b2535c44Smckusick 				retAddr = GetBranchDest((InstFmt *)instPC);
1010b2535c44Smckusick 			else
1011b2535c44Smckusick 				retAddr = instPC + 8;
1012b2535c44Smckusick 			break;
1013b2535c44Smckusick 
1014b2535c44Smckusick 		default:
1015b2535c44Smckusick 			if (!allowNonBranch)
1016b2535c44Smckusick 				panic("MachEmulateBranch: Bad coproc branch instruction");
1017b2535c44Smckusick 			retAddr = instPC + 4;
1018b2535c44Smckusick 		}
1019b2535c44Smckusick 		break;
1020b2535c44Smckusick 
1021b2535c44Smckusick 	default:
1022b2535c44Smckusick 		if (!allowNonBranch)
1023b2535c44Smckusick 			panic("MachEmulateBranch: Non-branch instruction");
1024b2535c44Smckusick 		retAddr = instPC + 4;
1025b2535c44Smckusick 	}
1026b2535c44Smckusick #if 0
1027b2535c44Smckusick 	printf("Target addr=%x\n", retAddr);
1028b2535c44Smckusick #endif
1029b2535c44Smckusick 	return (retAddr);
1030b2535c44Smckusick }
1031b2535c44Smckusick 
1032b2535c44Smckusick unsigned
GetBranchDest(InstPtr)1033b2535c44Smckusick GetBranchDest(InstPtr)
1034b2535c44Smckusick 	InstFmt *InstPtr;
1035b2535c44Smckusick {
1036b2535c44Smckusick 	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));
1037b2535c44Smckusick }
1038b2535c44Smckusick 
1039b2535c44Smckusick /*
1040b2535c44Smckusick  * This routine is called by procxmt() to single step one instruction.
1041b2535c44Smckusick  * We do this by storing a break instruction after the current instruction,
1042b2535c44Smckusick  * resuming execution, and then restoring the old instruction.
1043b2535c44Smckusick  */
cpu_singlestep(p)1044b2535c44Smckusick cpu_singlestep(p)
1045b2535c44Smckusick 	register struct proc *p;
1046b2535c44Smckusick {
1047b2535c44Smckusick 	register unsigned va;
1048b2535c44Smckusick 	register int *locr0 = p->p_md.md_regs;
1049b2535c44Smckusick 	int i;
1050b2535c44Smckusick 
1051b2535c44Smckusick 	/* compute next address after current location */
1052b2535c44Smckusick 	va = MachEmulateBranch(locr0, locr0[PC], 0, 1);
1053b2535c44Smckusick 	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||
1054b2535c44Smckusick 	    !useracc((caddr_t)va, 4, B_READ)) {
1055b2535c44Smckusick 		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1056b2535c44Smckusick 			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
1057b2535c44Smckusick 		return (EFAULT);
1058b2535c44Smckusick 	}
1059b2535c44Smckusick 	p->p_md.md_ss_addr = va;
10603a98b5ebSutashiro 	p->p_md.md_ss_instr = fuiword((caddr_t)va);
1061b2535c44Smckusick 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1062b2535c44Smckusick 	if (i < 0) {
1063b2535c44Smckusick 		vm_offset_t sa, ea;
1064b2535c44Smckusick 		int rv;
1065b2535c44Smckusick 
1066b2535c44Smckusick 		sa = trunc_page((vm_offset_t)va);
1067b2535c44Smckusick 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
1068b2535c44Smckusick 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
1069b2535c44Smckusick 			VM_PROT_DEFAULT, FALSE);
1070b2535c44Smckusick 		if (rv == KERN_SUCCESS) {
1071b2535c44Smckusick 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1072b2535c44Smckusick 			(void) vm_map_protect(&p->p_vmspace->vm_map,
1073b2535c44Smckusick 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1074b2535c44Smckusick 		}
1075b2535c44Smckusick 	}
1076b2535c44Smckusick 	if (i < 0)
1077b2535c44Smckusick 		return (EFAULT);
1078b2535c44Smckusick 	printf("SS %s (%d): breakpoint set at %x: %x (pc %x)\n",
1079b2535c44Smckusick 		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1080b2535c44Smckusick 		p->p_md.md_ss_instr, locr0[PC]); /* XXX */
1081b2535c44Smckusick 	return (0);
1082b2535c44Smckusick }
1083b2535c44Smckusick 
1084b2535c44Smckusick /*
1085b2535c44Smckusick  * news3400 - INT0 service routine.
1086b2535c44Smckusick  *
1087b2535c44Smckusick  * INTST0 bit	4:	dma
1088b2535c44Smckusick  *		3:	slot #1
1089b2535c44Smckusick  *		2:	slot #3
1090b2535c44Smckusick  *		1:	external #1
1091b2535c44Smckusick  *		0:	external #3
1092b2535c44Smckusick  */
1093b2535c44Smckusick 
1094b2535c44Smckusick #define	LEVEL0_MASK	\
1095b2535c44Smckusick 	(INTST1_DMA|INTST1_SLOT1|INTST1_SLOT3|INTST1_EXT1|INTST1_EXT3)
1096b2535c44Smckusick 
level0_intr()1097b2535c44Smckusick level0_intr()
1098b2535c44Smckusick {
1099b2535c44Smckusick 	register int stat;
1100b2535c44Smckusick 
1101b2535c44Smckusick 	stat = *(volatile u_char *)INTST1 & LEVEL0_MASK;
1102b2535c44Smckusick 	*(u_char *)INTCLR1 = stat;
1103b2535c44Smckusick 
1104b2535c44Smckusick 	if (stat & INTST1_DMA)
1105b2535c44Smckusick 		dma_intr();
1106b2535c44Smckusick 	if (stat & INTST1_SLOT1)
1107b2535c44Smckusick 		exec_hb_intr2();
1108b2535c44Smckusick #if NEN > 0
1109b2535c44Smckusick 	if (stat & INTST1_SLOT3) {
1110b2535c44Smckusick 		int s, t;
1111b2535c44Smckusick 
1112b2535c44Smckusick 		s = splimp();
1113b2535c44Smckusick 		t = lance_intr();
1114b2535c44Smckusick 		(void) splx(s);
1115b2535c44Smckusick 		if (t == 0)
1116b2535c44Smckusick 			exec_hb_intr4();
1117b2535c44Smckusick 	}
1118b2535c44Smckusick #endif
1119b2535c44Smckusick #if NLE > 0
1120b2535c44Smckusick 	if (stat & INTST1_SLOT3) {
1121b2535c44Smckusick 		int s;
1122b2535c44Smckusick 
1123b2535c44Smckusick 		s = splimp();
1124b2535c44Smckusick 		leintr(0);
1125b2535c44Smckusick 		(void) splx(s);
1126b2535c44Smckusick 	}
1127b2535c44Smckusick #endif
1128b2535c44Smckusick 	if (stat & INTST1_EXT1)
1129b2535c44Smckusick 		print_int_stat("EXT #1");
1130b2535c44Smckusick 	if (stat & INTST1_EXT3)
1131b2535c44Smckusick 		print_int_stat("EXT #3");
1132b2535c44Smckusick }
1133b2535c44Smckusick 
1134b2535c44Smckusick /*
1135b2535c44Smckusick  * news3400 - INT1 service routine.
1136b2535c44Smckusick  *
1137b2535c44Smckusick  * INTST0 bit	1:	centro fault
1138b2535c44Smckusick  *		0:	centro busy
1139b2535c44Smckusick  * INTST1 bit	7:	beep
1140b2535c44Smckusick  *		6:	scc
1141b2535c44Smckusick  *		5:	lance
1142b2535c44Smckusick  */
1143b2535c44Smckusick 
1144b2535c44Smckusick #define LEVEL1_MASK2	(INTST0_CFLT|INTST0_CBSY)
1145b2535c44Smckusick #define LEVEL1_MASK1	(INTST1_BEEP|INTST1_SCC|INTST1_LANCE)
1146b2535c44Smckusick 
level1_intr(pc)1147b2535c44Smckusick level1_intr(pc)
1148b2535c44Smckusick 	unsigned pc;
1149b2535c44Smckusick {
1150b2535c44Smckusick 	register int stat;
1151b2535c44Smckusick 	register u_int saved_inten1 = *(u_char *)INTEN1;
1152b2535c44Smckusick 
1153b2535c44Smckusick 	*(u_char *)INTEN1 = 0;		/* disable intr: beep, lance, scc */
1154b2535c44Smckusick 
1155b2535c44Smckusick 	stat = *(volatile u_char *)INTST1 & LEVEL1_MASK1;
1156b2535c44Smckusick 	*(u_char *)INTCLR1 = stat;
1157b2535c44Smckusick 
1158b2535c44Smckusick 	stat &= saved_inten1;
1159b2535c44Smckusick 
1160b2535c44Smckusick 	if (stat & INTST1_BEEP) {
1161b2535c44Smckusick 		*(volatile u_char *)INTCLR1 = INTCLR1_BEEP;
1162b2535c44Smckusick 		print_int_stat("BEEP");
1163b2535c44Smckusick 	}
1164b2535c44Smckusick 	if (stat & INTST1_SCC) {
1165b2535c44Smckusick 		scc_intr();
1166b2535c44Smckusick 		if (saved_inten1 & *(u_char *)INTST1 & INTST1_SCC)
1167b2535c44Smckusick 			scc_intr();
1168b2535c44Smckusick 	}
1169b2535c44Smckusick #if NEN > 0
1170b2535c44Smckusick 	if (stat & INTST1_LANCE)
1171b2535c44Smckusick 		lance_intr();
1172b2535c44Smckusick #endif
1173b2535c44Smckusick #if NLE > 0
1174b2535c44Smckusick 	if (stat & INTST1_LANCE)
1175b2535c44Smckusick 		leintr(0);
1176b2535c44Smckusick #endif
1177b2535c44Smckusick 
1178b2535c44Smckusick 	*(u_char *)INTEN1 = saved_inten1;
1179b2535c44Smckusick 
1180b2535c44Smckusick #if NLP > 0
1181b2535c44Smckusick 	/*
1182b2535c44Smckusick 	 * The PARK2 cannot find centro interrupt correctly.
1183b2535c44Smckusick 	 * We must check it by reading the cause register of cpu
1184b2535c44Smckusick 	 * while other interrupts are disabled.
1185b2535c44Smckusick 	 */
1186b2535c44Smckusick 	{
1187b2535c44Smckusick 		register int causereg;
1188b2535c44Smckusick 		int s = splhigh();
1189b2535c44Smckusick 
1190b2535c44Smckusick 		causereg = get_causereg();
1191b2535c44Smckusick 		(void) splx(s);
1192b2535c44Smckusick 
1193b2535c44Smckusick 		if ((causereg & CAUSE_IP4) == 0)
1194b2535c44Smckusick 			return;
1195b2535c44Smckusick 	}
1196b2535c44Smckusick #endif
1197b2535c44Smckusick 
1198b2535c44Smckusick 	stat = (int)(*(u_char *)INTST0) & LEVEL1_MASK2;
1199b2535c44Smckusick 	*(u_char *)INTCLR0 = stat;
1200b2535c44Smckusick 
1201b2535c44Smckusick 	if (stat & INTST0_CBSY)		/* centro busy */
1202b2535c44Smckusick #if NLP > 0
1203b2535c44Smckusick 		lpxint(0);
1204b2535c44Smckusick #else
1205b2535c44Smckusick 		printf("stray intr: CBSY\n");
1206b2535c44Smckusick #endif
1207b2535c44Smckusick }
1208b2535c44Smckusick 
1209b2535c44Smckusick /*
1210b2535c44Smckusick  * DMA interrupt service routine.
1211b2535c44Smckusick  */
dma_intr()1212b2535c44Smckusick dma_intr()
1213b2535c44Smckusick {
1214b2535c44Smckusick         register volatile u_char *gsp = (u_char *)DMAC_GSTAT;
1215b2535c44Smckusick         register u_int gstat = *gsp;
1216b2535c44Smckusick         register int mrqb, i;
1217b2535c44Smckusick 
1218b2535c44Smckusick 	/*
1219b2535c44Smckusick 	 * when DMA intrrupt occurs there remain some untransferred data.
1220b2535c44Smckusick 	 * wait data transfer completion.
1221b2535c44Smckusick 	 */
1222b2535c44Smckusick 	mrqb = (gstat & (CH0_INT|CH1_INT|CH2_INT|CH3_INT)) << 1;
1223b2535c44Smckusick 	if (gstat & mrqb) {
1224b2535c44Smckusick 		/*
1225b2535c44Smckusick 		 * SHOULD USE DELAY()
1226b2535c44Smckusick 		 */
1227b2535c44Smckusick 		for (i = 0; i < 50; i++)
1228b2535c44Smckusick 			;
1229b2535c44Smckusick 		if (*gsp & mrqb)
1230b2535c44Smckusick 			printf("dma_intr: MRQ\n");
1231b2535c44Smckusick 	}
1232b2535c44Smckusick 
1233b2535c44Smckusick 	/* SCSI Dispatch */
1234b2535c44Smckusick 	if (gstat & CH_INT(CH_SCSI))
1235b2535c44Smckusick 		scintr();
1236b2535c44Smckusick 
1237b2535c44Smckusick #include "fd.h"
1238b2535c44Smckusick #if NFD > 0
1239b2535c44Smckusick         /* FDC Interrupt Dispatch */
1240b2535c44Smckusick 	if (gstat & CH_INT(CH_FDC))
1241b2535c44Smckusick 		fdc_intr(0);
1242b2535c44Smckusick #endif /* NFD > 0 */
1243b2535c44Smckusick 
1244b2535c44Smckusick #include "sb.h"
1245b2535c44Smckusick #if NSB > 0
1246b2535c44Smckusick         /* Audio Interface Dispatch */
1247b2535c44Smckusick 	sbintr(0);
1248b2535c44Smckusick #endif /* NSB > 0 */
1249b2535c44Smckusick 
1250b2535c44Smckusick         /* Video I/F Dispatch */
1251b2535c44Smckusick 	if (gstat & CH_INT(CH_VIDEO))
1252b2535c44Smckusick 		;
1253b2535c44Smckusick }
1254b2535c44Smckusick 
1255b2535c44Smckusick /*
1256b2535c44Smckusick  * SCC vector interrupt service routine.
1257b2535c44Smckusick  */
scc_intr()1258b2535c44Smckusick scc_intr()
1259b2535c44Smckusick {
1260b2535c44Smckusick 	int vec;
1261b2535c44Smckusick 	extern int scc_xint(), scc_sint(), scc_rint(), scc_cint();
1262b2535c44Smckusick 	static int (*func[])() = {
1263b2535c44Smckusick 		scc_xint,
1264b2535c44Smckusick 		scc_sint,
1265b2535c44Smckusick 		scc_rint,
1266b2535c44Smckusick 		scc_cint
1267b2535c44Smckusick 	};
1268b2535c44Smckusick 
1269b2535c44Smckusick 	vec = *(volatile u_char *)SCCVECT;
1270b2535c44Smckusick 	(*func[(vec & SCC_INT_MASK) >> 1])(vec);
1271b2535c44Smckusick }
1272b2535c44Smckusick 
print_int_stat(msg)1273b2535c44Smckusick print_int_stat(msg)
1274b2535c44Smckusick 	char *msg;
1275b2535c44Smckusick {
1276b2535c44Smckusick 	int s0 = *(volatile u_char *)INTST0;
1277b2535c44Smckusick 	int s1 = *(volatile u_char *)INTST1;
1278b2535c44Smckusick 
1279b2535c44Smckusick 	if (msg)
1280b2535c44Smckusick 		printf("%s: ", msg);
1281b2535c44Smckusick 	else
1282b2535c44Smckusick 		printf("intr: ");
1283b2535c44Smckusick 	printf("INTST0=0x%x, INTST1=0x%x.\n", s0, s1);
1284b2535c44Smckusick }
12856a898fb7Sutashiro 
traceback()12866a898fb7Sutashiro traceback()
12876a898fb7Sutashiro {
12886a898fb7Sutashiro 	u_int pc, sp;
12896a898fb7Sutashiro 
12906a898fb7Sutashiro 	getpcsp(&pc, &sp);
12916a898fb7Sutashiro 	backtr(pc, sp);
12926a898fb7Sutashiro }
12936a898fb7Sutashiro 
12946a898fb7Sutashiro #define EF_RA   	        92              /* r31: return address */
12956a898fb7Sutashiro #define KERN_REG_SIZE		(18 * 4)
12966a898fb7Sutashiro #define STAND_FRAME_SIZE	24
12976a898fb7Sutashiro #define EF_SIZE			STAND_FRAME_SIZE + KERN_REG_SIZE + 12
12986a898fb7Sutashiro 
12996a898fb7Sutashiro extern u_int MachKernGenExceptionEnd[];
13006a898fb7Sutashiro extern u_int end[];
13016a898fb7Sutashiro #define	ENDOFTXT	(end + 1)
13026a898fb7Sutashiro 
13036a898fb7Sutashiro #define VALID_TEXT(pc)	\
13046a898fb7Sutashiro 	((u_int *)MACH_CODE_START <= (u_int *)MACH_UNCACHED_TO_CACHED(pc) && \
13056a898fb7Sutashiro 	 (u_int *)MACH_UNCACHED_TO_CACHED(pc) <= (u_int *)ENDOFTXT)
13066a898fb7Sutashiro 
13076a898fb7Sutashiro #define ExceptionHandler(x) \
13086a898fb7Sutashiro 	((u_int*)MachKernGenException < (u_int*)MACH_UNCACHED_TO_CACHED(x) && \
13096a898fb7Sutashiro 	 (u_int*)MACH_UNCACHED_TO_CACHED(x) < (u_int*)MachKernGenExceptionEnd)
13106a898fb7Sutashiro 
backtr(pc,sp)13116a898fb7Sutashiro backtr(pc, sp)
13126a898fb7Sutashiro 	register u_int *pc;
13136a898fb7Sutashiro 	register caddr_t sp;
13146a898fb7Sutashiro {
13156a898fb7Sutashiro 	int fsize;
13166a898fb7Sutashiro 	u_int *getra();
13176a898fb7Sutashiro 	extern int _gp[];
13186a898fb7Sutashiro 
13196a898fb7Sutashiro 	printf("start trace back pc=%x, sp=%x, pid=%d[%s]\n",
13206a898fb7Sutashiro 		pc, sp, curproc->p_pid, curproc->p_comm);
13216a898fb7Sutashiro 
13226a898fb7Sutashiro 	while (VALID_TEXT(pc)) {
13236a898fb7Sutashiro 		if (sp >= (caddr_t)KERNELSTACK || sp < (caddr_t)UADDR) {
13246a898fb7Sutashiro 			printf("stack exhausted (sp=0x%x)\n", sp);
13256a898fb7Sutashiro 			break;
13266a898fb7Sutashiro 		}
13276a898fb7Sutashiro 		if (ExceptionHandler(pc)) {
13286a898fb7Sutashiro 			pc = (u_int *)(*((u_int *)&sp[EF_RA]));
13296a898fb7Sutashiro 			sp += EF_SIZE;
13306a898fb7Sutashiro 			printf("trapped from pc=%x, sp=%x\n", pc, sp);
13316a898fb7Sutashiro 		} else {
13326a898fb7Sutashiro 			pc = getra(pc, sp, &fsize);
13336a898fb7Sutashiro 			sp += fsize;
13346a898fb7Sutashiro 			printf("called from pc=%x, sp=%x\n", pc, sp);
13356a898fb7Sutashiro 		}
13366a898fb7Sutashiro 	}
13376a898fb7Sutashiro 	printf("trace back END. pid=%d[%s]\n", curproc->p_pid, curproc->p_comm);
13386a898fb7Sutashiro }
13396a898fb7Sutashiro 
13406a898fb7Sutashiro #define	NPCSTOCK	128
13416a898fb7Sutashiro 
13426a898fb7Sutashiro u_int *
getra(pc,sp,fsize)13436a898fb7Sutashiro getra(pc, sp, fsize)
13446a898fb7Sutashiro 	register int *pc;
13456a898fb7Sutashiro 	register caddr_t sp;
13466a898fb7Sutashiro 	int *fsize;
13476a898fb7Sutashiro {
13486a898fb7Sutashiro 	u_int regs[32];
13496a898fb7Sutashiro 	int *opcs[NPCSTOCK];
13506a898fb7Sutashiro 	register int i, nbpc = 0;
13516a898fb7Sutashiro 	int printed = 0;
13526a898fb7Sutashiro 	InstFmt I;
13536a898fb7Sutashiro 
13546a898fb7Sutashiro 	*fsize = 0;
13556a898fb7Sutashiro 	for (i = 0; i < 32; i++) regs[i] = 0;
13566a898fb7Sutashiro 	for (; (u_int*)MACH_UNCACHED_TO_CACHED(pc) < (u_int*)ENDOFTXT; pc++) {
13576a898fb7Sutashiro 		I.word = *pc;
13586a898fb7Sutashiro 		switch (I.IType.op) {
13596a898fb7Sutashiro 
13606a898fb7Sutashiro 		case OP_ADDIU:
13616a898fb7Sutashiro 			/* sp += fsize */
13626a898fb7Sutashiro 			if (I.IType.rs == SP && I.IType.rt == SP)
13636a898fb7Sutashiro 				*fsize = (u_short)I.IType.imm;
13646a898fb7Sutashiro 			break;
13656a898fb7Sutashiro 
13666a898fb7Sutashiro 		case OP_LW:
13676a898fb7Sutashiro 			if (I.IType.rs != SP)
13686a898fb7Sutashiro 				break;
13696a898fb7Sutashiro 			regs[I.IType.rt] = *(u_int *)&sp[(short)I.IType.imm];
13706a898fb7Sutashiro 			break;
13716a898fb7Sutashiro 
13726a898fb7Sutashiro 		case OP_BEQ:
13736a898fb7Sutashiro 			if (I.IType.rs != ZERO || I.IType.rt != ZERO)
13746a898fb7Sutashiro 				break;
13756a898fb7Sutashiro 			for (i = 0; i < nbpc; i++)
13766a898fb7Sutashiro 				if (pc == opcs[i]) {
13776a898fb7Sutashiro 					/*
13786a898fb7Sutashiro 					 * Brach constructs infinite loop.
13796a898fb7Sutashiro 					 */
13806a898fb7Sutashiro 					if (!printed) {
13816a898fb7Sutashiro 						printf("branch loop\n");
13826a898fb7Sutashiro 						printed = 1;
13836a898fb7Sutashiro 					}
13846a898fb7Sutashiro 					break;
13856a898fb7Sutashiro 				}
13866a898fb7Sutashiro 			if (i == nbpc) {
13876a898fb7Sutashiro 				opcs[nbpc] = pc;
13886a898fb7Sutashiro 				nbpc = imin(nbpc + 1, NPCSTOCK);
13896a898fb7Sutashiro 				pc = pc + (short)I.IType.imm;
13906a898fb7Sutashiro 			}
13916a898fb7Sutashiro 			break;
13926a898fb7Sutashiro 
13936a898fb7Sutashiro 		default:
13946a898fb7Sutashiro 			break;
13956a898fb7Sutashiro 		}
13966a898fb7Sutashiro 
13976a898fb7Sutashiro 		I.word = *(pc - 1);
13986a898fb7Sutashiro 		if (I.RType.op == OP_SPECIAL && I.RType.func == OP_JR)
13996a898fb7Sutashiro 			return ((int *)regs[I.RType.rs]);
14006a898fb7Sutashiro 	}
14016a898fb7Sutashiro 	printf("pc run out of TEXT\n");
14026a898fb7Sutashiro 	return (0);
14036a898fb7Sutashiro }
1404