1/* $NetBSD: trap.c,v 1.8 2009/03/14 15:36:08 dsl Exp $ */
2
3/*-
4 * Copyright (c) 2005 Marcel Moolenaar
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 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*-
30 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
31 * All rights reserved.
32 *
33 * This code is derived from software contributed to The NetBSD Foundation
34 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
35 * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
57 */
58
59
60#include "opt_ddb.h"
61
62#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
63
64__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.8 2009/03/14 15:36:08 dsl Exp $");
65
66#include <sys/param.h>
67#include <sys/systm.h>
68#include <sys/proc.h>
69#include <sys/sa.h>
70#include <sys/savar.h>
71
72#include <sys/userret.h>
73
74#include <uvm/uvm_extern.h>
75
76#include <machine/frame.h>
77#include <machine/md_var.h>
78#include <machine/cpu.h>
79#include <machine/ia64_cpu.h>
80#include <machine/fpu.h>
81#ifdef DDB
82#include <machine/db_machdep.h>
83#include <ddb/db_extern.h>
84#endif
85
86#include <ia64/disasm/disasm.h>
87
88
89static const char *ia64_vector_names[] = {
90	"VHPT Translation",			/* 0 */
91	"Instruction TLB",			/* 1 */
92	"Data TLB",				/* 2 */
93	"Alternate Instruction TLB",		/* 3 */
94	"Alternate Data TLB",			/* 4 */
95	"Data Nested TLB",			/* 5 */
96	"Instruction Key Miss",			/* 6 */
97	"Data Key Miss",			/* 7 */
98	"Dirty-Bit",				/* 8 */
99	"Instruction Access-Bit",		/* 9 */
100	"Data Access-Bit",			/* 10 */
101	"Break Instruction",			/* 11 */
102	"External Interrupt",			/* 12 */
103	"Reserved 13",				/* 13 */
104	"Reserved 14",				/* 14 */
105	"Reserved 15",				/* 15 */
106	"Reserved 16",				/* 16 */
107	"Reserved 17",				/* 17 */
108	"Reserved 18",				/* 18 */
109	"Reserved 19",				/* 19 */
110	"Page Not Present",			/* 20 */
111	"Key Permission",			/* 21 */
112	"Instruction Access Rights",		/* 22 */
113	"Data Access Rights",			/* 23 */
114	"General Exception",			/* 24 */
115	"Disabled FP-Register",			/* 25 */
116	"NaT Consumption",			/* 26 */
117	"Speculation",				/* 27 */
118	"Reserved 28",				/* 28 */
119	"Debug",				/* 29 */
120	"Unaligned Reference",			/* 30 */
121	"Unsupported Data Reference",		/* 31 */
122	"Floating-point Fault",			/* 32 */
123	"Floating-point Trap",			/* 33 */
124	"Lower-Privilege Transfer Trap",	/* 34 */
125	"Taken Branch Trap",			/* 35 */
126	"Single Step Trap",			/* 36 */
127	"Reserved 37",				/* 37 */
128	"Reserved 38",				/* 38 */
129	"Reserved 39",				/* 39 */
130	"Reserved 40",				/* 40 */
131	"Reserved 41",				/* 41 */
132	"Reserved 42",				/* 42 */
133	"Reserved 43",				/* 43 */
134	"Reserved 44",				/* 44 */
135	"IA-32 Exception",			/* 45 */
136	"IA-32 Intercept",			/* 46 */
137	"IA-32 Interrupt",			/* 47 */
138	"Reserved 48",				/* 48 */
139	"Reserved 49",				/* 49 */
140	"Reserved 50",				/* 50 */
141	"Reserved 51",				/* 51 */
142	"Reserved 52",				/* 52 */
143	"Reserved 53",				/* 53 */
144	"Reserved 54",				/* 54 */
145	"Reserved 55",				/* 55 */
146	"Reserved 56",				/* 56 */
147	"Reserved 57",				/* 57 */
148	"Reserved 58",				/* 58 */
149	"Reserved 59",				/* 59 */
150	"Reserved 60",				/* 60 */
151	"Reserved 61",				/* 61 */
152	"Reserved 62",				/* 62 */
153	"Reserved 63",				/* 63 */
154	"Reserved 64",				/* 64 */
155	"Reserved 65",				/* 65 */
156	"Reserved 66",				/* 66 */
157	"Reserved 67",				/* 67 */
158};
159
160struct bitname {
161	uint64_t mask;
162	const char* name;
163};
164
165static void
166printbits(uint64_t mask, struct bitname *bn, int count)
167{
168	int i, first = 1;
169	uint64_t bit;
170
171	for (i = 0; i < count; i++) {
172		/*
173		 * Handle fields wider than one bit.
174		 */
175		bit = bn[i].mask & ~(bn[i].mask - 1);
176		if (bn[i].mask > bit) {
177			if (first)
178				first = 0;
179			else
180				printf(",");
181			printf("%s=%ld", bn[i].name,
182			       (mask & bn[i].mask) / bit);
183		} else if (mask & bit) {
184			if (first)
185				first = 0;
186			else
187				printf(",");
188			printf("%s", bn[i].name);
189		}
190	}
191}
192
193struct bitname psr_bits[] = {
194	{IA64_PSR_BE,	"be"},
195	{IA64_PSR_UP,	"up"},
196	{IA64_PSR_AC,	"ac"},
197	{IA64_PSR_MFL,	"mfl"},
198	{IA64_PSR_MFH,	"mfh"},
199	{IA64_PSR_IC,	"ic"},
200	{IA64_PSR_I,	"i"},
201	{IA64_PSR_PK,	"pk"},
202	{IA64_PSR_DT,	"dt"},
203	{IA64_PSR_DFL,	"dfl"},
204	{IA64_PSR_DFH,	"dfh"},
205	{IA64_PSR_SP,	"sp"},
206	{IA64_PSR_PP,	"pp"},
207	{IA64_PSR_DI,	"di"},
208	{IA64_PSR_SI,	"si"},
209	{IA64_PSR_DB,	"db"},
210	{IA64_PSR_LP,	"lp"},
211	{IA64_PSR_TB,	"tb"},
212	{IA64_PSR_RT,	"rt"},
213	{IA64_PSR_CPL,	"cpl"},
214	{IA64_PSR_IS,	"is"},
215	{IA64_PSR_MC,	"mc"},
216	{IA64_PSR_IT,	"it"},
217	{IA64_PSR_ID,	"id"},
218	{IA64_PSR_DA,	"da"},
219	{IA64_PSR_DD,	"dd"},
220	{IA64_PSR_SS,	"ss"},
221	{IA64_PSR_RI,	"ri"},
222	{IA64_PSR_ED,	"ed"},
223	{IA64_PSR_BN,	"bn"},
224	{IA64_PSR_IA,	"ia"},
225};
226
227static void
228printpsr(uint64_t psr)
229{
230	printbits(psr, psr_bits, sizeof(psr_bits)/sizeof(psr_bits[0]));
231}
232
233struct bitname isr_bits[] = {
234	{IA64_ISR_CODE,	"code"},
235	{IA64_ISR_VECTOR, "vector"},
236	{IA64_ISR_X,	"x"},
237	{IA64_ISR_W,	"w"},
238	{IA64_ISR_R,	"r"},
239	{IA64_ISR_NA,	"na"},
240	{IA64_ISR_SP,	"sp"},
241	{IA64_ISR_RS,	"rs"},
242	{IA64_ISR_IR,	"ir"},
243	{IA64_ISR_NI,	"ni"},
244	{IA64_ISR_SO,	"so"},
245	{IA64_ISR_EI,	"ei"},
246	{IA64_ISR_ED,	"ed"},
247};
248
249static void printisr(uint64_t isr)
250{
251	printbits(isr, isr_bits, sizeof(isr_bits)/sizeof(isr_bits[0]));
252}
253
254static void
255printtrap(int vector, struct trapframe *tf, int isfatal, int user)
256{
257
258	printf("\n");
259	printf("%s %s trap (cpu %lu):\n", isfatal? "fatal" : "handled",
260	       user ? "user" : "kernel", curcpu()->ci_cpuid);
261	printf("\n");
262	printf("    trap vector = 0x%x (%s)\n",
263	       vector, ia64_vector_names[vector]);
264	printf("    cr.iip      = 0x%lx\n", tf->tf_special.iip);
265	printf("    cr.ipsr     = 0x%lx (", tf->tf_special.psr);
266	printpsr(tf->tf_special.psr);
267	printf(")\n");
268	printf("    cr.isr      = 0x%lx (", tf->tf_special.isr);
269	printisr(tf->tf_special.isr);
270	printf(")\n");
271	printf("    cr.ifa      = 0x%lx\n", tf->tf_special.ifa);
272	if (tf->tf_special.psr & IA64_PSR_IS) {
273		printf("    ar.cflg     = 0x%lx\n", ia64_get_cflg());
274		printf("    ar.csd      = 0x%lx\n", ia64_get_csd());
275		printf("    ar.ssd      = 0x%lx\n", ia64_get_ssd());
276	}
277	printf("    curlwp   = %p\n", curlwp);
278	if (curproc != NULL)
279		printf("        pid = %d, comm = %s\n",
280		       curproc->p_pid, curproc->p_comm);
281	printf("\n");
282}
283
284/*
285 * We got a trap caused by a break instruction and the immediate was 0.
286 * This indicates that we may have a break.b with some non-zero immediate.
287 * The break.b doesn't cause the immediate to be put in cr.iim.  Hence,
288 * we need to disassemble the bundle and return the immediate found there.
289 * This may be a 0 value anyway.  Return 0 for any error condition.  This
290 * will result in a SIGILL, which is pretty much the best thing to do.
291 */
292static uint64_t
293trap_decode_break(struct trapframe *tf)
294{
295	struct asm_bundle bundle;
296	struct asm_inst *inst;
297	int slot;
298
299	if (!asm_decode(tf->tf_special.iip, &bundle))
300		return (0);
301
302	slot = ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_0) ? 0 :
303            ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_1) ? 1 : 2;
304	inst = bundle.b_inst + slot;
305
306	/*
307	 * Sanity checking: It must be a break instruction and the operand
308	 * that has the break value must be an immediate.
309	 */
310	if (inst->i_op != ASM_OP_BREAK ||
311	    inst->i_oper[1].o_type != ASM_OPER_IMM)
312		return (0);
313
314	return (inst->i_oper[1].o_value);
315}
316
317
318/*
319 * Start a new LWP
320 */
321void
322startlwp(void *arg)
323{
324printf("%s: not yet\n", __func__);
325	return;
326}
327
328void
329upcallret(struct lwp *l)
330{
331printf("%s: not yet\n", __func__);
332	return;
333}
334
335#ifdef DDB
336	int call_debugger = 1;
337
338/*
339 * Enter the debugger due to a trap.
340 */
341
342int
343ia64_trap(int type, int code, db_regs_t *regs)
344{
345
346	/* XXX: Switch stacks ? */
347
348	/* Debugger is not re-entrant. */
349
350	ddb_regp = regs;
351	db_trap(type, code);
352	return 1; /* XXX: Always handled ??? */
353
354}
355
356#endif
357
358void
359trap_panic(int vector, struct trapframe *tf)
360{
361
362	printtrap(vector, tf, 1, TRAPF_USERMODE(tf));
363
364#ifdef DDB
365	if (ia64_trap(vector, 0, tf)) return;
366#endif
367	panic("trap");
368
369	return;
370}
371
372/*
373 *
374 */
375int
376do_ast(struct trapframe *tf)
377{
378printf("%s: not yet\n", __func__);
379	return 0;
380}
381
382/*
383 * Trap is called from exception.s to handle most types of processor traps.
384 */
385/*ARGSUSED*/
386void
387trap(int vector, struct trapframe *tf)
388{
389
390	struct proc *p;
391	struct lwp *l;
392	uint64_t ucode;
393	int sig, user;
394	u_int sticks;
395	ksiginfo_t ksi;
396
397	user = TRAPF_USERMODE(tf) ? 1 : 0;
398
399	l = curlwp;
400
401	ucode = 0;
402
403#if 0
404	printtrap(vector, tf, 0, TRAPF_USERMODE(tf));
405#endif
406	if (user) {
407		ia64_set_fpsr(IA64_FPSR_DEFAULT);
408		p = l->l_proc;
409		sticks = p->p_sticks;
410		l->l_md.md_tf = tf;
411		LWP_CACHE_CREDS(l, p);
412	} else {
413		sticks = 0;		/* XXX bogus -Wuninitialized warning */
414		p = NULL;
415	}
416	sig = 0;
417	switch (vector) {
418	case IA64_VEC_VHPT:
419		/*
420		 * This one is tricky. We should hardwire the VHPT, but
421		 * don't at this time. I think we're mostly lucky that
422		 * the VHPT is mapped.
423		 */
424		trap_panic(vector, tf);
425		break;
426	case IA64_VEC_ITLB:
427	case IA64_VEC_DTLB:
428	case IA64_VEC_EXT_INTR:
429		/* We never call trap() with these vectors. */
430		trap_panic(vector, tf);
431		break;
432
433	case IA64_VEC_ALT_ITLB:
434	case IA64_VEC_ALT_DTLB:
435		/*
436		 * These should never happen, because regions 0-4 use the
437		 * VHPT. If we get one of these it means we didn't program
438		 * the region registers correctly.
439		 */
440		trap_panic(vector, tf);
441		break;
442
443	case IA64_VEC_NESTED_DTLB:
444		/*
445		 * We never call trap() with this vector. We may want to
446		 * do that in the future in case the nested TLB handler
447		 * could not find the translation it needs. In that case
448		 * we could switch to a special (hardwired) stack and
449		 * come here to produce a nice panic().
450		 */
451		trap_panic(vector, tf);
452		break;
453
454	case IA64_VEC_IKEY_MISS:
455	case IA64_VEC_DKEY_MISS:
456	case IA64_VEC_KEY_PERMISSION:
457		/*
458		 * We don't use protection keys, so we should never get
459		 * these faults.
460		 */
461		trap_panic(vector, tf);
462		break;
463
464	case IA64_VEC_DIRTY_BIT:
465	case IA64_VEC_INST_ACCESS:
466	case IA64_VEC_DATA_ACCESS:
467		/*
468		 * We get here if we read or write to a page of which the
469		 * PTE does not have the access bit or dirty bit set and
470		 * we can not find the PTE in our datastructures. This
471		 * either means we have a stale PTE in the TLB, or we lost
472		 * the PTE in our datastructures.
473		 */
474		trap_panic(vector, tf);
475		break;
476
477	case IA64_VEC_BREAK:
478		if (user) {
479			ucode = (int)tf->tf_special.ifa & 0x1FFFFF;
480			if (ucode == 0) {
481				/*
482				 * A break.b doesn't cause the immediate to be
483				 * stored in cr.iim (and saved in the TF in
484				 * tf_special.ifa).  We need to decode the
485				 * instruction to find out what the immediate
486				 * was.  Note that if the break instruction
487				 * didn't happen to be a break.b, but any
488				 * other break with an immediate of 0, we
489				 * will do unnecessary work to get the value
490				 * we already had.  Not an issue, because a
491				 * break 0 is invalid.
492				 */
493				ucode = trap_decode_break(tf);
494			}
495			if (ucode < 0x80000) {
496				/* Software interrupts. */
497				switch (ucode) {
498				case 0:		/* Unknown error. */
499					sig = SIGILL;
500					break;
501				case 1:		/* Integer divide by zero. */
502					sig = SIGFPE;
503					ucode = FPE_INTDIV;
504					break;
505				case 2:		/* Integer overflow. */
506					sig = SIGFPE;
507					ucode = FPE_INTOVF;
508					break;
509				case 3:		/* Range check/bounds check. */
510					sig = SIGFPE;
511					ucode = FPE_FLTSUB;
512					break;
513				case 6: 	/* Decimal overflow. */
514				case 7: 	/* Decimal divide by zero. */
515				case 8: 	/* Packed decimal error. */
516				case 9: 	/* Invalid ASCII digit. */
517				case 10:	/* Invalid decimal digit. */
518					sig = SIGFPE;
519					ucode = FPE_FLTINV;
520					break;
521				case 4:		/* Null pointer dereference. */
522				case 5:		/* Misaligned data. */
523				case 11:	/* Paragraph stack overflow. */
524					sig = SIGSEGV;
525					break;
526				default:
527					sig = SIGILL;
528					break;
529				}
530			} else if (ucode < 0x100000) {
531				/* Debugger breakpoint. */
532				tf->tf_special.psr &= ~IA64_PSR_SS;
533				sig = SIGTRAP;
534#if 0
535			} else if (ucode == 0x100000) {
536				break_syscall(tf);
537				return;		/* do_ast() already called. */
538
539			} else if (ucode == 0x180000) {
540				mcontext_t mc;
541
542				error = copyin((void*)tf->tf_scratch.gr8,
543				    &mc, sizeof(mc));
544				if (!error) {
545					set_mcontext(td, &mc);
546					return;	/* Don't call do_ast()!!! */
547				}
548				sig = SIGSEGV;
549				ucode = tf->tf_scratch.gr8;
550#endif
551			} else
552				sig = SIGILL;
553		} else {
554			trap_panic(vector, tf);
555			goto out;
556		}
557		break;
558
559/* XXX: Fill in the rest */
560
561	case IA64_VEC_DEBUG:
562	case IA64_VEC_SINGLE_STEP_TRAP:
563		tf->tf_special.psr &= ~IA64_PSR_SS;
564		if (!user) {
565			trap_panic(vector, tf);
566			goto out;
567		}
568		sig = SIGTRAP;
569		break;
570
571
572
573	default:
574		/* Reserved vectors get here. Should never happen of course. */
575		trap_panic(vector, tf);
576		break;
577	}
578
579	printf("sig = %d", sig);
580	KASSERT(sig != 0);
581
582	KSI_INIT(&ksi);
583	ksi.ksi_signo = sig;
584	ksi.ksi_code = ucode;
585	trapsignal(l, &ksi);
586
587#if 1
588out:
589#endif
590
591	if (user) {
592		mi_userret(l);
593	}
594
595
596	return;
597}
598