trap.c revision 1.2
1/* $OpenBSD: trap.c,v 1.2 1999/01/11 05:11:22 millert Exp $ */ 2 3/* 4 * Copyright (c) 1998 Michael Shalayeff 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Michael Shalayeff. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#define INTRDEBUG 34 35#include <sys/param.h> 36#include <sys/systm.h> 37 38#include <vm/vm.h> 39 40#include <machine/iomod.h> 41#include <machine/cpufunc.h> 42#include <machine/reg.h> 43#include <machine/db_machdep.h> 44#include <machine/autoconf.h> 45 46#define FAULT_TYPE(op) (VM_PROT_READ|(inst_load(op) ? 0 : VM_PROT_WRITE)) 47 48const char *trap_type[] = { 49 "invalid interrupt vector", 50 "high priority machine check", 51 "power failure", 52 "recovery counter trap", 53 "external interrupt", 54 "low-priority machine check", 55 "instruction TLB miss fault", 56 "instruction protection trap", 57 "Illegal instruction trap", 58 "break instruction trap", 59 "privileged operation trap", 60 "privileged register trap", 61 "overflow trap", 62 "conditional trap", 63 "assist exception trap", 64 "data TLB miss fault", 65 "ITLB non-access miss fault", 66 "DTLB non-access miss fault", 67 "data protection trap/unalligned data reference trap", 68 "data break trap", 69 "TLB dirty bit trap", 70 "page reference trap", 71 "assist emulation trap", 72 "higher-privelege transfer trap", 73 "lower-privilege transfer trap", 74 "taken branch trap", 75 "data access rights trap", 76 "data protection ID trap", 77 "unaligned data ref trap", 78 "reserved", 79 "reserved 2" 80}; 81int trap_types = sizeof(trap_type)/sizeof(trap_type[0]); 82 83u_int32_t sir; 84 85void pmap_hptdump __P((void)); 86void cpu_intr __P((struct trapframe *)); 87 88void 89trap(type, frame) 90 int type; 91 struct trapframe *frame; 92{ 93 struct proc *p = curproc; 94 register vm_offset_t va; 95 register vm_map_t map; 96 register pa_space_t space; 97 u_int opcode, t; 98 int ret; 99 100 va = frame->ior; 101 space = (pa_space_t) frame->isr; 102 103 if (USERMODE(frame->iioq_head)) { 104 type |= T_USER; 105 p->p_md.md_regs = frame; 106 } 107 108 if ((type & ~T_USER) != T_INTERRUPT) 109 printf("trap: %d, %s for %x:%x at %x:%x\n", 110 type, trap_type[type & ~T_USER], space, va, 111 frame->iisq_head, frame->iioq_head); 112 113 switch (type) { 114 case T_NONEXIST: 115 case T_NONEXIST|T_USER: 116 /* we are screwd up by the central scrutinizer */ 117 panic ("trap: zombie on the bridge!!!"); 118 break; 119 120 case T_RECOVERY: 121 case T_RECOVERY|T_USER: 122 printf ("trap: handicapped"); 123 break; 124 125 case T_INTERRUPT: 126 case T_INTERRUPT|T_USER: 127 mfctl(CR_EIRR, t); 128 t &= frame->eiem; 129 /* hardcode intvl timer intr, to save for proc switching */ 130 if (t & INT_ITMR) { 131 /* ACK it now */ 132 mtctl(INT_ITMR, CR_EIRR); 133 /* we've got an interval timer interrupt */ 134 cpu_initclocks(); 135 hardclock(frame); 136 } else { 137#ifdef INTRDEBUG 138 printf ("cpu_intr: 0x%08x\n", t); 139#endif 140 cpu_intr(frame); 141 } 142 return; 143 144 case T_HPMC: 145 case T_POWERFAIL: 146 case T_LPMC: 147 break; 148 149 case T_IBREAK: 150 case T_DBREAK: 151 if (kdb_trap (type, 0, frame)) 152 return; 153 break; 154 155 case T_DTLBMISS: 156 va = trunc_page(va); 157 opcode = frame->iir; 158 159#ifdef DDB 160 Debugger(); 161#endif 162 ret = vm_fault(map, va, FAULT_TYPE(opcode), FALSE); 163 if (ret == KERN_SUCCESS) 164 break; 165 panic("trap: vm_fault(%p, %x, %d, %d): %d", 166 map, va, FAULT_TYPE(opcode), 0, ret); 167 break; 168 default: 169 /* pmap_hptdump(); */ 170#ifdef DDB 171 Debugger(); 172#endif 173 } 174} 175 176/* all the interrupts, minus cpu clock, which is the last */ 177struct cpu_intr_vector { 178 const char *name; 179 int pri; 180 int (*handler) __P((void *)); 181 void *arg; 182} cpu_intr_vectors[CPU_NINTS - 1]; 183#define ECPU_INTR_VECTORS &cpu_intr_vectors[CPU_NINTS - 1] 184 185int 186cpu_intr_establish(pri, handler, arg, name) 187 int pri; 188 int (*handler) __P((void *)); 189 void *arg; 190 const char *name; 191{ 192 register struct cpu_intr_vector *p; 193 194 for (p = cpu_intr_vectors; p < ECPU_INTR_VECTORS; p++) 195 if (!p->handler) 196 break; 197 198 /* no more vectors, fail */ 199 if (p >= ECPU_INTR_VECTORS) 200 return 0; 201 202 p->name = name; 203 p->pri = pri; 204 p->handler = handler; 205 p->arg = arg; 206 207 return p - cpu_intr_vectors; 208} 209 210void 211cpu_intr(frame) 212 struct trapframe *frame; 213{ 214 register u_int32_t t; 215 register struct cpu_intr_vector *p; 216 register int bit; 217 218 do { 219 mfctl(CR_EIRR, t); 220 t &= frame->eiem; 221 bit = ffs(t) - 1; 222 if (bit >= 0) { 223 mtctl(1 << bit, CR_EIRR); 224#ifdef INTRDEBUG 225 printf ("cpu_intr: 0x%x\n", (1 << bit)); 226#endif 227 p = &cpu_intr_vectors[bit]; 228 if (p->handler) { 229 register int s = splx(p->pri); 230 if (!(p->handler)(p->arg)) 231 printf ("%s: can't handle interrupt\n", 232 p->name); 233 splx(s); 234 } else 235 printf ("cpu_intr: stray interrupt %d\n", bit); 236 } 237 } while (bit >= 0); 238} 239 240