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