xref: /original-bsd/sys/pmax/pmax/trap.c (revision 759b7897)
1a06587f5Smckusick /*
2a06587f5Smckusick  * Copyright (c) 1988 University of Utah.
3faebe45cSbostic  * Copyright (c) 1992, 1993
4faebe45cSbostic  *	The Regents of the University of California.  All rights reserved.
5a06587f5Smckusick  *
6a06587f5Smckusick  * This code is derived from software contributed to Berkeley by
7a06587f5Smckusick  * the Systems Programming Group of the University of Utah Computer
8a06587f5Smckusick  * Science Department and Ralph Campbell.
9a06587f5Smckusick  *
10a06587f5Smckusick  * %sccs.include.redist.c%
11a06587f5Smckusick  *
12a06587f5Smckusick  * from: Utah $Hdr: trap.c 1.32 91/04/06$
13a06587f5Smckusick  *
14*759b7897Sralph  *	@(#)trap.c	8.7 (Berkeley) 06/02/95
15a06587f5Smckusick  */
16a06587f5Smckusick 
17327b2279Sbostic #include <sys/param.h>
18327b2279Sbostic #include <sys/systm.h>
19327b2279Sbostic #include <sys/proc.h>
20327b2279Sbostic #include <sys/kernel.h>
21327b2279Sbostic #include <sys/signalvar.h>
22327b2279Sbostic #include <sys/syscall.h>
23327b2279Sbostic #include <sys/user.h>
24327b2279Sbostic #include <sys/buf.h>
25a06587f5Smckusick #ifdef KTRACE
26327b2279Sbostic #include <sys/ktrace.h>
27a06587f5Smckusick #endif
28327b2279Sbostic #include <net/netisr.h>
29a06587f5Smckusick 
30327b2279Sbostic #include <machine/trap.h>
31327b2279Sbostic #include <machine/psl.h>
32327b2279Sbostic #include <machine/reg.h>
33327b2279Sbostic #include <machine/cpu.h>
34327b2279Sbostic #include <machine/pte.h>
35327b2279Sbostic #include <machine/mips_opcode.h>
36a06587f5Smckusick 
37327b2279Sbostic #include <vm/vm.h>
38327b2279Sbostic #include <vm/vm_kern.h>
39327b2279Sbostic #include <vm/vm_page.h>
40a06587f5Smckusick 
41a2916846Sralph #include <pmax/pmax/clockreg.h>
42a2916846Sralph #include <pmax/pmax/kn01.h>
43a2916846Sralph #include <pmax/pmax/kn02.h>
44a2916846Sralph #include <pmax/pmax/kmin.h>
45a2916846Sralph #include <pmax/pmax/maxine.h>
46ab61b8b0Sralph #include <pmax/pmax/kn03.h>
47a2916846Sralph #include <pmax/pmax/asic.h>
48a2916846Sralph #include <pmax/pmax/turbochannel.h>
49a2916846Sralph 
50348607e6Sralph #include <pmax/stand/dec_prom.h>
51348607e6Sralph 
52a2916846Sralph #include <asc.h>
53a2916846Sralph #include <sii.h>
54a2916846Sralph #include <le.h>
55a2916846Sralph #include <dc.h>
56a2916846Sralph 
57a06587f5Smckusick struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */
58a06587f5Smckusick 
59a06587f5Smckusick extern void MachKernGenException();
60a06587f5Smckusick extern void MachUserGenException();
61a06587f5Smckusick extern void MachKernIntr();
62a06587f5Smckusick extern void MachUserIntr();
63a06587f5Smckusick extern void MachTLBModException();
64a06587f5Smckusick extern void MachTLBMissException();
65a0ea849cSralph extern unsigned MachEmulateBranch();
66a06587f5Smckusick 
67a06587f5Smckusick void (*machExceptionTable[])() = {
68a06587f5Smckusick /*
69a06587f5Smckusick  * The kernel exception handlers.
70a06587f5Smckusick  */
71a06587f5Smckusick 	MachKernIntr,			/* external interrupt */
72a06587f5Smckusick 	MachKernGenException,		/* TLB modification */
73a06587f5Smckusick 	MachTLBMissException,		/* TLB miss (load or instr. fetch) */
74a06587f5Smckusick 	MachTLBMissException,		/* TLB miss (store) */
75a06587f5Smckusick 	MachKernGenException,		/* address error (load or I-fetch) */
76a06587f5Smckusick 	MachKernGenException,		/* address error (store) */
77a06587f5Smckusick 	MachKernGenException,		/* bus error (I-fetch) */
78a06587f5Smckusick 	MachKernGenException,		/* bus error (load or store) */
79a06587f5Smckusick 	MachKernGenException,		/* system call */
80a06587f5Smckusick 	MachKernGenException,		/* breakpoint */
81a06587f5Smckusick 	MachKernGenException,		/* reserved instruction */
82a06587f5Smckusick 	MachKernGenException,		/* coprocessor unusable */
83a06587f5Smckusick 	MachKernGenException,		/* arithmetic overflow */
84a06587f5Smckusick 	MachKernGenException,		/* reserved */
85a06587f5Smckusick 	MachKernGenException,		/* reserved */
86a06587f5Smckusick 	MachKernGenException,		/* reserved */
87a06587f5Smckusick /*
88a06587f5Smckusick  * The user exception handlers.
89a06587f5Smckusick  */
90a06587f5Smckusick 	MachUserIntr,
91a06587f5Smckusick 	MachUserGenException,
92a06587f5Smckusick 	MachUserGenException,
93a06587f5Smckusick 	MachUserGenException,
94a06587f5Smckusick 	MachUserGenException,
95a06587f5Smckusick 	MachUserGenException,
96a06587f5Smckusick 	MachUserGenException,
97a06587f5Smckusick 	MachUserGenException,
98a06587f5Smckusick 	MachUserGenException,
99a06587f5Smckusick 	MachUserGenException,
100a06587f5Smckusick 	MachUserGenException,
101a06587f5Smckusick 	MachUserGenException,
102a06587f5Smckusick 	MachUserGenException,
103a06587f5Smckusick 	MachUserGenException,
104a06587f5Smckusick 	MachUserGenException,
105a06587f5Smckusick 	MachUserGenException,
106a06587f5Smckusick };
107a06587f5Smckusick 
108a06587f5Smckusick char	*trap_type[] = {
109a06587f5Smckusick 	"external interrupt",
110a06587f5Smckusick 	"TLB modification",
111a06587f5Smckusick 	"TLB miss (load or instr. fetch)",
112a06587f5Smckusick 	"TLB miss (store)",
113a06587f5Smckusick 	"address error (load or I-fetch)",
114a06587f5Smckusick 	"address error (store)",
115a06587f5Smckusick 	"bus error (I-fetch)",
116a06587f5Smckusick 	"bus error (load or store)",
117a06587f5Smckusick 	"system call",
118a06587f5Smckusick 	"breakpoint",
119a06587f5Smckusick 	"reserved instruction",
120a06587f5Smckusick 	"coprocessor unusable",
121a06587f5Smckusick 	"arithmetic overflow",
122a06587f5Smckusick 	"reserved 13",
123a06587f5Smckusick 	"reserved 14",
124a06587f5Smckusick 	"reserved 15",
125a06587f5Smckusick };
126a06587f5Smckusick 
127a06587f5Smckusick #ifdef DEBUG
128a06587f5Smckusick #define TRAPSIZE	10
129a06587f5Smckusick struct trapdebug {		/* trap history buffer for debugging */
130a06587f5Smckusick 	u_int	status;
131a06587f5Smckusick 	u_int	cause;
132a06587f5Smckusick 	u_int	vadr;
133a06587f5Smckusick 	u_int	pc;
134a06587f5Smckusick 	u_int	ra;
135a06587f5Smckusick 	u_int	code;
136a06587f5Smckusick } trapdebug[TRAPSIZE], *trp = trapdebug;
137843a209bSmckusick 
138843a209bSmckusick u_int	intr_level;		/* number of nested interrupts */
139a06587f5Smckusick #endif
140a06587f5Smckusick 
141a2916846Sralph static void pmax_errintr();
142a2916846Sralph static void kn02_errintr(), kn02ba_errintr();
143ab61b8b0Sralph #ifdef DS5000_240
144ab61b8b0Sralph static void kn03_errintr();
145ab61b8b0Sralph #endif
146a2916846Sralph static unsigned kn02ba_recover_erradr();
147a2916846Sralph extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
148a2916846Sralph extern u_long kmin_tc3_imask, xine_tc3_imask;
149348607e6Sralph extern const struct callback *callv;
150ab61b8b0Sralph #ifdef DS5000_240
151ab61b8b0Sralph extern u_long kn03_tc3_imask;
152ab61b8b0Sralph #endif
153a2916846Sralph int (*pmax_hardware_intr)() = (int (*)())0;
154a2916846Sralph extern volatile struct chiptime *Mach_clock_addr;
155*759b7897Sralph extern long intrcnt[];
156a2916846Sralph 
157a06587f5Smckusick /*
158a06587f5Smckusick  * Handle an exception.
159a06587f5Smckusick  * Called from MachKernGenException() or MachUserGenException()
160a06587f5Smckusick  * when a processor trap occurs.
161a06587f5Smckusick  * In the case of a kernel trap, we return the pc where to resume if
162a06587f5Smckusick  * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
163a06587f5Smckusick  */
164a06587f5Smckusick unsigned
trap(statusReg,causeReg,vadr,pc,args)165a0ea849cSralph trap(statusReg, causeReg, vadr, pc, args)
166a06587f5Smckusick 	unsigned statusReg;	/* status register at time of the exception */
167a06587f5Smckusick 	unsigned causeReg;	/* cause register at time of exception */
168a06587f5Smckusick 	unsigned vadr;		/* address (if any) the fault occured on */
169a06587f5Smckusick 	unsigned pc;		/* program counter where to continue */
170a06587f5Smckusick {
171a06587f5Smckusick 	register int type, i;
172a06587f5Smckusick 	unsigned ucode = 0;
173a06587f5Smckusick 	register struct proc *p = curproc;
174a2823b70Sralph 	u_quad_t sticks;
175a06587f5Smckusick 	vm_prot_t ftype;
176a06587f5Smckusick 	extern unsigned onfault_table[];
177a06587f5Smckusick 
178a06587f5Smckusick #ifdef DEBUG
179a06587f5Smckusick 	trp->status = statusReg;
180a06587f5Smckusick 	trp->cause = causeReg;
181a06587f5Smckusick 	trp->vadr = vadr;
182a06587f5Smckusick 	trp->pc = pc;
183a43518feSralph 	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
184a43518feSralph 		p->p_md.md_regs[RA];
185a06587f5Smckusick 	trp->code = 0;
186a06587f5Smckusick 	if (++trp == &trapdebug[TRAPSIZE])
187a06587f5Smckusick 		trp = trapdebug;
188a06587f5Smckusick #endif
189a06587f5Smckusick 
190a06587f5Smckusick 	cnt.v_trap++;
191a06587f5Smckusick 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
192a06587f5Smckusick 	if (USERMODE(statusReg)) {
193a06587f5Smckusick 		type |= T_USER;
194a2823b70Sralph 		sticks = p->p_sticks;
195a06587f5Smckusick 	}
196a06587f5Smckusick 
197a06587f5Smckusick 	/*
198a06587f5Smckusick 	 * Enable hardware interrupts if they were on before.
199a06587f5Smckusick 	 * We only respond to software interrupts when returning to user mode.
200a06587f5Smckusick 	 */
201a06587f5Smckusick 	if (statusReg & MACH_SR_INT_ENA_PREV)
202a06587f5Smckusick 		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);
203a06587f5Smckusick 
204a06587f5Smckusick 	switch (type) {
205a06587f5Smckusick 	case T_TLB_MOD:
206a2823b70Sralph 		/* check for kernel address */
207a06587f5Smckusick 		if ((int)vadr < 0) {
208a06587f5Smckusick 			register pt_entry_t *pte;
209a06587f5Smckusick 			register unsigned entry;
210a06587f5Smckusick 			register vm_offset_t pa;
211a06587f5Smckusick 
212a06587f5Smckusick 			pte = kvtopte(vadr);
213a06587f5Smckusick 			entry = pte->pt_entry;
2148f497010Sralph #ifdef DIAGNOSTIC
2158f497010Sralph 			if (!(entry & PG_V) || (entry & PG_M))
2168f497010Sralph 				panic("trap: ktlbmod: invalid pte");
2178f497010Sralph #endif
218a06587f5Smckusick 			if (entry & PG_RO) {
219a06587f5Smckusick 				/* write to read only page in the kernel */
220a06587f5Smckusick 				ftype = VM_PROT_WRITE;
221a06587f5Smckusick 				goto kernel_fault;
222a06587f5Smckusick 			}
223a06587f5Smckusick 			entry |= PG_M;
224a06587f5Smckusick 			pte->pt_entry = entry;
2258f497010Sralph 			vadr &= ~PGOFSET;
226fe638d35Sralph 			MachTLBUpdate(vadr, entry);
227a06587f5Smckusick 			pa = entry & PG_FRAME;
2288f497010Sralph #ifdef ATTR
2298f497010Sralph 			pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
2308f497010Sralph #else
231a06587f5Smckusick 			if (!IS_VM_PHYSADDR(pa))
2328f497010Sralph 				panic("trap: ktlbmod: unmanaged page");
233ea43aba3Sralph 			PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
234a06587f5Smckusick #endif
235a06587f5Smckusick 			return (pc);
236a06587f5Smckusick 		}
237a06587f5Smckusick 		/* FALLTHROUGH */
238a06587f5Smckusick 
239a06587f5Smckusick 	case T_TLB_MOD+T_USER:
240a06587f5Smckusick 	    {
2418f497010Sralph 		register pt_entry_t *pte;
2428f497010Sralph 		register unsigned entry;
2438f497010Sralph 		register vm_offset_t pa;
2448f497010Sralph 		pmap_t pmap = &p->p_vmspace->vm_pmap;
245a06587f5Smckusick 
2468f497010Sralph 		if (!(pte = pmap_segmap(pmap, vadr)))
2478f497010Sralph 			panic("trap: utlbmod: invalid segmap");
2488f497010Sralph 		pte += (vadr >> PGSHIFT) & (NPTEPG - 1);
2498f497010Sralph 		entry = pte->pt_entry;
2508f497010Sralph #ifdef DIAGNOSTIC
2518f497010Sralph 		if (!(entry & PG_V) || (entry & PG_M))
2528f497010Sralph 			panic("trap: utlbmod: invalid pte");
253a06587f5Smckusick #endif
2548f497010Sralph 		if (entry & PG_RO) {
2558f497010Sralph 			/* write to read only page */
256a06587f5Smckusick 			ftype = VM_PROT_WRITE;
257a06587f5Smckusick 			goto dofault;
258a06587f5Smckusick 		}
2598f497010Sralph 		entry |= PG_M;
2608f497010Sralph 		pte->pt_entry = entry;
2618f497010Sralph 		vadr = (vadr & ~PGOFSET) |
2628f497010Sralph 			(pmap->pm_tlbpid << VMMACH_TLB_PID_SHIFT);
263fe638d35Sralph 		MachTLBUpdate(vadr, entry);
2648f497010Sralph 		pa = entry & PG_FRAME;
265a06587f5Smckusick #ifdef ATTR
2668f497010Sralph 		pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
267a06587f5Smckusick #else
268a06587f5Smckusick 		if (!IS_VM_PHYSADDR(pa))
2698f497010Sralph 			panic("trap: utlbmod: unmanaged page");
270ea43aba3Sralph 		PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
271a06587f5Smckusick #endif
272a06587f5Smckusick 		if (!USERMODE(statusReg))
273a06587f5Smckusick 			return (pc);
274a06587f5Smckusick 		goto out;
275a06587f5Smckusick 	    }
276a06587f5Smckusick 
277a06587f5Smckusick 	case T_TLB_LD_MISS:
278a06587f5Smckusick 	case T_TLB_ST_MISS:
279a06587f5Smckusick 		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
280a2823b70Sralph 		/* check for kernel address */
281a06587f5Smckusick 		if ((int)vadr < 0) {
282a06587f5Smckusick 			register vm_offset_t va;
283a06587f5Smckusick 			int rv;
284a06587f5Smckusick 
285a06587f5Smckusick 		kernel_fault:
286a06587f5Smckusick 			va = trunc_page((vm_offset_t)vadr);
287a06587f5Smckusick 			rv = vm_fault(kernel_map, va, ftype, FALSE);
288a06587f5Smckusick 			if (rv == KERN_SUCCESS)
289a06587f5Smckusick 				return (pc);
290a06587f5Smckusick 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
291a06587f5Smckusick 				((struct pcb *)UADDR)->pcb_onfault = 0;
292a06587f5Smckusick 				return (onfault_table[i]);
293a06587f5Smckusick 			}
294a06587f5Smckusick 			goto err;
295a06587f5Smckusick 		}
296ea43aba3Sralph 		/*
297ea43aba3Sralph 		 * It is an error for the kernel to access user space except
298ea43aba3Sralph 		 * through the copyin/copyout routines.
299ea43aba3Sralph 		 */
300ea43aba3Sralph 		if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)
301ea43aba3Sralph 			goto err;
302a2823b70Sralph 		/* check for fuswintr() or suswintr() getting a page fault */
303ea43aba3Sralph 		if (i == 4)
304a2823b70Sralph 			return (onfault_table[i]);
305a06587f5Smckusick 		goto dofault;
306a06587f5Smckusick 
307a06587f5Smckusick 	case T_TLB_LD_MISS+T_USER:
308a06587f5Smckusick 		ftype = VM_PROT_READ;
309a06587f5Smckusick 		goto dofault;
310a06587f5Smckusick 
311a06587f5Smckusick 	case T_TLB_ST_MISS+T_USER:
312a06587f5Smckusick 		ftype = VM_PROT_WRITE;
313a06587f5Smckusick 	dofault:
314a06587f5Smckusick 	    {
315a06587f5Smckusick 		register vm_offset_t va;
3168f497010Sralph 		register struct vmspace *vm;
3178f497010Sralph 		register vm_map_t map;
318a06587f5Smckusick 		int rv;
319a06587f5Smckusick 
3208f497010Sralph 		vm = p->p_vmspace;
3218f497010Sralph 		map = &vm->vm_map;
322a06587f5Smckusick 		va = trunc_page((vm_offset_t)vadr);
323a06587f5Smckusick 		rv = vm_fault(map, va, ftype, FALSE);
324a06587f5Smckusick 		/*
325a06587f5Smckusick 		 * If this was a stack access we keep track of the maximum
326a06587f5Smckusick 		 * accessed stack size.  Also, if vm_fault gets a protection
327a06587f5Smckusick 		 * failure it is due to accessing the stack region outside
328a06587f5Smckusick 		 * the current limit and we need to reflect that as an access
329a06587f5Smckusick 		 * error.
330a06587f5Smckusick 		 */
331a06587f5Smckusick 		if ((caddr_t)va >= vm->vm_maxsaddr) {
332a06587f5Smckusick 			if (rv == KERN_SUCCESS) {
333a06587f5Smckusick 				unsigned nss;
334a06587f5Smckusick 
335a06587f5Smckusick 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
336a06587f5Smckusick 				if (nss > vm->vm_ssize)
337a06587f5Smckusick 					vm->vm_ssize = nss;
338a06587f5Smckusick 			} else if (rv == KERN_PROTECTION_FAILURE)
339a06587f5Smckusick 				rv = KERN_INVALID_ADDRESS;
340a06587f5Smckusick 		}
341a06587f5Smckusick 		if (rv == KERN_SUCCESS) {
342a06587f5Smckusick 			if (!USERMODE(statusReg))
343a06587f5Smckusick 				return (pc);
344a06587f5Smckusick 			goto out;
345a06587f5Smckusick 		}
346a06587f5Smckusick 		if (!USERMODE(statusReg)) {
347a06587f5Smckusick 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
348a06587f5Smckusick 				((struct pcb *)UADDR)->pcb_onfault = 0;
349a06587f5Smckusick 				return (onfault_table[i]);
350a06587f5Smckusick 			}
351a06587f5Smckusick 			goto err;
352a06587f5Smckusick 		}
353a06587f5Smckusick 		ucode = vadr;
354a06587f5Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
355a06587f5Smckusick 		break;
356a06587f5Smckusick 	    }
357a06587f5Smckusick 
358a06587f5Smckusick 	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
359a06587f5Smckusick 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
360a06587f5Smckusick 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
361a06587f5Smckusick 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
362a06587f5Smckusick 		i = SIGSEGV;
363a06587f5Smckusick 		break;
364a06587f5Smckusick 
365a06587f5Smckusick 	case T_SYSCALL+T_USER:
366a06587f5Smckusick 	    {
367a43518feSralph 		register int *locr0 = p->p_md.md_regs;
368a06587f5Smckusick 		register struct sysent *callp;
369d5322df6Smckusick 		unsigned int code;
370d5322df6Smckusick 		int numsys;
371a06587f5Smckusick 		struct args {
372a06587f5Smckusick 			int i[8];
373a06587f5Smckusick 		} args;
374a06587f5Smckusick 		int rval[2];
375a06587f5Smckusick 		struct sysent *systab;
376a06587f5Smckusick 		extern int nsysent;
377a06587f5Smckusick #ifdef ULTRIXCOMPAT
378a06587f5Smckusick 		extern struct sysent ultrixsysent[];
379a06587f5Smckusick 		extern int ultrixnsysent;
380a06587f5Smckusick #endif
381a06587f5Smckusick 
382a06587f5Smckusick 		cnt.v_syscall++;
383a06587f5Smckusick 		/* compute next PC after syscall instruction */
384a06587f5Smckusick 		if ((int)causeReg < 0)
385a06587f5Smckusick 			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
386a06587f5Smckusick 		else
387a06587f5Smckusick 			locr0[PC] += 4;
388a06587f5Smckusick 		systab = sysent;
389a06587f5Smckusick 		numsys = nsysent;
390a06587f5Smckusick #ifdef ULTRIXCOMPAT
391a06587f5Smckusick 		if (p->p_md.md_flags & MDP_ULTRIX) {
392a06587f5Smckusick 			systab = ultrixsysent;
393a06587f5Smckusick 			numsys = ultrixnsysent;
394a06587f5Smckusick 		}
395a06587f5Smckusick #endif
396a06587f5Smckusick 		code = locr0[V0];
397d1029299Sralph 		switch (code) {
398c15eaae5Smckusick 		case SYS_syscall:
399d1029299Sralph 			/*
400d1029299Sralph 			 * Code is first argument, followed by actual args.
401d1029299Sralph 			 */
402a06587f5Smckusick 			code = locr0[A0];
403a06587f5Smckusick 			if (code >= numsys)
404c15eaae5Smckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
405a06587f5Smckusick 			else
406a06587f5Smckusick 				callp = &systab[code];
407*759b7897Sralph 			i = callp->sy_argsize;
408a06587f5Smckusick 			args.i[0] = locr0[A1];
409a06587f5Smckusick 			args.i[1] = locr0[A2];
410a06587f5Smckusick 			args.i[2] = locr0[A3];
411*759b7897Sralph 			if (i > 3 * sizeof(register_t)) {
412a06587f5Smckusick 				i = copyin((caddr_t)(locr0[SP] +
413*759b7897Sralph 						4 * sizeof(register_t)),
414a06587f5Smckusick 					(caddr_t)&args.i[3],
415*759b7897Sralph 					(u_int)(i - 3 * sizeof(register_t)));
416a06587f5Smckusick 				if (i) {
417a06587f5Smckusick 					locr0[V0] = i;
418a06587f5Smckusick 					locr0[A3] = 1;
419a06587f5Smckusick #ifdef KTRACE
420a06587f5Smckusick 					if (KTRPOINT(p, KTR_SYSCALL))
421a06587f5Smckusick 						ktrsyscall(p->p_tracep, code,
422*759b7897Sralph 							callp->sy_argsize,
423*759b7897Sralph 							args.i);
424a06587f5Smckusick #endif
425a06587f5Smckusick 					goto done;
426a06587f5Smckusick 				}
427a06587f5Smckusick 			}
428d1029299Sralph 			break;
429d1029299Sralph 
430c15eaae5Smckusick 		case SYS___syscall:
431d1029299Sralph 			/*
432c15eaae5Smckusick 			 * Like syscall, but code is a quad, so as to maintain
433d1029299Sralph 			 * quad alignment for the rest of the arguments.
434d1029299Sralph 			 */
435d1029299Sralph 			code = locr0[A0 + _QUAD_LOWWORD];
436d5322df6Smckusick 			if (code >= numsys)
437c15eaae5Smckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
438d1029299Sralph 			else
439d1029299Sralph 				callp = &systab[code];
440*759b7897Sralph 			i = callp->sy_argsize;
441d1029299Sralph 			args.i[0] = locr0[A2];
442d1029299Sralph 			args.i[1] = locr0[A3];
443*759b7897Sralph 			if (i > 2 * sizeof(register_t)) {
444d1029299Sralph 				i = copyin((caddr_t)(locr0[SP] +
445*759b7897Sralph 						4 * sizeof(register_t)),
446d1029299Sralph 					(caddr_t)&args.i[2],
447*759b7897Sralph 					(u_int)(i - 2 * sizeof(register_t)));
448d1029299Sralph 				if (i) {
449d1029299Sralph 					locr0[V0] = i;
450d1029299Sralph 					locr0[A3] = 1;
451d1029299Sralph #ifdef KTRACE
452d1029299Sralph 					if (KTRPOINT(p, KTR_SYSCALL))
453d1029299Sralph 						ktrsyscall(p->p_tracep, code,
454*759b7897Sralph 							callp->sy_argsize,
455*759b7897Sralph 							args.i);
456d1029299Sralph #endif
457d1029299Sralph 					goto done;
458d1029299Sralph 				}
459d1029299Sralph 			}
460d1029299Sralph 			break;
461d1029299Sralph 
462d1029299Sralph 		default:
463d1029299Sralph 			if (code >= numsys)
464c15eaae5Smckusick 				callp = &systab[SYS_syscall]; /* (illegal) */
465a06587f5Smckusick 			else
466a06587f5Smckusick 				callp = &systab[code];
467*759b7897Sralph 			i = callp->sy_argsize;
468a06587f5Smckusick 			args.i[0] = locr0[A0];
469a06587f5Smckusick 			args.i[1] = locr0[A1];
470a06587f5Smckusick 			args.i[2] = locr0[A2];
471a06587f5Smckusick 			args.i[3] = locr0[A3];
472*759b7897Sralph 			if (i > 4 * sizeof(register_t)) {
473a06587f5Smckusick 				i = copyin((caddr_t)(locr0[SP] +
474*759b7897Sralph 						4 * sizeof(register_t)),
475a06587f5Smckusick 					(caddr_t)&args.i[4],
476*759b7897Sralph 					(u_int)(i - 4 * sizeof(register_t)));
477a06587f5Smckusick 				if (i) {
478a06587f5Smckusick 					locr0[V0] = i;
479a06587f5Smckusick 					locr0[A3] = 1;
480a06587f5Smckusick #ifdef KTRACE
481a06587f5Smckusick 					if (KTRPOINT(p, KTR_SYSCALL))
482a06587f5Smckusick 						ktrsyscall(p->p_tracep, code,
483*759b7897Sralph 							callp->sy_argsize,
484*759b7897Sralph 							args.i);
485a06587f5Smckusick #endif
486a06587f5Smckusick 					goto done;
487a06587f5Smckusick 				}
488a06587f5Smckusick 			}
489a06587f5Smckusick 		}
490a06587f5Smckusick #ifdef KTRACE
491a06587f5Smckusick 		if (KTRPOINT(p, KTR_SYSCALL))
492*759b7897Sralph 			ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i);
493a06587f5Smckusick #endif
494a06587f5Smckusick 		rval[0] = 0;
495a06587f5Smckusick 		rval[1] = locr0[V1];
496a06587f5Smckusick #ifdef DEBUG
497a06587f5Smckusick 		if (trp == trapdebug)
498a06587f5Smckusick 			trapdebug[TRAPSIZE - 1].code = code;
499a06587f5Smckusick 		else
500a06587f5Smckusick 			trp[-1].code = code;
501a06587f5Smckusick #endif
502a06587f5Smckusick 		i = (*callp->sy_call)(p, &args, rval);
503a06587f5Smckusick 		/*
504a06587f5Smckusick 		 * Reinitialize proc pointer `p' as it may be different
505a06587f5Smckusick 		 * if this is a child returning from fork syscall.
506a06587f5Smckusick 		 */
507a06587f5Smckusick 		p = curproc;
508a43518feSralph 		locr0 = p->p_md.md_regs;
509a06587f5Smckusick #ifdef DEBUG
510a06587f5Smckusick 		{ int s;
511a06587f5Smckusick 		s = splhigh();
512a06587f5Smckusick 		trp->status = statusReg;
513a06587f5Smckusick 		trp->cause = causeReg;
514a06587f5Smckusick 		trp->vadr = locr0[SP];
515a06587f5Smckusick 		trp->pc = locr0[PC];
516a06587f5Smckusick 		trp->ra = locr0[RA];
517a06587f5Smckusick 		trp->code = -code;
518a06587f5Smckusick 		if (++trp == &trapdebug[TRAPSIZE])
519a06587f5Smckusick 			trp = trapdebug;
520a06587f5Smckusick 		splx(s);
521a06587f5Smckusick 		}
522a06587f5Smckusick #endif
523d1029299Sralph 		switch (i) {
524d1029299Sralph 		case 0:
525a06587f5Smckusick 			locr0[V0] = rval[0];
526a06587f5Smckusick 			locr0[V1] = rval[1];
527a06587f5Smckusick 			locr0[A3] = 0;
528d1029299Sralph 			break;
529d1029299Sralph 
530d1029299Sralph 		case ERESTART:
531d1029299Sralph 			locr0[PC] = pc;
532d1029299Sralph 			break;
533d1029299Sralph 
534d1029299Sralph 		case EJUSTRETURN:
535d1029299Sralph 			break;	/* nothing to do */
536d1029299Sralph 
537d1029299Sralph 		default:
538d1029299Sralph 			locr0[V0] = i;
539d1029299Sralph 			locr0[A3] = 1;
540a06587f5Smckusick 		}
541a06587f5Smckusick 	done:
542a06587f5Smckusick #ifdef KTRACE
543a06587f5Smckusick 		if (KTRPOINT(p, KTR_SYSRET))
544a06587f5Smckusick 			ktrsysret(p->p_tracep, code, i, rval[0]);
545a06587f5Smckusick #endif
546a06587f5Smckusick 		goto out;
547a06587f5Smckusick 	    }
548a06587f5Smckusick 
549a06587f5Smckusick 	case T_BREAK+T_USER:
550a0ea849cSralph 	    {
551a0ea849cSralph 		register unsigned va, instr;
552a0ea849cSralph 
553a0ea849cSralph 		/* compute address of break instruction */
554a0ea849cSralph 		va = pc;
555a0ea849cSralph 		if ((int)causeReg < 0)
556a0ea849cSralph 			va += 4;
557a0ea849cSralph 
558a0ea849cSralph 		/* read break instruction */
55943e69fa3Sralph 		instr = fuiword((caddr_t)va);
5604ab0a127Smckusick #if 0
5614ab0a127Smckusick 		printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
5624ab0a127Smckusick 			p->p_comm, p->p_pid, instr, pc,
5634ab0a127Smckusick 			p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
5644ab0a127Smckusick #endif
565a0ea849cSralph #ifdef KADB
566a0ea849cSralph 		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)
567a0ea849cSralph 			goto err;
568a0ea849cSralph #endif
569a0ea849cSralph 		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {
570a06587f5Smckusick 			i = SIGTRAP;
571a06587f5Smckusick 			break;
572a0ea849cSralph 		}
573a0ea849cSralph 
574a0ea849cSralph 		/* restore original instruction and clear BP  */
575a0ea849cSralph 		i = suiword((caddr_t)va, p->p_md.md_ss_instr);
576a0ea849cSralph 		if (i < 0) {
577a0ea849cSralph 			vm_offset_t sa, ea;
578a0ea849cSralph 			int rv;
579a0ea849cSralph 
580a0ea849cSralph 			sa = trunc_page((vm_offset_t)va);
581a0ea849cSralph 			ea = round_page((vm_offset_t)va+sizeof(int)-1);
582a0ea849cSralph 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
583a0ea849cSralph 				VM_PROT_DEFAULT, FALSE);
584a0ea849cSralph 			if (rv == KERN_SUCCESS) {
585a0ea849cSralph 				i = suiword((caddr_t)va, p->p_md.md_ss_instr);
586a0ea849cSralph 				(void) vm_map_protect(&p->p_vmspace->vm_map,
587a0ea849cSralph 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
588a0ea849cSralph 					FALSE);
589a0ea849cSralph 			}
590a0ea849cSralph 		}
5914ab0a127Smckusick 		if (i < 0)
5924ab0a127Smckusick 			printf("Warning: can't restore instruction at %x: %x\n",
5934ab0a127Smckusick 				p->p_md.md_ss_addr, p->p_md.md_ss_instr);
5944ab0a127Smckusick 		p->p_md.md_ss_addr = 0;
595a0ea849cSralph 		i = SIGTRAP;
596a0ea849cSralph 		break;
597a0ea849cSralph 	    }
598a06587f5Smckusick 
599a06587f5Smckusick 	case T_RES_INST+T_USER:
600a06587f5Smckusick 		i = SIGILL;
601a06587f5Smckusick 		break;
602a06587f5Smckusick 
603a06587f5Smckusick 	case T_COP_UNUSABLE+T_USER:
604a06587f5Smckusick 		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {
605a06587f5Smckusick 			i = SIGILL;	/* only FPU instructions allowed */
606a06587f5Smckusick 			break;
607a06587f5Smckusick 		}
608a43518feSralph 		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
609a06587f5Smckusick 		machFPCurProcPtr = p;
610a43518feSralph 		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;
611a06587f5Smckusick 		p->p_md.md_flags |= MDP_FPUSED;
612a06587f5Smckusick 		goto out;
613a06587f5Smckusick 
614a06587f5Smckusick 	case T_OVFLOW+T_USER:
615a06587f5Smckusick 		i = SIGFPE;
616a06587f5Smckusick 		break;
617a06587f5Smckusick 
618a06587f5Smckusick 	case T_ADDR_ERR_LD:	/* misaligned access */
619a06587f5Smckusick 	case T_ADDR_ERR_ST:	/* misaligned access */
620a06587f5Smckusick 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
621a06587f5Smckusick 		if (i = ((struct pcb *)UADDR)->pcb_onfault) {
622a06587f5Smckusick 			((struct pcb *)UADDR)->pcb_onfault = 0;
623a06587f5Smckusick 			return (onfault_table[i]);
624a06587f5Smckusick 		}
625a06587f5Smckusick 		/* FALLTHROUGH */
626a06587f5Smckusick 
627a06587f5Smckusick 	default:
628a06587f5Smckusick 	err:
629a0ea849cSralph #ifdef KADB
630a0ea849cSralph 	    {
631a0ea849cSralph 		extern struct pcb kdbpcb;
632a0ea849cSralph 
633a0ea849cSralph 		if (USERMODE(statusReg))
634a0ea849cSralph 			kdbpcb = p->p_addr->u_pcb;
635a0ea849cSralph 		else {
636a0ea849cSralph 			kdbpcb.pcb_regs[ZERO] = 0;
637a0ea849cSralph 			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];
638a0ea849cSralph 			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];
639a0ea849cSralph 			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];
640a0ea849cSralph 			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];
641a0ea849cSralph 			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];
642a0ea849cSralph 			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];
643a0ea849cSralph 			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];
644a0ea849cSralph 			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];
645a0ea849cSralph 			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];
646a0ea849cSralph 			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];
647a0ea849cSralph 			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];
648a0ea849cSralph 			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];
649a0ea849cSralph 			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];
650a0ea849cSralph 			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];
651a0ea849cSralph 			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];
652a0ea849cSralph 			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];
653a0ea849cSralph 			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];
654a0ea849cSralph 			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];
655a0ea849cSralph 			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
656a0ea849cSralph 			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
657a0ea849cSralph 			kdbpcb.pcb_regs[PC] = pc;
658a0ea849cSralph 			kdbpcb.pcb_regs[SR] = statusReg;
659a0ea849cSralph 			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));
660a0ea849cSralph 		}
661a0ea849cSralph 		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))
662a0ea849cSralph 			return (kdbpcb.pcb_regs[PC]);
663a0ea849cSralph 	    }
66443e69fa3Sralph #else
66543e69fa3Sralph #ifdef DEBUG
66643e69fa3Sralph 		trapDump("trap");
66743e69fa3Sralph #endif
668a0ea849cSralph #endif
669a06587f5Smckusick 		panic("trap");
670a06587f5Smckusick 	}
671a06587f5Smckusick 	trapsignal(p, i, ucode);
672a06587f5Smckusick out:
673a06587f5Smckusick 	/*
674a06587f5Smckusick 	 * Note: we should only get here if returning to user mode.
675a06587f5Smckusick 	 */
676a2823b70Sralph 	/* take pending signals */
677a2823b70Sralph 	while ((i = CURSIG(p)) != 0)
6780082cbe2Sbostic 		postsig(i);
6790082cbe2Sbostic 	p->p_priority = p->p_usrpri;
680a2823b70Sralph 	astpending = 0;
681a06587f5Smckusick 	if (want_resched) {
682a0ea849cSralph 		int s;
683a0ea849cSralph 
684a06587f5Smckusick 		/*
685a06587f5Smckusick 		 * Since we are curproc, clock will normally just change
686a06587f5Smckusick 		 * our priority without moving us from one queue to another
687a06587f5Smckusick 		 * (since the running process is not on a queue.)
688793bd282Sbostic 		 * If that happened after we put ourselves on the run queue
6890082cbe2Sbostic 		 * but before we switched, we might not be on the queue
690793bd282Sbostic 		 * indicated by our priority.
691a06587f5Smckusick 		 */
692a2823b70Sralph 		s = splstatclock();
693793bd282Sbostic 		setrunqueue(p);
694a06587f5Smckusick 		p->p_stats->p_ru.ru_nivcsw++;
6950082cbe2Sbostic 		mi_switch();
696a0ea849cSralph 		splx(s);
697a2823b70Sralph 		while ((i = CURSIG(p)) != 0)
6980082cbe2Sbostic 			postsig(i);
699a06587f5Smckusick 	}
700a06587f5Smckusick 
701a2823b70Sralph 	/*
702a2823b70Sralph 	 * If profiling, charge system time to the trapped pc.
703a2823b70Sralph 	 */
7040082cbe2Sbostic 	if (p->p_flag & P_PROFIL) {
705ea43aba3Sralph 		extern int psratio;
706ea43aba3Sralph 
707ea43aba3Sralph 		addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
708ea43aba3Sralph 	}
709a2823b70Sralph 
7100082cbe2Sbostic 	curpriority = p->p_priority;
711a06587f5Smckusick 	return (pc);
712a06587f5Smckusick }
713a06587f5Smckusick 
714a06587f5Smckusick /*
715a06587f5Smckusick  * Handle an interrupt.
716a06587f5Smckusick  * Called from MachKernIntr() or MachUserIntr()
717a06587f5Smckusick  * Note: curproc might be NULL.
718a06587f5Smckusick  */
interrupt(statusReg,causeReg,pc)719a06587f5Smckusick interrupt(statusReg, causeReg, pc)
720a06587f5Smckusick 	unsigned statusReg;	/* status register at time of the exception */
721a06587f5Smckusick 	unsigned causeReg;	/* cause register at time of exception */
722a06587f5Smckusick 	unsigned pc;		/* program counter where to continue */
723a06587f5Smckusick {
724a06587f5Smckusick 	register unsigned mask;
725a2823b70Sralph 	struct clockframe cf;
726a06587f5Smckusick 
727a06587f5Smckusick #ifdef DEBUG
728a06587f5Smckusick 	trp->status = statusReg;
729a06587f5Smckusick 	trp->cause = causeReg;
730a06587f5Smckusick 	trp->vadr = 0;
731a06587f5Smckusick 	trp->pc = pc;
732a06587f5Smckusick 	trp->ra = 0;
733a06587f5Smckusick 	trp->code = 0;
734a06587f5Smckusick 	if (++trp == &trapdebug[TRAPSIZE])
735a06587f5Smckusick 		trp = trapdebug;
736843a209bSmckusick 
737843a209bSmckusick 	intr_level++;
738a06587f5Smckusick #endif
739a06587f5Smckusick 
740a06587f5Smckusick 	cnt.v_intr++;
741a06587f5Smckusick 	mask = causeReg & statusReg;	/* pending interrupts & enable mask */
742a2916846Sralph 	if (pmax_hardware_intr)
743a2916846Sralph 		splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg));
744a06587f5Smckusick 	if (mask & MACH_INT_MASK_5) {
745*759b7897Sralph 		intrcnt[7]++;
746a06587f5Smckusick 		if (!USERMODE(statusReg)) {
747a06587f5Smckusick #ifdef DEBUG
748a06587f5Smckusick 			trapDump("fpintr");
749a06587f5Smckusick #else
750a06587f5Smckusick 			printf("FPU interrupt: PC %x CR %x SR %x\n",
751a06587f5Smckusick 				pc, causeReg, statusReg);
752a06587f5Smckusick #endif
753a06587f5Smckusick 		} else
754a06587f5Smckusick 			MachFPInterrupt(statusReg, causeReg, pc);
755a06587f5Smckusick 	}
756a06587f5Smckusick 	if (mask & MACH_SOFT_INT_MASK_0) {
757a06587f5Smckusick 		clearsoftclock();
75843e69fa3Sralph 		cnt.v_soft++;
759*759b7897Sralph 		intrcnt[0]++;
760a2823b70Sralph 		softclock();
761a06587f5Smckusick 	}
762a06587f5Smckusick 	/* process network interrupt if we trapped or will very soon */
763a06587f5Smckusick 	if ((mask & MACH_SOFT_INT_MASK_1) ||
764a06587f5Smckusick 	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
765a06587f5Smckusick 		clearsoftnet();
76643e69fa3Sralph 		cnt.v_soft++;
767*759b7897Sralph 		intrcnt[1]++;
768a06587f5Smckusick #ifdef INET
769a06587f5Smckusick 		if (netisr & (1 << NETISR_ARP)) {
770a06587f5Smckusick 			netisr &= ~(1 << NETISR_ARP);
771a06587f5Smckusick 			arpintr();
772a06587f5Smckusick 		}
773a06587f5Smckusick 		if (netisr & (1 << NETISR_IP)) {
774a06587f5Smckusick 			netisr &= ~(1 << NETISR_IP);
775a06587f5Smckusick 			ipintr();
776a06587f5Smckusick 		}
777a06587f5Smckusick #endif
778a06587f5Smckusick #ifdef NS
779a06587f5Smckusick 		if (netisr & (1 << NETISR_NS)) {
780a06587f5Smckusick 			netisr &= ~(1 << NETISR_NS);
781a06587f5Smckusick 			nsintr();
782a06587f5Smckusick 		}
783a06587f5Smckusick #endif
784a06587f5Smckusick #ifdef ISO
785a06587f5Smckusick 		if (netisr & (1 << NETISR_ISO)) {
786a06587f5Smckusick 			netisr &= ~(1 << NETISR_ISO);
787a06587f5Smckusick 			clnlintr();
788a06587f5Smckusick 		}
789a06587f5Smckusick #endif
790a06587f5Smckusick 	}
791843a209bSmckusick #ifdef DEBUG
792843a209bSmckusick 	intr_level--;
793843a209bSmckusick #endif
794a06587f5Smckusick }
795a06587f5Smckusick 
796a06587f5Smckusick /*
797a2916846Sralph  * Handle pmax (DECstation 2100/3100) interrupts.
798a2916846Sralph  */
pmax_intr(mask,pc,statusReg,causeReg)799a2916846Sralph pmax_intr(mask, pc, statusReg, causeReg)
800a2916846Sralph 	unsigned mask;
801a2916846Sralph 	unsigned pc;
802a2916846Sralph 	unsigned statusReg;
803a2916846Sralph 	unsigned causeReg;
804a2916846Sralph {
805a2916846Sralph 	register volatile struct chiptime *c = Mach_clock_addr;
806a2916846Sralph 	struct clockframe cf;
807a2916846Sralph 	int temp;
808a2916846Sralph 
809a2916846Sralph 	/* handle clock interrupts ASAP */
810a2916846Sralph 	if (mask & MACH_INT_MASK_3) {
811*759b7897Sralph 		intrcnt[6]++;
812a2916846Sralph 		temp = c->regc;	/* XXX clear interrupt bits */
813a2916846Sralph 		cf.pc = pc;
814a2916846Sralph 		cf.sr = statusReg;
815a2916846Sralph 		hardclock(&cf);
816640f1a43Sralph 		/* keep clock interrupts enabled */
817640f1a43Sralph 		causeReg &= ~MACH_INT_MASK_3;
818a2916846Sralph 	}
819640f1a43Sralph 	/* Re-enable clock interrupts */
820640f1a43Sralph 	splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);
821a2916846Sralph #if NSII > 0
822*759b7897Sralph 	if (mask & MACH_INT_MASK_0) {
823*759b7897Sralph 		intrcnt[2]++;
824a2916846Sralph 		siiintr(0);
825*759b7897Sralph 	}
826a2916846Sralph #endif
827a2916846Sralph #if NLE > 0
828*759b7897Sralph 	if (mask & MACH_INT_MASK_1) {
829*759b7897Sralph 		intrcnt[3]++;
830a2916846Sralph 		leintr(0);
831*759b7897Sralph 	}
832a2916846Sralph #endif
833a2916846Sralph #if NDC > 0
834*759b7897Sralph 	if (mask & MACH_INT_MASK_2) {
835*759b7897Sralph 		intrcnt[4]++;
836a2916846Sralph 		dcintr(0);
837*759b7897Sralph 	}
838a2916846Sralph #endif
839*759b7897Sralph 	if (mask & MACH_INT_MASK_4) {
840*759b7897Sralph 		intrcnt[5]++;
841a2916846Sralph 		pmax_errintr();
842*759b7897Sralph 	}
843a2916846Sralph 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
844a2916846Sralph 		MACH_SR_INT_ENA_CUR);
845a2916846Sralph }
846a2916846Sralph 
847a2916846Sralph /*
848a2916846Sralph  * Handle hardware interrupts for the KN02. (DECstation 5000/200)
849a2916846Sralph  * Returns spl value.
850a2916846Sralph  */
kn02_intr(mask,pc,statusReg,causeReg)851a2916846Sralph kn02_intr(mask, pc, statusReg, causeReg)
852a2916846Sralph 	unsigned mask;
853a2916846Sralph 	unsigned pc;
854a2916846Sralph 	unsigned statusReg;
855a2916846Sralph 	unsigned causeReg;
856a2916846Sralph {
857a2916846Sralph 	register unsigned i, m;
858a2916846Sralph 	register volatile struct chiptime *c = Mach_clock_addr;
859a2916846Sralph 	register unsigned csr;
860a2916846Sralph 	int temp;
861a2916846Sralph 	struct clockframe cf;
862a2916846Sralph 	static int warned = 0;
863a2916846Sralph 
864a2916846Sralph 	/* handle clock interrupts ASAP */
865a2916846Sralph 	if (mask & MACH_INT_MASK_1) {
866a2916846Sralph 		csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
867a2916846Sralph 		if ((csr & KN02_CSR_PSWARN) && !warned) {
868a2916846Sralph 			warned = 1;
869a2916846Sralph 			printf("WARNING: power supply is overheating!\n");
870a2916846Sralph 		} else if (warned && !(csr & KN02_CSR_PSWARN)) {
871a2916846Sralph 			warned = 0;
872a2916846Sralph 			printf("WARNING: power supply is OK again\n");
873a2916846Sralph 		}
874*759b7897Sralph 		intrcnt[6]++;
875a2916846Sralph 
876a2916846Sralph 		temp = c->regc;	/* XXX clear interrupt bits */
877a2916846Sralph 		cf.pc = pc;
878a2916846Sralph 		cf.sr = statusReg;
879a2916846Sralph 		hardclock(&cf);
880a2916846Sralph 
881640f1a43Sralph 		/* keep clock interrupts enabled */
882a2916846Sralph 		causeReg &= ~MACH_INT_MASK_1;
883a2916846Sralph 	}
884640f1a43Sralph 	/* Re-enable clock interrupts */
885640f1a43Sralph 	splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
886a2916846Sralph 	if (mask & MACH_INT_MASK_0) {
887*759b7897Sralph 		static int map[8] = { 8, 8, 8, 8, 8, 4, 3, 2 };
888a2916846Sralph 
889a2916846Sralph 		csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
890a2916846Sralph 		m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;
891a2916846Sralph #if 0
892a2916846Sralph 		*(unsigned *)MACHPHYS_TO_UNCACHED(KN02_SYS_CSR) =
893a2916846Sralph 			(csr & ~(KN02_CSR_WRESERVED | 0xFF)) |
894a2916846Sralph 			(m << KN02_CSR_IOINTEN_SHIFT);
895a2916846Sralph #endif
896a2916846Sralph 		for (i = 0; m; i++, m >>= 1) {
897a2916846Sralph 			if (!(m & 1))
898a2916846Sralph 				continue;
899*759b7897Sralph 			intrcnt[map[i]]++;
900a2916846Sralph 			if (tc_slot_info[i].intr)
901a2916846Sralph 				(*tc_slot_info[i].intr)(tc_slot_info[i].unit);
902a2916846Sralph 			else
903a2916846Sralph 				printf("spurious interrupt %d\n", i);
904a2916846Sralph 		}
905a2916846Sralph #if 0
906a2916846Sralph 		*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
907a2916846Sralph 			csr & ~(KN02_CSR_WRESERVED | 0xFF);
908a2916846Sralph #endif
909a2916846Sralph 	}
910*759b7897Sralph 	if (mask & MACH_INT_MASK_3) {
911*759b7897Sralph 		intrcnt[5]++;
912a2916846Sralph 		kn02_errintr();
913*759b7897Sralph 	}
914a2916846Sralph 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
915a2916846Sralph 		MACH_SR_INT_ENA_CUR);
916a2916846Sralph }
917a2916846Sralph 
918a2916846Sralph /*
919a2916846Sralph  * 3min hardware interrupts. (DECstation 5000/1xx)
920a2916846Sralph  */
kmin_intr(mask,pc,statusReg,causeReg)921a2916846Sralph kmin_intr(mask, pc, statusReg, causeReg)
922a2916846Sralph 	unsigned mask;
923a2916846Sralph 	unsigned pc;
924a2916846Sralph 	unsigned statusReg;
925a2916846Sralph 	unsigned causeReg;
926a2916846Sralph {
927a2916846Sralph 	register u_int intr;
928a2916846Sralph 	register volatile struct chiptime *c = Mach_clock_addr;
929a2916846Sralph 	volatile u_int *imaskp =
930a2916846Sralph 		(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK);
931a2916846Sralph 	volatile u_int *intrp =
932a2916846Sralph 		(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR);
933a2916846Sralph 	unsigned int old_mask;
934a2916846Sralph 	struct clockframe cf;
935a2916846Sralph 	int temp;
936a2916846Sralph 	static int user_warned = 0;
937a2916846Sralph 
938a2916846Sralph 	old_mask = *imaskp & kmin_tc3_imask;
939a2916846Sralph 	*imaskp = old_mask;
940a2916846Sralph 
941348607e6Sralph 	if (mask & MACH_INT_MASK_4)
942348607e6Sralph 		(*callv->halt)((int *)0, 0);
943a2916846Sralph 	if (mask & MACH_INT_MASK_3) {
944a2916846Sralph 		intr = *intrp;
945a2916846Sralph 		/* masked interrupts are still observable */
946a2916846Sralph 		intr &= old_mask;
947a2916846Sralph 
948a2916846Sralph 		if (intr & KMIN_INTR_SCSI_PTR_LOAD) {
949a2916846Sralph 			*intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;
950ab61b8b0Sralph #ifdef notdef
951a2916846Sralph 			asc_dma_intr();
952a2916846Sralph #endif
953a2916846Sralph 		}
954a2916846Sralph 
955a2916846Sralph 		if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E))
956a2916846Sralph 			*intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
957a2916846Sralph 
958a2916846Sralph 		if (intr & KMIN_INTR_LANCE_READ_E)
959a2916846Sralph 			*intrp &= ~KMIN_INTR_LANCE_READ_E;
960a2916846Sralph 
961a2916846Sralph 		if (intr & KMIN_INTR_TIMEOUT)
962a2916846Sralph 			kn02ba_errintr();
963a2916846Sralph 
964a2916846Sralph 		if (intr & KMIN_INTR_CLOCK) {
965a2916846Sralph 			temp = c->regc;	/* XXX clear interrupt bits */
966a2916846Sralph 			cf.pc = pc;
967a2916846Sralph 			cf.sr = statusReg;
968a2916846Sralph 			hardclock(&cf);
969a2916846Sralph 		}
970a2916846Sralph 
971a2916846Sralph 		if ((intr & KMIN_INTR_SCC_0) &&
972a2916846Sralph 			tc_slot_info[KMIN_SCC0_SLOT].intr)
973a2916846Sralph 			(*(tc_slot_info[KMIN_SCC0_SLOT].intr))
974a2916846Sralph 			(tc_slot_info[KMIN_SCC0_SLOT].unit);
975a2916846Sralph 
976a2916846Sralph 		if ((intr & KMIN_INTR_SCC_1) &&
977a2916846Sralph 			tc_slot_info[KMIN_SCC1_SLOT].intr)
978a2916846Sralph 			(*(tc_slot_info[KMIN_SCC1_SLOT].intr))
979a2916846Sralph 			(tc_slot_info[KMIN_SCC1_SLOT].unit);
980a2916846Sralph 
981a2916846Sralph 		if ((intr & KMIN_INTR_SCSI) &&
982a2916846Sralph 			tc_slot_info[KMIN_SCSI_SLOT].intr)
983a2916846Sralph 			(*(tc_slot_info[KMIN_SCSI_SLOT].intr))
984a2916846Sralph 			(tc_slot_info[KMIN_SCSI_SLOT].unit);
985a2916846Sralph 
986a2916846Sralph 		if ((intr & KMIN_INTR_LANCE) &&
987a2916846Sralph 			tc_slot_info[KMIN_LANCE_SLOT].intr)
988a2916846Sralph 			(*(tc_slot_info[KMIN_LANCE_SLOT].intr))
989a2916846Sralph 			(tc_slot_info[KMIN_LANCE_SLOT].unit);
990a2916846Sralph 
991a2916846Sralph 		if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
992a2916846Sralph 			printf("%s\n", "Power supply ok now.");
993a2916846Sralph 			user_warned = 0;
994a2916846Sralph 		}
995a2916846Sralph 		if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
996a2916846Sralph 			user_warned++;
997a2916846Sralph 			printf("%s\n", "Power supply overheating");
998a2916846Sralph 		}
999a2916846Sralph 	}
1000a2916846Sralph 	if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr)
1001a2916846Sralph 		(*tc_slot_info[0].intr)(tc_slot_info[0].unit);
1002a2916846Sralph 	if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr)
1003a2916846Sralph 		(*tc_slot_info[1].intr)(tc_slot_info[1].unit);
1004a2916846Sralph 	if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr)
1005a2916846Sralph 		(*tc_slot_info[2].intr)(tc_slot_info[2].unit);
1006a2916846Sralph 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1007a2916846Sralph 		MACH_SR_INT_ENA_CUR);
1008a2916846Sralph }
1009a2916846Sralph 
1010a2916846Sralph /*
1011640f1a43Sralph  * Maxine hardware interrupts. (Personal DECstation 5000/xx)
1012a2916846Sralph  */
xine_intr(mask,pc,statusReg,causeReg)1013a2916846Sralph xine_intr(mask, pc, statusReg, causeReg)
1014a2916846Sralph 	unsigned mask;
1015a2916846Sralph 	unsigned pc;
1016a2916846Sralph 	unsigned statusReg;
1017a2916846Sralph 	unsigned causeReg;
1018a2916846Sralph {
1019a2916846Sralph 	register u_int intr;
1020a2916846Sralph 	register volatile struct chiptime *c = Mach_clock_addr;
1021a2916846Sralph 	volatile u_int *imaskp = (volatile u_int *)
1022a2916846Sralph 		MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK);
1023a2916846Sralph 	volatile u_int *intrp = (volatile u_int *)
1024a2916846Sralph 		MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
1025a2916846Sralph 	u_int old_mask;
1026a2916846Sralph 	struct clockframe cf;
1027a2916846Sralph 	int temp;
1028a2916846Sralph 
1029a2916846Sralph 	old_mask = *imaskp & xine_tc3_imask;
1030a2916846Sralph 	*imaskp = old_mask;
1031a2916846Sralph 
1032348607e6Sralph 	if (mask & MACH_INT_MASK_4)
1033348607e6Sralph 		(*callv->halt)((int *)0, 0);
1034348607e6Sralph 
1035a2916846Sralph 	/* handle clock interrupts ASAP */
1036a2916846Sralph 	if (mask & MACH_INT_MASK_1) {
1037a2916846Sralph 		temp = c->regc;	/* XXX clear interrupt bits */
1038a2916846Sralph 		cf.pc = pc;
1039a2916846Sralph 		cf.sr = statusReg;
1040a2916846Sralph 		hardclock(&cf);
1041a2916846Sralph 		causeReg &= ~MACH_INT_MASK_1;
1042a2916846Sralph 		/* reenable clock interrupts */
1043a2916846Sralph 		splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
1044a2916846Sralph 	}
1045a2916846Sralph 	if (mask & MACH_INT_MASK_3) {
1046a2916846Sralph 		intr = *intrp;
1047a2916846Sralph 		/* masked interrupts are still observable */
1048a2916846Sralph 		intr &= old_mask;
1049a2916846Sralph 
1050a2916846Sralph 		if (intr & XINE_INTR_SCSI_PTR_LOAD) {
1051a2916846Sralph 			*intrp &= ~XINE_INTR_SCSI_PTR_LOAD;
1052ab61b8b0Sralph #ifdef notdef
1053a2916846Sralph 			asc_dma_intr();
1054a2916846Sralph #endif
1055a2916846Sralph 		}
1056a2916846Sralph 
1057a2916846Sralph 		if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E))
1058a2916846Sralph 			*intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
1059a2916846Sralph 
1060a2916846Sralph 		if (intr & XINE_INTR_LANCE_READ_E)
1061a2916846Sralph 			*intrp &= ~XINE_INTR_LANCE_READ_E;
1062a2916846Sralph 
1063348607e6Sralph 		if ((intr & XINE_INTR_SCC_0) &&
1064348607e6Sralph 			tc_slot_info[XINE_SCC0_SLOT].intr)
1065348607e6Sralph 			(*(tc_slot_info[XINE_SCC0_SLOT].intr))
1066348607e6Sralph 			(tc_slot_info[XINE_SCC0_SLOT].unit);
1067348607e6Sralph 
1068348607e6Sralph 		if ((intr & XINE_INTR_DTOP_RX) &&
1069348607e6Sralph 			tc_slot_info[XINE_DTOP_SLOT].intr)
1070348607e6Sralph 			(*(tc_slot_info[XINE_DTOP_SLOT].intr))
1071348607e6Sralph 			(tc_slot_info[XINE_DTOP_SLOT].unit);
1072348607e6Sralph 
1073a2916846Sralph 		if ((intr & XINE_INTR_FLOPPY) &&
1074a2916846Sralph 			tc_slot_info[XINE_FLOPPY_SLOT].intr)
1075a2916846Sralph 			(*(tc_slot_info[XINE_FLOPPY_SLOT].intr))
1076a2916846Sralph 			(tc_slot_info[XINE_FLOPPY_SLOT].unit);
1077a2916846Sralph 
1078a2916846Sralph 		if ((intr & XINE_INTR_TC_0) &&
1079a2916846Sralph 			tc_slot_info[0].intr)
1080a2916846Sralph 			(*(tc_slot_info[0].intr))
1081a2916846Sralph 			(tc_slot_info[0].unit);
1082a2916846Sralph 
1083348607e6Sralph 		if ((intr & XINE_INTR_TC_1) &&
1084348607e6Sralph 			tc_slot_info[1].intr)
1085348607e6Sralph 			(*(tc_slot_info[1].intr))
1086348607e6Sralph 			(tc_slot_info[1].unit);
1087348607e6Sralph 
1088a2916846Sralph 		if ((intr & XINE_INTR_ISDN) &&
1089a2916846Sralph 			tc_slot_info[XINE_ISDN_SLOT].intr)
1090a2916846Sralph 			(*(tc_slot_info[XINE_ISDN_SLOT].intr))
1091a2916846Sralph 			(tc_slot_info[XINE_ISDN_SLOT].unit);
1092a2916846Sralph 
1093a2916846Sralph 		if ((intr & XINE_INTR_SCSI) &&
1094a2916846Sralph 			tc_slot_info[XINE_SCSI_SLOT].intr)
1095a2916846Sralph 			(*(tc_slot_info[XINE_SCSI_SLOT].intr))
1096a2916846Sralph 			(tc_slot_info[XINE_SCSI_SLOT].unit);
1097a2916846Sralph 
1098a2916846Sralph 		if ((intr & XINE_INTR_LANCE) &&
1099a2916846Sralph 			tc_slot_info[XINE_LANCE_SLOT].intr)
1100a2916846Sralph 			(*(tc_slot_info[XINE_LANCE_SLOT].intr))
1101a2916846Sralph 			(tc_slot_info[XINE_LANCE_SLOT].unit);
1102a2916846Sralph 
1103a2916846Sralph 	}
1104a2916846Sralph 	if (mask & MACH_INT_MASK_2)
1105a2916846Sralph 		kn02ba_errintr();
1106a2916846Sralph 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1107a2916846Sralph 		MACH_SR_INT_ENA_CUR);
1108a2916846Sralph }
1109a2916846Sralph 
1110ab61b8b0Sralph #ifdef DS5000_240
1111ab61b8b0Sralph /*
1112ab61b8b0Sralph  * 3Max+ hardware interrupts. (DECstation 5000/240) UNTESTED!!
1113ab61b8b0Sralph  */
kn03_intr(mask,pc,statusReg,causeReg)1114ab61b8b0Sralph kn03_intr(mask, pc, statusReg, causeReg)
1115ab61b8b0Sralph 	unsigned mask;
1116ab61b8b0Sralph 	unsigned pc;
1117ab61b8b0Sralph 	unsigned statusReg;
1118ab61b8b0Sralph 	unsigned causeReg;
1119ab61b8b0Sralph {
1120ab61b8b0Sralph 	register u_int intr;
1121ab61b8b0Sralph 	register volatile struct chiptime *c = Mach_clock_addr;
1122ab61b8b0Sralph 	volatile u_int *imaskp = (volatile u_int *)
1123ab61b8b0Sralph 		MACH_PHYS_TO_UNCACHED(KN03_REG_IMSK);
1124ab61b8b0Sralph 	volatile u_int *intrp = (volatile u_int *)
1125ab61b8b0Sralph 		MACH_PHYS_TO_UNCACHED(KN03_REG_INTR);
1126ab61b8b0Sralph 	u_int old_mask;
1127ab61b8b0Sralph 	struct clockframe cf;
1128ab61b8b0Sralph 	int temp;
1129348607e6Sralph 	static int user_warned = 0;
1130ab61b8b0Sralph 
1131ab61b8b0Sralph 	old_mask = *imaskp & kn03_tc3_imask;
1132ab61b8b0Sralph 	*imaskp = old_mask;
1133ab61b8b0Sralph 
1134348607e6Sralph 	if (mask & MACH_INT_MASK_4)
1135348607e6Sralph 		(*callv->halt)((int *)0, 0);
1136348607e6Sralph 
1137ab61b8b0Sralph 	/* handle clock interrupts ASAP */
1138ab61b8b0Sralph 	if (mask & MACH_INT_MASK_1) {
1139ab61b8b0Sralph 		temp = c->regc;	/* XXX clear interrupt bits */
1140ab61b8b0Sralph 		cf.pc = pc;
1141ab61b8b0Sralph 		cf.sr = statusReg;
1142ab61b8b0Sralph 		hardclock(&cf);
1143ab61b8b0Sralph 		causeReg &= ~MACH_INT_MASK_1;
1144ab61b8b0Sralph 		/* reenable clock interrupts */
1145ab61b8b0Sralph 		splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
1146ab61b8b0Sralph 	}
1147ab61b8b0Sralph 	if (mask & MACH_INT_MASK_0) {
1148ab61b8b0Sralph 		intr = *intrp;
1149ab61b8b0Sralph 		/* masked interrupts are still observable */
1150ab61b8b0Sralph 		intr &= old_mask;
1151ab61b8b0Sralph 
1152ab61b8b0Sralph 		if (intr & KN03_INTR_SCSI_PTR_LOAD) {
1153ab61b8b0Sralph 			*intrp &= ~KN03_INTR_SCSI_PTR_LOAD;
1154ab61b8b0Sralph #ifdef notdef
1155ab61b8b0Sralph 			asc_dma_intr();
1156ab61b8b0Sralph #endif
1157ab61b8b0Sralph 		}
1158ab61b8b0Sralph 
1159ab61b8b0Sralph 		if (intr & (KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E))
1160ab61b8b0Sralph 			*intrp &= ~(KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
1161ab61b8b0Sralph 
1162ab61b8b0Sralph 		if (intr & KN03_INTR_LANCE_READ_E)
1163ab61b8b0Sralph 			*intrp &= ~KN03_INTR_LANCE_READ_E;
1164ab61b8b0Sralph 
1165348607e6Sralph 		if ((intr & KN03_INTR_SCC_0) &&
1166348607e6Sralph 			tc_slot_info[KN03_SCC0_SLOT].intr)
1167348607e6Sralph 			(*(tc_slot_info[KN03_SCC0_SLOT].intr))
1168348607e6Sralph 			(tc_slot_info[KN03_SCC0_SLOT].unit);
1169348607e6Sralph 
1170348607e6Sralph 		if ((intr & KN03_INTR_SCC_1) &&
1171348607e6Sralph 			tc_slot_info[KN03_SCC1_SLOT].intr)
1172348607e6Sralph 			(*(tc_slot_info[KN03_SCC1_SLOT].intr))
1173348607e6Sralph 			(tc_slot_info[KN03_SCC1_SLOT].unit);
1174348607e6Sralph 
1175ab61b8b0Sralph 		if ((intr & KN03_INTR_TC_0) &&
1176ab61b8b0Sralph 			tc_slot_info[0].intr)
1177ab61b8b0Sralph 			(*(tc_slot_info[0].intr))
1178ab61b8b0Sralph 			(tc_slot_info[0].unit);
1179ab61b8b0Sralph 
1180ab61b8b0Sralph 		if ((intr & KN03_INTR_TC_1) &&
1181ab61b8b0Sralph 			tc_slot_info[1].intr)
1182ab61b8b0Sralph 			(*(tc_slot_info[1].intr))
1183ab61b8b0Sralph 			(tc_slot_info[1].unit);
1184ab61b8b0Sralph 
1185ab61b8b0Sralph 		if ((intr & KN03_INTR_TC_2) &&
1186ab61b8b0Sralph 			tc_slot_info[2].intr)
1187ab61b8b0Sralph 			(*(tc_slot_info[2].intr))
1188ab61b8b0Sralph 			(tc_slot_info[2].unit);
1189ab61b8b0Sralph 
1190ab61b8b0Sralph 		if ((intr & KN03_INTR_SCSI) &&
1191ab61b8b0Sralph 			tc_slot_info[KN03_SCSI_SLOT].intr)
1192ab61b8b0Sralph 			(*(tc_slot_info[KN03_SCSI_SLOT].intr))
1193ab61b8b0Sralph 			(tc_slot_info[KN03_SCSI_SLOT].unit);
1194ab61b8b0Sralph 
1195ab61b8b0Sralph 		if ((intr & KN03_INTR_LANCE) &&
1196ab61b8b0Sralph 			tc_slot_info[KN03_LANCE_SLOT].intr)
1197ab61b8b0Sralph 			(*(tc_slot_info[KN03_LANCE_SLOT].intr))
1198ab61b8b0Sralph 			(tc_slot_info[KN03_LANCE_SLOT].unit);
1199ab61b8b0Sralph 
1200348607e6Sralph 		if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) {
1201348607e6Sralph 			printf("%s\n", "Power supply ok now.");
1202348607e6Sralph 			user_warned = 0;
1203348607e6Sralph 		}
1204348607e6Sralph 		if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) {
1205348607e6Sralph 			user_warned++;
1206348607e6Sralph 			printf("%s\n", "Power supply overheating");
1207348607e6Sralph 		}
1208ab61b8b0Sralph 	}
1209ab61b8b0Sralph 	if (mask & MACH_INT_MASK_3)
1210ab61b8b0Sralph 		kn03_errintr();
1211ab61b8b0Sralph 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1212ab61b8b0Sralph 		MACH_SR_INT_ENA_CUR);
1213ab61b8b0Sralph }
1214ab61b8b0Sralph #endif /* DS5000_240 */
1215ab61b8b0Sralph 
1216a2916846Sralph /*
1217a06587f5Smckusick  * This is called from MachUserIntr() if astpending is set.
1218a06587f5Smckusick  * This is very similar to the tail of trap().
1219a06587f5Smckusick  */
softintr(statusReg,pc)1220a06587f5Smckusick softintr(statusReg, pc)
1221a06587f5Smckusick 	unsigned statusReg;	/* status register at time of the exception */
1222a06587f5Smckusick 	unsigned pc;		/* program counter where to continue */
1223a06587f5Smckusick {
1224a06587f5Smckusick 	register struct proc *p = curproc;
1225a2823b70Sralph 	int sig;
1226a06587f5Smckusick 
1227a06587f5Smckusick 	cnt.v_soft++;
1228a2823b70Sralph 	/* take pending signals */
1229a2823b70Sralph 	while ((sig = CURSIG(p)) != 0)
12300082cbe2Sbostic 		postsig(sig);
12310082cbe2Sbostic 	p->p_priority = p->p_usrpri;
1232a2823b70Sralph 	astpending = 0;
12330082cbe2Sbostic 	if (p->p_flag & P_OWEUPC) {
12340082cbe2Sbostic 		p->p_flag &= ~P_OWEUPC;
1235a2823b70Sralph 		ADDUPROF(p);
1236a2823b70Sralph 	}
1237a06587f5Smckusick 	if (want_resched) {
1238a0ea849cSralph 		int s;
1239a0ea849cSralph 
1240a06587f5Smckusick 		/*
1241a06587f5Smckusick 		 * Since we are curproc, clock will normally just change
1242a06587f5Smckusick 		 * our priority without moving us from one queue to another
1243a06587f5Smckusick 		 * (since the running process is not on a queue.)
1244793bd282Sbostic 		 * If that happened after we put ourselves on the run queue
12450082cbe2Sbostic 		 * but before we switched, we might not be on the queue
1246793bd282Sbostic 		 * indicated by our priority.
1247a06587f5Smckusick 		 */
1248a2823b70Sralph 		s = splstatclock();
1249793bd282Sbostic 		setrunqueue(p);
1250a06587f5Smckusick 		p->p_stats->p_ru.ru_nivcsw++;
12510082cbe2Sbostic 		mi_switch();
1252a0ea849cSralph 		splx(s);
1253a2823b70Sralph 		while ((sig = CURSIG(p)) != 0)
12540082cbe2Sbostic 			postsig(sig);
1255a06587f5Smckusick 	}
12560082cbe2Sbostic 	curpriority = p->p_priority;
1257a06587f5Smckusick }
1258a06587f5Smckusick 
1259a06587f5Smckusick #ifdef DEBUG
trapDump(msg)1260a06587f5Smckusick trapDump(msg)
1261a06587f5Smckusick 	char *msg;
1262a06587f5Smckusick {
1263a06587f5Smckusick 	register int i;
1264a06587f5Smckusick 	int s;
1265a06587f5Smckusick 
1266a06587f5Smckusick 	s = splhigh();
1267a06587f5Smckusick 	printf("trapDump(%s)\n", msg);
1268a06587f5Smckusick 	for (i = 0; i < TRAPSIZE; i++) {
1269a06587f5Smckusick 		if (trp == trapdebug)
1270a06587f5Smckusick 			trp = &trapdebug[TRAPSIZE - 1];
1271a06587f5Smckusick 		else
1272a06587f5Smckusick 			trp--;
1273a06587f5Smckusick 		if (trp->cause == 0)
1274a06587f5Smckusick 			break;
1275a06587f5Smckusick 		printf("%s: ADR %x PC %x CR %x SR %x\n",
1276a06587f5Smckusick 			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>
1277a06587f5Smckusick 				MACH_CR_EXC_CODE_SHIFT],
1278a06587f5Smckusick 			trp->vadr, trp->pc, trp->cause, trp->status);
1279a06587f5Smckusick 		printf("   RA %x code %d\n", trp-> ra, trp->code);
1280a06587f5Smckusick 	}
1281a06587f5Smckusick 	bzero(trapdebug, sizeof(trapdebug));
1282a06587f5Smckusick 	trp = trapdebug;
1283a06587f5Smckusick 	splx(s);
1284a06587f5Smckusick }
1285a06587f5Smckusick #endif
1286a06587f5Smckusick 
1287a06587f5Smckusick /*
1288a06587f5Smckusick  *----------------------------------------------------------------------
1289a06587f5Smckusick  *
1290a2916846Sralph  * MemErrorInterrupts --
1291a2916846Sralph  *   pmax_errintr - for the DS2100/DS3100
1292a2916846Sralph  *   kn02_errintr - for the DS5000/200
1293a2916846Sralph  *   kn02ba_errintr - for the DS5000/1xx and DS5000/xx
1294a06587f5Smckusick  *
1295a06587f5Smckusick  *	Handler an interrupt for the control register.
1296a06587f5Smckusick  *
1297a06587f5Smckusick  * Results:
1298a06587f5Smckusick  *	None.
1299a06587f5Smckusick  *
1300a06587f5Smckusick  * Side effects:
1301a06587f5Smckusick  *	None.
1302a06587f5Smckusick  *
1303a06587f5Smckusick  *----------------------------------------------------------------------
1304a06587f5Smckusick  */
1305a06587f5Smckusick static void
pmax_errintr()1306a2916846Sralph pmax_errintr()
1307a06587f5Smckusick {
1308a2916846Sralph 	volatile u_short *sysCSRPtr =
1309a2916846Sralph 		(u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);
1310a06587f5Smckusick 	u_short csr;
1311a06587f5Smckusick 
1312a06587f5Smckusick 	csr = *sysCSRPtr;
1313a06587f5Smckusick 
1314a2916846Sralph 	if (csr & KN01_CSR_MERR) {
1315a06587f5Smckusick 		printf("Memory error at 0x%x\n",
1316a2916846Sralph 			*(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
1317a06587f5Smckusick 		panic("Mem error interrupt");
1318a06587f5Smckusick 	}
1319a2916846Sralph 	*sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
1320a2916846Sralph }
1321a2916846Sralph 
1322a2916846Sralph static void
kn02_errintr()1323a2916846Sralph kn02_errintr()
1324a2916846Sralph {
1325b7c21bfdSmckusick 	u_int erradr, chksyn, physadr;
1326b7c21bfdSmckusick 	int i;
1327a2916846Sralph 
132813800629Sralph 	erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR);
132913800629Sralph 	chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN);
133013800629Sralph 	*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
1331a0ea849cSralph 	MachEmptyWriteBuffer();
133213800629Sralph 
133313800629Sralph 	if (!(erradr & KN02_ERR_VALID))
133413800629Sralph 		return;
1335b7c21bfdSmckusick 	/* extract the physical word address and compensate for pipelining */
1336b7c21bfdSmckusick 	physadr = erradr & KN02_ERR_ADDRESS;
1337b7c21bfdSmckusick 	if (!(erradr & KN02_ERR_WRITE))
1338b7c21bfdSmckusick 		physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
1339b7c21bfdSmckusick 	physadr <<= 2;
134013800629Sralph 	printf("%s memory %s %s error at 0x%x\n",
134113800629Sralph 		(erradr & KN02_ERR_CPU) ? "CPU" : "DMA",
134213800629Sralph 		(erradr & KN02_ERR_WRITE) ? "write" : "read",
134313800629Sralph 		(erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout",
1344b7c21bfdSmckusick 		physadr);
134513800629Sralph 	if (erradr & KN02_ERR_ECCERR) {
134613800629Sralph 		*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0;
134713800629Sralph 		MachEmptyWriteBuffer();
134813800629Sralph 		printf("ECC 0x%x\n", chksyn);
1349b7c21bfdSmckusick 
1350b7c21bfdSmckusick 		/* check for a corrected, single bit, read error */
1351b7c21bfdSmckusick 		if (!(erradr & KN02_ERR_WRITE)) {
1352b7c21bfdSmckusick 			if (physadr & 0x4) {
1353b7c21bfdSmckusick 				/* check high word */
1354b7c21bfdSmckusick 				if (chksyn & KN02_ECC_SNGHI)
1355b7c21bfdSmckusick 					return;
1356b7c21bfdSmckusick 			} else {
1357b7c21bfdSmckusick 				/* check low word */
1358b7c21bfdSmckusick 				if (chksyn & KN02_ECC_SNGLO)
1359b7c21bfdSmckusick 					return;
1360b7c21bfdSmckusick 			}
1361b7c21bfdSmckusick 		}
136213800629Sralph 	}
136313800629Sralph 	panic("Mem error interrupt");
1364a2916846Sralph }
1365a2916846Sralph 
1366ab61b8b0Sralph #ifdef DS5000_240
1367ab61b8b0Sralph static void
kn03_errintr()1368ab61b8b0Sralph kn03_errintr()
1369ab61b8b0Sralph {
1370ab61b8b0Sralph 
1371ab61b8b0Sralph 	printf("erradr %x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR));
1372ab61b8b0Sralph 	*(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
1373ab61b8b0Sralph 	MachEmptyWriteBuffer();
1374ab61b8b0Sralph }
1375ab61b8b0Sralph #endif /* DS5000_240 */
1376ab61b8b0Sralph 
1377a2916846Sralph static void
kn02ba_errintr()1378a2916846Sralph kn02ba_errintr()
1379a2916846Sralph {
1380a2916846Sralph 	register int mer, adr, siz;
1381a2916846Sralph 	static int errintr_cnt = 0;
1382a2916846Sralph 
1383a2916846Sralph 	siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);
1384a2916846Sralph 	mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);
1385a2916846Sralph 	adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);
1386a2916846Sralph 
1387a2916846Sralph 	/* clear interrupt bit */
1388a2916846Sralph 	*(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
1389a2916846Sralph 
1390a2916846Sralph 	errintr_cnt++;
1391a2916846Sralph 	printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,
1392a2916846Sralph 	       "Bad memory chip at phys ",
1393a2916846Sralph 	       kn02ba_recover_erradr(adr, mer),
1394a2916846Sralph 	       mer, siz, adr);
1395a2916846Sralph }
1396a2916846Sralph 
1397a2916846Sralph static unsigned
kn02ba_recover_erradr(phys,mer)1398a2916846Sralph kn02ba_recover_erradr(phys, mer)
1399a2916846Sralph 	register unsigned phys, mer;
1400a2916846Sralph {
1401a2916846Sralph 	/* phys holds bits 28:2, mer knows which byte */
1402a2916846Sralph 	switch (mer & KMIN_MER_LASTBYTE) {
1403a2916846Sralph 	case KMIN_LASTB31:
1404a2916846Sralph 		mer = 3; break;
1405a2916846Sralph 	case KMIN_LASTB23:
1406a2916846Sralph 		mer = 2; break;
1407a2916846Sralph 	case KMIN_LASTB15:
1408a2916846Sralph 		mer = 1; break;
1409a2916846Sralph 	case KMIN_LASTB07:
1410a2916846Sralph 		mer = 0; break;
1411a2916846Sralph 	}
1412a2916846Sralph 	return ((phys & KMIN_AER_ADDR_MASK) | mer);
1413a06587f5Smckusick }
1414a06587f5Smckusick 
1415a06587f5Smckusick /*
1416a06587f5Smckusick  * Return the resulting PC as if the branch was executed.
1417a06587f5Smckusick  */
1418a06587f5Smckusick unsigned
MachEmulateBranch(regsPtr,instPC,fpcCSR,allowNonBranch)1419a06587f5Smckusick MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
1420a06587f5Smckusick 	unsigned *regsPtr;
1421a06587f5Smckusick 	unsigned instPC;
1422a06587f5Smckusick 	unsigned fpcCSR;
1423a06587f5Smckusick 	int allowNonBranch;
1424a06587f5Smckusick {
1425a0ea849cSralph 	InstFmt inst;
1426a06587f5Smckusick 	unsigned retAddr;
1427a06587f5Smckusick 	int condition;
1428a06587f5Smckusick 	extern unsigned GetBranchDest();
1429a06587f5Smckusick 
1430a06587f5Smckusick 
1431a0ea849cSralph 	inst = *(InstFmt *)instPC;
14324ab0a127Smckusick #if 0
14334ab0a127Smckusick 	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
14344ab0a127Smckusick 		inst.word, fpcCSR); /* XXX */
14354ab0a127Smckusick #endif
1436a0ea849cSralph 	switch ((int)inst.JType.op) {
1437a06587f5Smckusick 	case OP_SPECIAL:
1438a0ea849cSralph 		switch ((int)inst.RType.func) {
1439a06587f5Smckusick 		case OP_JR:
1440a06587f5Smckusick 		case OP_JALR:
1441a0ea849cSralph 			retAddr = regsPtr[inst.RType.rs];
1442a06587f5Smckusick 			break;
1443a06587f5Smckusick 
1444a06587f5Smckusick 		default:
1445a06587f5Smckusick 			if (!allowNonBranch)
1446a06587f5Smckusick 				panic("MachEmulateBranch: Non-branch");
1447a06587f5Smckusick 			retAddr = instPC + 4;
1448a06587f5Smckusick 			break;
1449a06587f5Smckusick 		}
1450a06587f5Smckusick 		break;
1451a06587f5Smckusick 
1452a06587f5Smckusick 	case OP_BCOND:
1453a0ea849cSralph 		switch ((int)inst.IType.rt) {
1454a06587f5Smckusick 		case OP_BLTZ:
1455a06587f5Smckusick 		case OP_BLTZAL:
1456a0ea849cSralph 			if ((int)(regsPtr[inst.RType.rs]) < 0)
1457a0ea849cSralph 				retAddr = GetBranchDest((InstFmt *)instPC);
1458a06587f5Smckusick 			else
1459a06587f5Smckusick 				retAddr = instPC + 8;
1460a06587f5Smckusick 			break;
1461a06587f5Smckusick 
1462a06587f5Smckusick 		case OP_BGEZAL:
1463a06587f5Smckusick 		case OP_BGEZ:
1464a0ea849cSralph 			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1465a0ea849cSralph 				retAddr = GetBranchDest((InstFmt *)instPC);
1466a06587f5Smckusick 			else
1467a06587f5Smckusick 				retAddr = instPC + 8;
1468a06587f5Smckusick 			break;
1469a06587f5Smckusick 
1470a06587f5Smckusick 		default:
1471a06587f5Smckusick 			panic("MachEmulateBranch: Bad branch cond");
1472a06587f5Smckusick 		}
1473a06587f5Smckusick 		break;
1474a06587f5Smckusick 
1475a06587f5Smckusick 	case OP_J:
1476a06587f5Smckusick 	case OP_JAL:
1477a0ea849cSralph 		retAddr = (inst.JType.target << 2) |
1478a06587f5Smckusick 			((unsigned)instPC & 0xF0000000);
1479a06587f5Smckusick 		break;
1480a06587f5Smckusick 
1481a06587f5Smckusick 	case OP_BEQ:
1482a0ea849cSralph 		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1483a0ea849cSralph 			retAddr = GetBranchDest((InstFmt *)instPC);
1484a06587f5Smckusick 		else
1485a06587f5Smckusick 			retAddr = instPC + 8;
1486a06587f5Smckusick 		break;
1487a06587f5Smckusick 
1488a06587f5Smckusick 	case OP_BNE:
1489a0ea849cSralph 		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1490a0ea849cSralph 			retAddr = GetBranchDest((InstFmt *)instPC);
1491a06587f5Smckusick 		else
1492a06587f5Smckusick 			retAddr = instPC + 8;
1493a06587f5Smckusick 		break;
1494a06587f5Smckusick 
1495a06587f5Smckusick 	case OP_BLEZ:
1496a0ea849cSralph 		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1497a0ea849cSralph 			retAddr = GetBranchDest((InstFmt *)instPC);
1498a06587f5Smckusick 		else
1499a06587f5Smckusick 			retAddr = instPC + 8;
1500a06587f5Smckusick 		break;
1501a06587f5Smckusick 
1502a06587f5Smckusick 	case OP_BGTZ:
1503a0ea849cSralph 		if ((int)(regsPtr[inst.RType.rs]) > 0)
1504a0ea849cSralph 			retAddr = GetBranchDest((InstFmt *)instPC);
1505a06587f5Smckusick 		else
1506a06587f5Smckusick 			retAddr = instPC + 8;
1507a06587f5Smckusick 		break;
1508a06587f5Smckusick 
1509a0ea849cSralph 	case OP_COP1:
1510a0ea849cSralph 		switch (inst.RType.rs) {
1511a0ea849cSralph 		case OP_BCx:
1512a0ea849cSralph 		case OP_BCy:
1513a0ea849cSralph 			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1514a06587f5Smckusick 				condition = fpcCSR & MACH_FPC_COND_BIT;
1515a06587f5Smckusick 			else
1516a06587f5Smckusick 				condition = !(fpcCSR & MACH_FPC_COND_BIT);
1517a06587f5Smckusick 			if (condition)
1518a0ea849cSralph 				retAddr = GetBranchDest((InstFmt *)instPC);
1519a06587f5Smckusick 			else
1520a06587f5Smckusick 				retAddr = instPC + 8;
1521a0ea849cSralph 			break;
1522a0ea849cSralph 
1523a0ea849cSralph 		default:
1524a0ea849cSralph 			if (!allowNonBranch)
1525a06587f5Smckusick 				panic("MachEmulateBranch: Bad coproc branch instruction");
1526a0ea849cSralph 			retAddr = instPC + 4;
1527a0ea849cSralph 		}
1528a06587f5Smckusick 		break;
1529a06587f5Smckusick 
1530a06587f5Smckusick 	default:
1531a06587f5Smckusick 		if (!allowNonBranch)
1532a06587f5Smckusick 			panic("MachEmulateBranch: Non-branch instruction");
1533a06587f5Smckusick 		retAddr = instPC + 4;
1534a06587f5Smckusick 	}
1535a0ea849cSralph #if 0
15364ab0a127Smckusick 	printf("Target addr=%x\n", retAddr); /* XXX */
1537a06587f5Smckusick #endif
1538a06587f5Smckusick 	return (retAddr);
1539a06587f5Smckusick }
1540a06587f5Smckusick 
1541a06587f5Smckusick unsigned
GetBranchDest(InstPtr)1542a06587f5Smckusick GetBranchDest(InstPtr)
1543a06587f5Smckusick 	InstFmt *InstPtr;
1544a06587f5Smckusick {
1545a06587f5Smckusick 	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));
1546a06587f5Smckusick }
1547a0ea849cSralph 
1548a0ea849cSralph /*
1549a0ea849cSralph  * This routine is called by procxmt() to single step one instruction.
1550a0ea849cSralph  * We do this by storing a break instruction after the current instruction,
1551a0ea849cSralph  * resuming execution, and then restoring the old instruction.
1552a0ea849cSralph  */
cpu_singlestep(p)1553a0ea849cSralph cpu_singlestep(p)
1554a0ea849cSralph 	register struct proc *p;
1555a0ea849cSralph {
1556a0ea849cSralph 	register unsigned va;
1557a43518feSralph 	register int *locr0 = p->p_md.md_regs;
1558a0ea849cSralph 	int i;
1559a0ea849cSralph 
1560a0ea849cSralph 	/* compute next address after current location */
15614ab0a127Smckusick 	va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], 1);
1562a0ea849cSralph 	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||
1563a0ea849cSralph 	    !useracc((caddr_t)va, 4, B_READ)) {
1564a0ea849cSralph 		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1565a0ea849cSralph 			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
1566a0ea849cSralph 		return (EFAULT);
1567a0ea849cSralph 	}
1568a0ea849cSralph 	p->p_md.md_ss_addr = va;
156943e69fa3Sralph 	p->p_md.md_ss_instr = fuiword((caddr_t)va);
1570a0ea849cSralph 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1571a0ea849cSralph 	if (i < 0) {
1572a0ea849cSralph 		vm_offset_t sa, ea;
1573a0ea849cSralph 		int rv;
1574a0ea849cSralph 
1575a0ea849cSralph 		sa = trunc_page((vm_offset_t)va);
1576a0ea849cSralph 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
1577a0ea849cSralph 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
1578a0ea849cSralph 			VM_PROT_DEFAULT, FALSE);
1579a0ea849cSralph 		if (rv == KERN_SUCCESS) {
1580a0ea849cSralph 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1581a0ea849cSralph 			(void) vm_map_protect(&p->p_vmspace->vm_map,
1582a0ea849cSralph 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1583a0ea849cSralph 		}
1584a0ea849cSralph 	}
1585a0ea849cSralph 	if (i < 0)
1586a0ea849cSralph 		return (EFAULT);
15874ab0a127Smckusick #if 0
15884ab0a127Smckusick 	printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
1589a0ea849cSralph 		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
15904ab0a127Smckusick 		p->p_md.md_ss_instr, locr0[PC], fuword((caddr_t)va)); /* XXX */
15914ab0a127Smckusick #endif
1592a0ea849cSralph 	return (0);
1593a0ea849cSralph }
15942e260a69Sralph 
15952e260a69Sralph #ifdef DEBUG
kdbpeek(addr)15962e260a69Sralph kdbpeek(addr)
15972e260a69Sralph {
15982e260a69Sralph 	if (addr & 3) {
15992e260a69Sralph 		printf("kdbpeek: unaligned address %x\n", addr);
16002e260a69Sralph 		return (-1);
16012e260a69Sralph 	}
16022e260a69Sralph 	return (*(int *)addr);
16032e260a69Sralph }
16042e260a69Sralph 
16052e260a69Sralph #define MIPS_JR_RA	0x03e00008	/* instruction code for jr ra */
16062e260a69Sralph 
16072e260a69Sralph /*
16082e260a69Sralph  * Print a stack backtrace.
16092e260a69Sralph  */
16102e260a69Sralph void
stacktrace(a0,a1,a2,a3)16118f497010Sralph stacktrace(a0, a1, a2, a3)
16128f497010Sralph 	int a0, a1, a2, a3;
16132e260a69Sralph {
16142e260a69Sralph 	unsigned pc, sp, fp, ra, va, subr;
16152e260a69Sralph 	unsigned instr, mask;
16162e260a69Sralph 	InstFmt i;
16172e260a69Sralph 	int more, stksize;
16188f497010Sralph 	int regs[3];
16192e260a69Sralph 	extern setsoftclock();
16202e260a69Sralph 	extern char start[], edata[];
16212e260a69Sralph 
16222e260a69Sralph 	cpu_getregs(regs);
16232e260a69Sralph 
16242e260a69Sralph 	/* get initial values from the exception frame */
16252e260a69Sralph 	sp = regs[0];
16268f497010Sralph 	pc = regs[1];
16272e260a69Sralph 	ra = 0;
16288f497010Sralph 	fp = regs[2];
16292e260a69Sralph 
16302e260a69Sralph loop:
16312e260a69Sralph 	/* check for current PC in the kernel interrupt handler code */
16322e260a69Sralph 	if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) {
16332e260a69Sralph 		/* NOTE: the offsets depend on the code in locore.s */
16342e260a69Sralph 		printf("interrupt\n");
16352e260a69Sralph 		a0 = kdbpeek(sp + 36);
16362e260a69Sralph 		a1 = kdbpeek(sp + 40);
16372e260a69Sralph 		a2 = kdbpeek(sp + 44);
16382e260a69Sralph 		a3 = kdbpeek(sp + 48);
16392e260a69Sralph 		pc = kdbpeek(sp + 20);
16402e260a69Sralph 		ra = kdbpeek(sp + 92);
16412e260a69Sralph 		sp = kdbpeek(sp + 100);
16422e260a69Sralph 		fp = kdbpeek(sp + 104);
16432e260a69Sralph 	}
16442e260a69Sralph 
16452e260a69Sralph 	/* check for current PC in the exception handler code */
16462e260a69Sralph 	if (pc >= 0x80000000 && pc < (unsigned)setsoftclock) {
16472e260a69Sralph 		ra = 0;
16482e260a69Sralph 		subr = 0;
16492e260a69Sralph 		goto done;
16502e260a69Sralph 	}
16512e260a69Sralph 
16522e260a69Sralph 	/* check for bad PC */
16532e260a69Sralph 	if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
16542e260a69Sralph 		printf("PC 0x%x: not in kernel\n", pc);
16552e260a69Sralph 		ra = 0;
16562e260a69Sralph 		subr = 0;
16572e260a69Sralph 		goto done;
16582e260a69Sralph 	}
16592e260a69Sralph 
16602e260a69Sralph 	/*
16612e260a69Sralph 	 * Find the beginning of the current subroutine by scanning backwards
16622e260a69Sralph 	 * from the current PC for the end of the previous subroutine.
16632e260a69Sralph 	 */
16642e260a69Sralph 	va = pc - sizeof(int);
16652e260a69Sralph 	while ((instr = kdbpeek(va)) != MIPS_JR_RA)
16662e260a69Sralph 		va -= sizeof(int);
16672e260a69Sralph 	va += 2 * sizeof(int);	/* skip back over branch & delay slot */
16682e260a69Sralph 	/* skip over nulls which might separate .o files */
16692e260a69Sralph 	while ((instr = kdbpeek(va)) == 0)
16702e260a69Sralph 		va += sizeof(int);
16712e260a69Sralph 	subr = va;
16722e260a69Sralph 
16732e260a69Sralph 	/* scan forwards to find stack size and any saved registers */
16742e260a69Sralph 	stksize = 0;
16752e260a69Sralph 	more = 3;
16762e260a69Sralph 	mask = 0;
16772e260a69Sralph 	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
16782e260a69Sralph 		/* stop if hit our current position */
16792e260a69Sralph 		if (va >= pc)
16802e260a69Sralph 			break;
16812e260a69Sralph 		instr = kdbpeek(va);
16822e260a69Sralph 		i.word = instr;
16832e260a69Sralph 		switch (i.JType.op) {
16842e260a69Sralph 		case OP_SPECIAL:
16852e260a69Sralph 			switch (i.RType.func) {
16862e260a69Sralph 			case OP_JR:
16872e260a69Sralph 			case OP_JALR:
16882e260a69Sralph 				more = 2; /* stop after next instruction */
16892e260a69Sralph 				break;
16902e260a69Sralph 
16912e260a69Sralph 			case OP_SYSCALL:
16922e260a69Sralph 			case OP_BREAK:
16932e260a69Sralph 				more = 1; /* stop now */
16942e260a69Sralph 			};
16952e260a69Sralph 			break;
16962e260a69Sralph 
16972e260a69Sralph 		case OP_BCOND:
16982e260a69Sralph 		case OP_J:
16992e260a69Sralph 		case OP_JAL:
17002e260a69Sralph 		case OP_BEQ:
17012e260a69Sralph 		case OP_BNE:
17022e260a69Sralph 		case OP_BLEZ:
17032e260a69Sralph 		case OP_BGTZ:
17042e260a69Sralph 			more = 2; /* stop after next instruction */
17052e260a69Sralph 			break;
17062e260a69Sralph 
17072e260a69Sralph 		case OP_COP0:
17082e260a69Sralph 		case OP_COP1:
17092e260a69Sralph 		case OP_COP2:
17102e260a69Sralph 		case OP_COP3:
17112e260a69Sralph 			switch (i.RType.rs) {
17122e260a69Sralph 			case OP_BCx:
17132e260a69Sralph 			case OP_BCy:
17142e260a69Sralph 				more = 2; /* stop after next instruction */
17152e260a69Sralph 			};
17162e260a69Sralph 			break;
17172e260a69Sralph 
17182e260a69Sralph 		case OP_SW:
17192e260a69Sralph 			/* look for saved registers on the stack */
17202e260a69Sralph 			if (i.IType.rs != 29)
17212e260a69Sralph 				break;
17222e260a69Sralph 			/* only restore the first one */
17232e260a69Sralph 			if (mask & (1 << i.IType.rt))
17242e260a69Sralph 				break;
17252e260a69Sralph 			mask |= 1 << i.IType.rt;
17262e260a69Sralph 			switch (i.IType.rt) {
17272e260a69Sralph 			case 4: /* a0 */
17282e260a69Sralph 				a0 = kdbpeek(sp + (short)i.IType.imm);
17292e260a69Sralph 				break;
17302e260a69Sralph 
17312e260a69Sralph 			case 5: /* a1 */
17322e260a69Sralph 				a1 = kdbpeek(sp + (short)i.IType.imm);
17332e260a69Sralph 				break;
17342e260a69Sralph 
17352e260a69Sralph 			case 6: /* a2 */
17362e260a69Sralph 				a2 = kdbpeek(sp + (short)i.IType.imm);
17372e260a69Sralph 				break;
17382e260a69Sralph 
17392e260a69Sralph 			case 7: /* a3 */
17402e260a69Sralph 				a3 = kdbpeek(sp + (short)i.IType.imm);
17412e260a69Sralph 				break;
17422e260a69Sralph 
17432e260a69Sralph 			case 30: /* fp */
17442e260a69Sralph 				fp = kdbpeek(sp + (short)i.IType.imm);
17452e260a69Sralph 				break;
17462e260a69Sralph 
17472e260a69Sralph 			case 31: /* ra */
17482e260a69Sralph 				ra = kdbpeek(sp + (short)i.IType.imm);
17492e260a69Sralph 			}
17502e260a69Sralph 			break;
17512e260a69Sralph 
17522e260a69Sralph 		case OP_ADDI:
17532e260a69Sralph 		case OP_ADDIU:
17542e260a69Sralph 			/* look for stack pointer adjustment */
17552e260a69Sralph 			if (i.IType.rs != 29 || i.IType.rt != 29)
17562e260a69Sralph 				break;
17572e260a69Sralph 			stksize = (short)i.IType.imm;
17582e260a69Sralph 		}
17592e260a69Sralph 	}
17602e260a69Sralph 
17612e260a69Sralph done:
17622e260a69Sralph 	printf("%x+%x (%x,%x,%x,%x) ra %x sz %d\n",
17632e260a69Sralph 		subr, pc - subr, a0, a1, a2, a3, ra, stksize);
17642e260a69Sralph 
17652e260a69Sralph 	if (ra) {
17662e260a69Sralph 		if (pc == ra && stksize == 0)
17672e260a69Sralph 			printf("stacktrace: loop!\n");
17682e260a69Sralph 		else {
17692e260a69Sralph 			pc = ra;
17702e260a69Sralph 			sp -= stksize;
17712e260a69Sralph 			goto loop;
17722e260a69Sralph 		}
17732e260a69Sralph 	}
17742e260a69Sralph }
17752e260a69Sralph #endif /* DEBUG */
1776