trap.c revision 81337
1248590Smm/*-
2248590Smm * Copyright (C) 1994, David Greenman
3248590Smm * Copyright (c) 1990, 1993
4248590Smm *      The Regents of the University of California.  All rights reserved.
5248590Smm *
6248590Smm * This code is derived from software contributed to Berkeley by
7248590Smm * the University of Utah, and William Jolitz.
8248590Smm *
9248590Smm * Redistribution and use in source and binary forms, with or without
10248590Smm * modification, are permitted provided that the following conditions
11248590Smm * are met:
12248590Smm * 1. Redistributions of source code must retain the above copyright
13248590Smm *    notice, this list of conditions and the following disclaimer.
14248590Smm * 2. Redistributions in binary form must reproduce the above copyright
15248590Smm *    notice, this list of conditions and the following disclaimer in the
16248590Smm *    documentation and/or other materials provided with the distribution.
17248590Smm * 3. All advertising materials mentioning features or use of this software
18248590Smm *    must display the following acknowledgement:
19248590Smm *      This product includes software developed by the University of
20248590Smm *      California, Berkeley and its contributors.
21248590Smm * 4. Neither the name of the University nor the names of its contributors
22248590Smm *    may be used to endorse or promote products derived from this software
23248590Smm *    without specific prior written permission.
24248590Smm *
25248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26248590Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27248590Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28248590Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29248590Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30248590Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31248590Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32248590Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33248590Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34248590Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35248590Smm * SUCH DAMAGE.
36248590Smm *
37248590Smm *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
38248590Smm * 	from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
39248590Smm */
40248590Smm/*-
41248590Smm * Copyright (c) 2001 Jake Burkholder.
42248590Smm * All rights reserved.
43248590Smm *
44248590Smm * Redistribution and use in source and binary forms, with or without
45248590Smm * modification, are permitted provided that the following conditions
46248590Smm * are met:
47248590Smm * 1. Redistributions of source code must retain the above copyright
48248590Smm *    notice, this list of conditions and the following disclaimer.
49248590Smm * 2. Redistributions in binary form must reproduce the above copyright
50248590Smm *    notice, this list of conditions and the following disclaimer in the
51248590Smm *    documentation and/or other materials provided with the distribution.
52248590Smm *
53248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54248590Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55248590Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56248590Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57248590Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58248590Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59248590Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60248590Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61248590Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62248590Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63248590Smm * SUCH DAMAGE.
64248590Smm *
65248590Smm * $FreeBSD: head/sys/sparc64/sparc64/trap.c 81337 2001-08-09 02:32:05Z obrien $
66248590Smm */
67248590Smm
68248590Smm#include "opt_ddb.h"
69248590Smm
70248590Smm#include <sys/param.h>
71248590Smm#include <sys/lock.h>
72248590Smm#include <sys/mutex.h>
73248590Smm#include <sys/systm.h>
74248590Smm#include <sys/proc.h>
75248590Smm#include <sys/sysent.h>
76248590Smm#include <sys/user.h>
77248590Smm
78248590Smm#include <vm/vm.h>
79248590Smm#include <vm/pmap.h>
80248590Smm#include <vm/vm_extern.h>
81248590Smm#include <vm/vm_param.h>
82248590Smm#include <vm/vm_kern.h>
83248590Smm#include <vm/vm_map.h>
84248590Smm#include <vm/vm_page.h>
85248590Smm
86248590Smm#include <machine/frame.h>
87248590Smm#include <machine/pcb.h>
88248590Smm#include <machine/pv.h>
89248590Smm#include <machine/trap.h>
90248590Smm#include <machine/tte.h>
91248590Smm#include <machine/tlb.h>
92248590Smm#include <machine/tsb.h>
93248590Smm
94248590Smmvoid trap(struct trapframe *tf);
95248590Smmint trap_mmu_fault(struct proc *p, struct trapframe *tf);
96248590Smm
97248590Smmconst char *trap_msg[] = {
98248590Smm	"reserved",
99248590Smm	"power on reset",
100248590Smm	"watchdog reset",
101248590Smm	"externally initiated reset",
102248590Smm	"software initiated reset",
103248590Smm	"red state exception",
104248590Smm	"instruction access exception",
105248590Smm	"instruction access error",
106248590Smm	"illegal instruction",
107248590Smm	"privileged opcode",
108248590Smm	"floating point disabled",
109248590Smm	"floating point exception ieee 754",
110248590Smm	"floating point exception other",
111248590Smm	"tag overflow",
112248590Smm	"division by zero",
113248590Smm	"data access exception",
114248590Smm	"data access error",
115248590Smm	"memory address not aligned",
116248590Smm	"lddf memory address not aligned",
117248590Smm	"stdf memory address not aligned",
118248590Smm	"privileged action",
119248590Smm	"interrupt vector",
120248590Smm	"physical address watchpoint",
121248590Smm	"virtual address watchpoint",
122248590Smm	"corrected ecc error",
123248590Smm	"fast instruction access mmu miss",
124248590Smm	"fast data access mmu miss",
125248590Smm	"fast data access protection",
126248590Smm	"bad spill",
127248590Smm	"bad fill",
128248590Smm	"breakpoint",
129248590Smm};
130248590Smm
131248590Smmvoid
132248590Smmtrap(struct trapframe *tf)
133248590Smm{
134248590Smm	u_quad_t sticks;
135248590Smm	struct proc *p;
136248590Smm	int ucode;
137248590Smm	int sig;
138248590Smm
139248590Smm	KASSERT(PCPU_GET(curproc) != NULL, ("trap: curproc NULL"));
140248590Smm	KASSERT(PCPU_GET(curpcb) != NULL, ("trap: curpcb NULL"));
141248590Smm
142248590Smm	p = PCPU_GET(curproc);
143248590Smm	ucode = tf->tf_type;	/* XXX */
144248590Smm
145248590Smm	mtx_lock_spin(&sched_lock);
146248590Smm	sticks = p->p_sticks;
147248590Smm	mtx_unlock_spin(&sched_lock);
148248590Smm
149248590Smm	switch (tf->tf_type) {
150248590Smm	case T_FP_DISABLED:
151248590Smm		if (fp_enable_proc(p))
152248590Smm			goto user;
153248590Smm		else {
154248590Smm			sig = SIGFPE;
155248590Smm			goto trapsig;
156248590Smm		}
157248590Smm		break;
158248590Smm#ifdef DDB
159248590Smm	case T_BREAKPOINT | T_KERNEL:
160		if (kdb_trap(tf) != 0)
161			goto out;
162		break;
163#endif
164	case T_DMMU_MISS | T_KERNEL:
165	case T_DMMU_PROT | T_KERNEL:
166		if (trap_mmu_fault(p, tf) == 0)
167			goto out;
168		break;
169	default:
170		break;
171	}
172	panic("trap: %s", trap_msg[tf->tf_type & ~T_KERNEL]);
173
174trapsig:
175	mtx_lock(&Giant);
176	/* Translate fault for emulators. */
177	if (p->p_sysent->sv_transtrap != NULL)
178		sig = (p->p_sysent->sv_transtrap)(sig, tf->tf_type);
179
180	trapsignal(p, sig, ucode);
181	mtx_unlock(&Giant);
182user:
183	userret(p, tf, sticks);
184	if (mtx_owned(&Giant))
185		mtx_unlock(&Giant);
186out:
187	return;
188}
189
190int
191trap_mmu_fault(struct proc *p, struct trapframe *tf)
192{
193	struct mmuframe *mf;
194	struct vmspace *vm;
195	vm_offset_t va;
196	vm_prot_t type;
197	int flags;
198	int rv;
199
200	KASSERT(p->p_vmspace != NULL, ("trap_dmmu_miss: vmspace NULL"));
201
202	rv = KERN_FAILURE;
203	mf = tf->tf_arg;
204	va = TLB_TAR_VA(mf->mf_tar);
205	switch (tf->tf_type) {
206	case T_DMMU_MISS | T_KERNEL:
207		/*
208		 * If the context is not nucleus, this is a fault on
209		 * non-kernel virtual memory.
210		 */
211		if (TLB_TAR_CTX(mf->mf_tar) != TLB_CTX_KERNEL &&
212		    PCPU_GET(curpcb)->pcb_onfault == NULL)
213			break;
214
215		/*
216		 * First try the tsb.  The primary tsb was already searched.
217		 */
218		vm = p->p_vmspace;
219		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0) {
220			rv = KERN_SUCCESS;
221			break;
222		}
223
224		/*
225		 * Not found, call the vm system.
226		 */
227
228		/*
229		 * XXX!!!
230		 */
231		type = VM_PROT_READ;
232		flags = VM_FAULT_NORMAL;
233
234		/*
235		 * Keep the process from being swapped out at this critical
236		 * time.
237		 */
238		PROC_LOCK(p);
239		++p->p_lock;
240		PROC_UNLOCK(p);
241
242		/*
243		 * Grow the stack if necessary.  vm_map_growstack only fails
244		 * if the va falls into a growable stack region and the stack
245		 * growth fails.  If it succeeds, or the va was not within a
246		 * growable stack region, fault in the user page.
247		 */
248		if (vm_map_growstack(p, va) != KERN_SUCCESS)
249			rv = KERN_FAILURE;
250		else
251			rv = vm_fault(&vm->vm_map, va, type, flags);
252
253		/*
254		 * Now the process can be swapped again.
255		 */
256		PROC_LOCK(p);
257		--p->p_lock;
258		PROC_UNLOCK(p);
259		break;
260	case T_DMMU_PROT | T_KERNEL:
261		/*
262		 * If the context is not nucleus, this is a fault on
263		 * non-kernel virtual memory.
264		 */
265		if (TLB_TAR_CTX(mf->mf_tar) != TLB_CTX_KERNEL &&
266		    PCPU_GET(curpcb)->pcb_onfault == NULL)
267			break;
268
269		/*
270		 * Only look in the tsb.  Write access to an unmapped page
271		 * causes a miss first, so the page must have already been
272		 * brought in by vm_fault, we just need to find the tte and
273		 * update the write bit.  XXX How do we tell them vm system
274		 * that we are now writing?
275		 */
276		vm = p->p_vmspace;
277		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0)
278			rv = KERN_SUCCESS;
279		break;
280	default:
281		break;
282	}
283	if (rv == KERN_SUCCESS)
284		return (0);
285	if (tf->tf_type & T_KERNEL) {
286		if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
287			tf->tf_tpc = PCPU_GET(curpcb)->pcb_onfault;
288			tf->tf_tnpc = tf->tf_tpc + 4;
289			return (0);
290		}
291	}
292	return (rv == KERN_PROTECTION_FAILURE ? SIGBUS : SIGSEGV);
293}
294