trap.c revision 81493
1/*-
2 * Copyright (C) 1994, David Greenman
3 * Copyright (c) 1990, 1993
4 *      The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the University of Utah, and William Jolitz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the University of
20 *      California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
38 * 	from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
39 */
40/*-
41 * Copyright (c) 2001 Jake Burkholder.
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 *    notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 *    notice, this list of conditions and the following disclaimer in the
51 *    documentation and/or other materials provided with the distribution.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * $FreeBSD: head/sys/sparc64/sparc64/trap.c 81493 2001-08-10 22:53:32Z jhb $
66 */
67
68#include "opt_ddb.h"
69
70#include <sys/param.h>
71#include <sys/lock.h>
72#include <sys/mutex.h>
73#include <sys/systm.h>
74#include <sys/proc.h>
75#include <sys/sysent.h>
76#include <sys/user.h>
77
78#include <vm/vm.h>
79#include <vm/pmap.h>
80#include <vm/vm_extern.h>
81#include <vm/vm_param.h>
82#include <vm/vm_kern.h>
83#include <vm/vm_map.h>
84#include <vm/vm_page.h>
85
86#include <machine/clock.h>
87#include <machine/frame.h>
88#include <machine/intr_machdep.h>
89#include <machine/pcb.h>
90#include <machine/pv.h>
91#include <machine/trap.h>
92#include <machine/tte.h>
93#include <machine/tlb.h>
94#include <machine/tsb.h>
95
96void trap(struct trapframe *tf);
97int trap_mmu_fault(struct proc *p, struct trapframe *tf);
98
99const char *trap_msg[] = {
100	"reserved",
101	"power on reset",
102	"watchdog reset",
103	"externally initiated reset",
104	"software initiated reset",
105	"red state exception",
106	"instruction access exception",
107	"instruction access error",
108	"illegal instruction",
109	"privileged opcode",
110	"floating point disabled",
111	"floating point exception ieee 754",
112	"floating point exception other",
113	"tag overflow",
114	"division by zero",
115	"data access exception",
116	"data access error",
117	"memory address not aligned",
118	"lddf memory address not aligned",
119	"stdf memory address not aligned",
120	"privileged action",
121	"interrupt vector",
122	"physical address watchpoint",
123	"virtual address watchpoint",
124	"corrected ecc error",
125	"fast instruction access mmu miss",
126	"fast data access mmu miss",
127	"fast data access protection",
128	"clock",
129	"bad spill",
130	"bad fill",
131	"breakpoint",
132};
133
134void
135trap(struct trapframe *tf)
136{
137	u_int sticks;
138	struct proc *p;
139	int error;
140	int ucode;
141	int type;
142	int sig;
143
144	KASSERT(PCPU_GET(curproc) != NULL, ("trap: curproc NULL"));
145	KASSERT(PCPU_GET(curpcb) != NULL, ("trap: curpcb NULL"));
146
147	p = PCPU_GET(curproc);
148	type = T_TYPE(tf->tf_type);
149	ucode = type;	/* XXX */
150
151	if ((type & T_KERNEL) == 0)
152		sticks = p->p_sticks;
153
154	switch (type) {
155	case T_FP_DISABLED:
156		if (fp_enable_proc(p))
157			goto user;
158		else {
159			sig = SIGFPE;
160			goto trapsig;
161		}
162		break;
163	case T_IMMU_MISS:
164	case T_DMMU_MISS:
165	case T_DMMU_PROT:
166		mtx_lock(&Giant);
167		error = trap_mmu_fault(p, tf);
168		mtx_unlock(&Giant);
169		if (error == 0)
170			goto user;
171		break;
172	case T_INTR:
173		intr_dispatch(T_LEVEL(tf->tf_type), tf);
174		goto user;
175#ifdef DDB
176	case T_BREAKPOINT | T_KERNEL:
177		if (kdb_trap(tf) != 0)
178			goto out;
179		break;
180#endif
181	case T_DMMU_MISS | T_KERNEL:
182	case T_DMMU_PROT | T_KERNEL:
183		mtx_lock(&Giant);
184		error = trap_mmu_fault(p, tf);
185		mtx_unlock(&Giant);
186		if (error == 0)
187			goto out;
188		break;
189	case T_INTR | T_KERNEL:
190		intr_dispatch(T_LEVEL(tf->tf_type), tf);
191		goto out;
192	default:
193		break;
194	}
195	panic("trap: %s", trap_msg[type & ~T_KERNEL]);
196
197trapsig:
198	mtx_lock(&Giant);
199	/* Translate fault for emulators. */
200	if (p->p_sysent->sv_transtrap != NULL)
201		sig = (p->p_sysent->sv_transtrap)(sig, type);
202
203	trapsignal(p, sig, ucode);
204	mtx_unlock(&Giant);
205user:
206	userret(p, tf, sticks);
207	if (mtx_owned(&Giant))
208		mtx_unlock(&Giant);
209out:
210	return;
211}
212
213int
214trap_mmu_fault(struct proc *p, struct trapframe *tf)
215{
216	struct mmuframe *mf;
217	struct vmspace *vm;
218	vm_offset_t va;
219	vm_prot_t type;
220	int rv;
221
222	KASSERT(p->p_vmspace != NULL, ("trap_dmmu_miss: vmspace NULL"));
223
224	type = 0;
225	rv = KERN_FAILURE;
226	mf = tf->tf_arg;
227	va = TLB_TAR_VA(mf->mf_tar);
228	switch (tf->tf_type) {
229	case T_DMMU_MISS | T_KERNEL:
230		/*
231		 * If the context is nucleus this is a soft fault on kernel
232		 * memory, just fault in the pages.
233		 */
234		if (TLB_TAR_CTX(mf->mf_tar) == TLB_CTX_KERNEL) {
235			rv = vm_fault(kernel_map, va, VM_PROT_READ,
236			    VM_FAULT_NORMAL);
237			break;
238		}
239
240		/*
241		 * Don't allow kernel mode faults on user memory unless
242		 * pcb_onfault is set.
243		 */
244		if (PCPU_GET(curpcb)->pcb_onfault == NULL)
245			break;
246		/* Fallthrough. */
247	case T_IMMU_MISS:
248	case T_DMMU_MISS:
249		/*
250		 * First try the tsb.  The primary tsb was already searched.
251		 */
252		vm = p->p_vmspace;
253		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0) {
254			rv = KERN_SUCCESS;
255			break;
256		}
257
258		/*
259		 * Not found, call the vm system.
260		 */
261
262		if (tf->tf_type == T_IMMU_MISS)
263			type = VM_PROT_EXECUTE | VM_PROT_READ;
264		else
265			type = VM_PROT_READ;
266
267		/*
268		 * Keep the process from being swapped out at this critical
269		 * time.
270		 */
271		PROC_LOCK(p);
272		++p->p_lock;
273		PROC_UNLOCK(p);
274
275		/*
276		 * Grow the stack if necessary.  vm_map_growstack only fails
277		 * if the va falls into a growable stack region and the stack
278		 * growth fails.  If it succeeds, or the va was not within a
279		 * growable stack region, fault in the user page.
280		 */
281		if (vm_map_growstack(p, va) != KERN_SUCCESS)
282			rv = KERN_FAILURE;
283		else
284			rv = vm_fault(&vm->vm_map, va, type, VM_FAULT_NORMAL);
285
286		/*
287		 * Now the process can be swapped again.
288		 */
289		PROC_LOCK(p);
290		--p->p_lock;
291		PROC_UNLOCK(p);
292		break;
293	case T_DMMU_PROT | T_KERNEL:
294		/*
295		 * Protection faults should not happen on kernel memory.
296		 */
297		if (TLB_TAR_CTX(mf->mf_tar) == TLB_CTX_KERNEL)
298			break;
299
300		/*
301		 * Don't allow kernel mode faults on user memory unless
302		 * pcb_onfault is set.
303		 */
304		if (PCPU_GET(curpcb)->pcb_onfault == NULL)
305			break;
306		/* Fallthrough. */
307	case T_DMMU_PROT:
308		/*
309		 * Only look in the tsb.  Write access to an unmapped page
310		 * causes a miss first, so the page must have already been
311		 * brought in by vm_fault, we just need to find the tte and
312		 * update the write bit.  XXX How do we tell them vm system
313		 * that we are now writing?
314		 */
315		vm = p->p_vmspace;
316		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0)
317			rv = KERN_SUCCESS;
318		break;
319	default:
320		break;
321	}
322	if (rv == KERN_SUCCESS)
323		return (0);
324	if (tf->tf_type & T_KERNEL) {
325		if (PCPU_GET(curpcb)->pcb_onfault != NULL &&
326		    TLB_TAR_CTX(mf->mf_tar) != TLB_CTX_KERNEL) {
327			tf->tf_tpc = (u_long)PCPU_GET(curpcb)->pcb_onfault;
328			tf->tf_tnpc = tf->tf_tpc + 4;
329			return (0);
330		}
331	}
332	return (rv == KERN_PROTECTION_FAILURE ? SIGBUS : SIGSEGV);
333}
334