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