trap.c revision 1.2
1/*	$OpenBSD: trap.c,v 1.2 1999/01/11 05:11:22 millert Exp $	*/
2
3/*
4 * Copyright (c) 1998 Michael Shalayeff
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Michael Shalayeff.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#define INTRDEBUG
34
35#include <sys/param.h>
36#include <sys/systm.h>
37
38#include <vm/vm.h>
39
40#include <machine/iomod.h>
41#include <machine/cpufunc.h>
42#include <machine/reg.h>
43#include <machine/db_machdep.h>
44#include <machine/autoconf.h>
45
46#define	FAULT_TYPE(op)	(VM_PROT_READ|(inst_load(op) ? 0 : VM_PROT_WRITE))
47
48const char *trap_type[] = {
49	"invalid interrupt vector",
50	"high priority machine check",
51	"power failure",
52	"recovery counter trap",
53	"external interrupt",
54	"low-priority machine check",
55	"instruction TLB miss fault",
56	"instruction protection trap",
57	"Illegal instruction trap",
58	"break instruction trap",
59	"privileged operation trap",
60	"privileged register trap",
61	"overflow trap",
62	"conditional trap",
63	"assist exception trap",
64	"data TLB miss fault",
65	"ITLB non-access miss fault",
66	"DTLB non-access miss fault",
67	"data protection trap/unalligned data reference trap",
68	"data break trap",
69	"TLB dirty bit trap",
70	"page reference trap",
71	"assist emulation trap",
72	"higher-privelege transfer trap",
73	"lower-privilege transfer trap",
74	"taken branch trap",
75	"data access rights trap",
76	"data protection ID trap",
77	"unaligned data ref trap",
78	"reserved",
79	"reserved 2"
80};
81int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);
82
83u_int32_t sir;
84
85void pmap_hptdump __P((void));
86void cpu_intr __P((struct trapframe *));
87
88void
89trap(type, frame)
90	int type;
91	struct trapframe *frame;
92{
93	struct proc *p = curproc;
94	register vm_offset_t va;
95	register vm_map_t map;
96	register pa_space_t space;
97	u_int opcode, t;
98	int ret;
99
100	va = frame->ior;
101	space = (pa_space_t) frame->isr;
102
103	if (USERMODE(frame->iioq_head)) {
104		type |= T_USER;
105		p->p_md.md_regs = frame;
106	}
107
108	if ((type & ~T_USER) != T_INTERRUPT)
109		printf("trap: %d, %s for %x:%x at %x:%x\n",
110		       type, trap_type[type & ~T_USER], space, va,
111		       frame->iisq_head, frame->iioq_head);
112
113	switch (type) {
114	case T_NONEXIST:
115	case T_NONEXIST|T_USER:
116		/* we are screwd up by the central scrutinizer */
117		panic ("trap: zombie on the bridge!!!");
118		break;
119
120	case T_RECOVERY:
121	case T_RECOVERY|T_USER:
122		printf ("trap: handicapped");
123		break;
124
125	case T_INTERRUPT:
126	case T_INTERRUPT|T_USER:
127		mfctl(CR_EIRR, t);
128		t &= frame->eiem;
129		/* hardcode intvl timer intr, to save for proc switching */
130		if (t & INT_ITMR) {
131			/* ACK it now */
132			mtctl(INT_ITMR, CR_EIRR);
133			/* we've got an interval timer interrupt */
134			cpu_initclocks();
135			hardclock(frame);
136		} else {
137#ifdef INTRDEBUG
138			printf ("cpu_intr: 0x%08x\n", t);
139#endif
140			cpu_intr(frame);
141		}
142		return;
143
144	case T_HPMC:
145	case T_POWERFAIL:
146	case T_LPMC:
147		break;
148
149	case T_IBREAK:
150	case T_DBREAK:
151		if (kdb_trap (type, 0, frame))
152			return;
153		break;
154
155	case T_DTLBMISS:
156		va = trunc_page(va);
157		opcode = frame->iir;
158
159#ifdef DDB
160		Debugger();
161#endif
162		ret = vm_fault(map, va, FAULT_TYPE(opcode), FALSE);
163		if (ret == KERN_SUCCESS)
164			break;
165		panic("trap: vm_fault(%p, %x, %d, %d): %d",
166		      map, va, FAULT_TYPE(opcode), 0, ret);
167		break;
168	default:
169		/* pmap_hptdump(); */
170#ifdef DDB
171		Debugger();
172#endif
173	}
174}
175
176/* all the interrupts, minus cpu clock, which is the last */
177struct cpu_intr_vector {
178	const char *name;
179	int pri;
180	int (*handler) __P((void *));
181	void *arg;
182} cpu_intr_vectors[CPU_NINTS - 1];
183#define	ECPU_INTR_VECTORS	&cpu_intr_vectors[CPU_NINTS - 1]
184
185int
186cpu_intr_establish(pri, handler, arg, name)
187	int pri;
188	int (*handler) __P((void *));
189	void *arg;
190	const char *name;
191{
192	register struct cpu_intr_vector *p;
193
194	for (p = cpu_intr_vectors; p < ECPU_INTR_VECTORS; p++)
195		if (!p->handler)
196			break;
197
198	/* no more vectors, fail */
199	if (p >= ECPU_INTR_VECTORS)
200		return 0;
201
202	p->name = name;
203	p->pri = pri;
204	p->handler = handler;
205	p->arg = arg;
206
207	return p - cpu_intr_vectors;
208}
209
210void
211cpu_intr(frame)
212	struct trapframe *frame;
213{
214	register u_int32_t t;
215	register struct cpu_intr_vector *p;
216	register int bit;
217
218	do {
219		mfctl(CR_EIRR, t);
220		t &= frame->eiem;
221		bit = ffs(t) - 1;
222		if (bit >= 0) {
223			mtctl(1 << bit, CR_EIRR);
224#ifdef INTRDEBUG
225			printf ("cpu_intr: 0x%x\n", (1 << bit));
226#endif
227			p = &cpu_intr_vectors[bit];
228			if (p->handler) {
229				register int s = splx(p->pri);
230				if (!(p->handler)(p->arg))
231					printf ("%s: can't handle interrupt\n",
232						p->name);
233				splx(s);
234			} else
235				printf ("cpu_intr: stray interrupt %d\n", bit);
236		}
237	} while (bit >= 0);
238}
239
240