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