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