1*e494c7cfSmickey /* $OpenBSD: trap.c,v 1.17 2000/01/17 00:30:17 mickey Exp $ */ 2556d2ba7Smickey 3556d2ba7Smickey /* 48de28e3eSmickey * Copyright (c) 1998-2000 Michael Shalayeff 5556d2ba7Smickey * All rights reserved. 6556d2ba7Smickey * 7556d2ba7Smickey * Redistribution and use in source and binary forms, with or without 8556d2ba7Smickey * modification, are permitted provided that the following conditions 9556d2ba7Smickey * are met: 10556d2ba7Smickey * 1. Redistributions of source code must retain the above copyright 11556d2ba7Smickey * notice, this list of conditions and the following disclaimer. 12556d2ba7Smickey * 2. Redistributions in binary form must reproduce the above copyright 13556d2ba7Smickey * notice, this list of conditions and the following disclaimer in the 14556d2ba7Smickey * documentation and/or other materials provided with the distribution. 15556d2ba7Smickey * 3. All advertising materials mentioning features or use of this software 16556d2ba7Smickey * must display the following acknowledgement: 17556d2ba7Smickey * This product includes software developed by Michael Shalayeff. 18556d2ba7Smickey * 4. The name of the author may not be used to endorse or promote products 19556d2ba7Smickey * derived from this software without specific prior written permission. 20556d2ba7Smickey * 21556d2ba7Smickey * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22556d2ba7Smickey * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23556d2ba7Smickey * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24556d2ba7Smickey * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25556d2ba7Smickey * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26556d2ba7Smickey * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27556d2ba7Smickey * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28556d2ba7Smickey * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29556d2ba7Smickey * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30556d2ba7Smickey * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31556d2ba7Smickey */ 32556d2ba7Smickey 33a24c0b7aSmickey #undef INTRDEBUG 34af7386c3Smickey #define TRAPDEBUG 35556d2ba7Smickey 36556d2ba7Smickey #include <sys/param.h> 37556d2ba7Smickey #include <sys/systm.h> 38d412f1c2Smickey #include <sys/kernel.h> 39b9b95e0dSmickey #include <sys/syscall.h> 40b9b95e0dSmickey #include <sys/ktrace.h> 41d412f1c2Smickey #include <sys/proc.h> 42d412f1c2Smickey #include <sys/user.h> 43d412f1c2Smickey #include <sys/acct.h> 44d412f1c2Smickey #include <sys/signal.h> 45688a8060Smickey #include <sys/device.h> 46556d2ba7Smickey 47af7386c3Smickey #include <net/netisr.h> 48af7386c3Smickey 49556d2ba7Smickey #include <vm/vm.h> 508de28e3eSmickey #include <vm/vm_kern.h> 51b9b95e0dSmickey #include <uvm/uvm.h> 52556d2ba7Smickey 53556d2ba7Smickey #include <machine/iomod.h> 54556d2ba7Smickey #include <machine/cpufunc.h> 55556d2ba7Smickey #include <machine/reg.h> 56556d2ba7Smickey #include <machine/autoconf.h> 57556d2ba7Smickey 58137d3021Smickey #ifdef DDB 59137d3021Smickey #include <machine/db_machdep.h> 60137d3021Smickey #endif 61137d3021Smickey 62137d3021Smickey #if defined(INTRDEBUG) || defined(TRAPDEBUG) 63137d3021Smickey #include <ddb/db_output.h> 64137d3021Smickey #endif 65137d3021Smickey 66137d3021Smickey #define FAULT_TYPE(op) (VM_PROT_READ|(inst_store(op) ? VM_PROT_WRITE : 0)) 67556d2ba7Smickey 68556d2ba7Smickey const char *trap_type[] = { 69*e494c7cfSmickey "invalid", 70*e494c7cfSmickey "HPMC", 71556d2ba7Smickey "power failure", 72137d3021Smickey "recovery counter", 73556d2ba7Smickey "external interrupt", 74*e494c7cfSmickey "LPMC", 75*e494c7cfSmickey "ITLB miss fault", 76137d3021Smickey "instruction protection", 77137d3021Smickey "Illegal instruction", 78137d3021Smickey "break instruction", 79137d3021Smickey "privileged operation", 80137d3021Smickey "privileged register", 81137d3021Smickey "overflow", 82137d3021Smickey "conditional", 83137d3021Smickey "assist exception", 84*e494c7cfSmickey "DTLB miss", 85137d3021Smickey "ITLB non-access miss", 86137d3021Smickey "DTLB non-access miss", 87137d3021Smickey "data protection/rights/alignment", 88137d3021Smickey "data break", 89*e494c7cfSmickey "TLB dirty", 90137d3021Smickey "page reference", 91137d3021Smickey "assist emulation", 92*e494c7cfSmickey "higher-priv transfer", 93*e494c7cfSmickey "lower-priv transfer", 94137d3021Smickey "taken branch", 95137d3021Smickey "data access rights", 96*e494c7cfSmickey "data protection", 97137d3021Smickey "unaligned data ref", 98556d2ba7Smickey }; 99556d2ba7Smickey int trap_types = sizeof(trap_type)/sizeof(trap_type[0]); 100556d2ba7Smickey 101556d2ba7Smickey u_int32_t sir; 102b9b95e0dSmickey int want_resched; 103556d2ba7Smickey 104556d2ba7Smickey void pmap_hptdump __P((void)); 105a24c0b7aSmickey void cpu_intr __P((struct trapframe *frame)); 106b9b95e0dSmickey void syscall __P((struct trapframe *frame, int *args)); 107556d2ba7Smickey 108d412f1c2Smickey static __inline void 109d412f1c2Smickey userret (struct proc *p, register_t pc, u_quad_t oticks) 110d412f1c2Smickey { 111d412f1c2Smickey int sig; 112af7386c3Smickey 113d412f1c2Smickey /* take pending signals */ 114d412f1c2Smickey while ((sig = CURSIG(p)) != 0) 115d412f1c2Smickey postsig(sig); 116d412f1c2Smickey 117d412f1c2Smickey p->p_priority = p->p_usrpri; 118d412f1c2Smickey if (want_resched) { 119d412f1c2Smickey register int s; 120d412f1c2Smickey /* 121d412f1c2Smickey * Since we are curproc, a clock interrupt could 122d412f1c2Smickey * change our priority without changing run queues 123d412f1c2Smickey * (the running process is not kept on a run queue). 124d412f1c2Smickey * If this happened after we setrunqueue ourselves but 125d412f1c2Smickey * before we switch()'ed, we might not be on the queue 126d412f1c2Smickey * indicated by our priority. 127d412f1c2Smickey */ 128d412f1c2Smickey s = splstatclock(); 129d412f1c2Smickey setrunqueue(p); 130d412f1c2Smickey p->p_stats->p_ru.ru_nivcsw++; 131d412f1c2Smickey mi_switch(); 132d412f1c2Smickey splx(s); 133d412f1c2Smickey while ((sig = CURSIG(p)) != 0) 134d412f1c2Smickey postsig(sig); 135d412f1c2Smickey } 136d412f1c2Smickey 137d412f1c2Smickey /* 138d412f1c2Smickey * If profiling, charge recent system time to the trapped pc. 139d412f1c2Smickey */ 140d412f1c2Smickey if (p->p_flag & P_PROFIL) { 141d412f1c2Smickey extern int psratio; 142d412f1c2Smickey 143d412f1c2Smickey addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); 144d412f1c2Smickey } 145d412f1c2Smickey 146d412f1c2Smickey curpriority = p->p_priority; 147d412f1c2Smickey } 148d412f1c2Smickey 149556d2ba7Smickey void 150556d2ba7Smickey trap(type, frame) 151556d2ba7Smickey int type; 152556d2ba7Smickey struct trapframe *frame; 153556d2ba7Smickey { 154556d2ba7Smickey struct proc *p = curproc; 155137d3021Smickey struct pcb *pcbp; 156137d3021Smickey register vaddr_t va; 157556d2ba7Smickey register vm_map_t map; 158f17fa196Smickey struct vmspace *vm; 159af7386c3Smickey register vm_prot_t vftype; 160556d2ba7Smickey register pa_space_t space; 161a24c0b7aSmickey u_int opcode; 162556d2ba7Smickey int ret; 163af7386c3Smickey union sigval sv; 164a24c0b7aSmickey int s, si; 165137d3021Smickey const char *tts; 166556d2ba7Smickey 167137d3021Smickey opcode = frame->tf_iir; 168a24c0b7aSmickey if (type == T_ITLBMISS || type == T_ITLBMISSNA) { 169a24c0b7aSmickey va = frame->tf_iioq_head; 170a24c0b7aSmickey space = frame->tf_iisq_head; 171137d3021Smickey vftype = VM_PROT_EXECUTE; 172a24c0b7aSmickey } else { 173b9b95e0dSmickey va = frame->tf_ior; 174a24c0b7aSmickey space = frame->tf_isr; 175af7386c3Smickey vftype = FAULT_TYPE(opcode); 176556d2ba7Smickey } 177137d3021Smickey 178137d3021Smickey if (frame->tf_flags & TFF_LAST) 179137d3021Smickey p->p_md.md_regs = frame; 180137d3021Smickey 181af7386c3Smickey #ifdef TRAPDEBUG 182137d3021Smickey if ((type & ~T_USER) > trap_types) 183137d3021Smickey tts = "reserved"; 184137d3021Smickey else 185137d3021Smickey tts = trap_type[type & ~T_USER]; 186137d3021Smickey 187*e494c7cfSmickey if (type != T_INTERRUPT && (type & ~T_USER) != T_IBREAK) 188137d3021Smickey db_printf("trap: %d, %s for %x:%x at %x:%x, fl=%x, fp=%p\n", 189137d3021Smickey type, tts, space, va, frame->tf_iisq_head, 190137d3021Smickey frame->tf_iioq_head, frame->tf_flags, frame); 191a24c0b7aSmickey else if ((type & ~T_USER) == T_IBREAK) 192137d3021Smickey db_printf("trap: break instruction %x:%x at %x:%x, fp=%p\n", 193a24c0b7aSmickey break5(opcode), break13(opcode), 194137d3021Smickey frame->tf_iisq_head, frame->tf_iioq_head, frame); 195*e494c7cfSmickey 196*e494c7cfSmickey { 197*e494c7cfSmickey extern int etext; 198*e494c7cfSmickey if (frame < (struct trapframe *)&etext) 199*e494c7cfSmickey goto dead_end; 200*e494c7cfSmickey } 201d412f1c2Smickey #endif 202556d2ba7Smickey switch (type) { 203556d2ba7Smickey case T_NONEXIST: 204556d2ba7Smickey case T_NONEXIST|T_USER: 205137d3021Smickey #ifndef DDB 206af7386c3Smickey /* we've got screwed up by the central scrutinizer */ 207137d3021Smickey panic ("trap: elvis has just left the building!"); 208556d2ba7Smickey break; 209137d3021Smickey #endif 210556d2ba7Smickey case T_RECOVERY: 211556d2ba7Smickey case T_RECOVERY|T_USER: 212137d3021Smickey #ifndef DDB 213af7386c3Smickey /* XXX will implement later */ 214556d2ba7Smickey printf ("trap: handicapped"); 215556d2ba7Smickey break; 216d412f1c2Smickey #endif 21766d1ab7aSmickey 21866d1ab7aSmickey #ifdef DIAGNOSTIC 21966d1ab7aSmickey case T_EXCEPTION: 22066d1ab7aSmickey panic("FPU/SFU emulation botch"); 22166d1ab7aSmickey 22266d1ab7aSmickey /* these just can't happen ever */ 22366d1ab7aSmickey case T_PRIV_OP: 22466d1ab7aSmickey case T_PRIV_REG: 22566d1ab7aSmickey /* these just can't make it to the trap() ever */ 22666d1ab7aSmickey case T_HPMC: case T_HPMC | T_USER: 22766d1ab7aSmickey case T_EMULATION: case T_EMULATION | T_USER: 22866d1ab7aSmickey case T_TLB_DIRTY: case T_TLB_DIRTY | T_USER: 22966d1ab7aSmickey #endif 230f4daacd8Smickey case T_IBREAK: 231a24c0b7aSmickey case T_DATALIGN: 232a24c0b7aSmickey case T_DBREAK: 2338de28e3eSmickey dead_end: 234a24c0b7aSmickey #ifdef DDB 235a24c0b7aSmickey if (kdb_trap (type, 0, frame)) { 236a24c0b7aSmickey if (type == T_IBREAK) { 237f4daacd8Smickey /* skip break instruction */ 2388de28e3eSmickey frame->tf_iioq_head = frame->tf_iioq_tail; 239f4daacd8Smickey frame->tf_iioq_tail += 4; 240a24c0b7aSmickey } 241556d2ba7Smickey return; 242a24c0b7aSmickey } 243137d3021Smickey #else 244137d3021Smickey if (type == T_DATALIGN) 245137d3021Smickey panic ("trap: %s at 0x%x", tts, va); 246137d3021Smickey else 247137d3021Smickey panic ("trap: no debugger for \"%s\" (%d)", tts, type); 248a24c0b7aSmickey #endif 249556d2ba7Smickey break; 250556d2ba7Smickey 251af7386c3Smickey case T_IBREAK | T_USER: 252af7386c3Smickey case T_DBREAK | T_USER: 253af7386c3Smickey /* pass to user debugger */ 254d412f1c2Smickey break; 255d412f1c2Smickey 256af7386c3Smickey case T_EXCEPTION | T_USER: /* co-proc assist trap */ 257137d3021Smickey sv.sival_int = va; 258af7386c3Smickey trapsignal(p, SIGFPE, type &~ T_USER, FPE_FLTINV, sv); 259d412f1c2Smickey break; 260d412f1c2Smickey 261af7386c3Smickey case T_OVERFLOW | T_USER: 262137d3021Smickey sv.sival_int = va; 263af7386c3Smickey trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv); 264d412f1c2Smickey break; 265d412f1c2Smickey 266af7386c3Smickey case T_CONDITION | T_USER: 267af7386c3Smickey break; 268af7386c3Smickey 269af7386c3Smickey case T_ILLEGAL | T_USER: 270137d3021Smickey sv.sival_int = va; 271af7386c3Smickey trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv); 272af7386c3Smickey break; 273af7386c3Smickey 274af7386c3Smickey case T_PRIV_OP | T_USER: 275137d3021Smickey sv.sival_int = va; 276af7386c3Smickey trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv); 277af7386c3Smickey break; 278af7386c3Smickey 279af7386c3Smickey case T_PRIV_REG | T_USER: 280137d3021Smickey sv.sival_int = va; 281af7386c3Smickey trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv); 282af7386c3Smickey break; 283af7386c3Smickey 284af7386c3Smickey /* these should never got here */ 285af7386c3Smickey case T_HIGHERPL | T_USER: 286af7386c3Smickey case T_LOWERPL | T_USER: 287137d3021Smickey sv.sival_int = va; 288af7386c3Smickey trapsignal(p, SIGSEGV, type &~ T_USER, SEGV_ACCERR, sv); 289af7386c3Smickey break; 290af7386c3Smickey 291af7386c3Smickey case T_IPROT | T_USER: 292af7386c3Smickey case T_DPROT | T_USER: 293af7386c3Smickey sv.sival_int = va; 294af7386c3Smickey trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv); 295af7386c3Smickey break; 296af7386c3Smickey 297af7386c3Smickey case T_DPROT: 298137d3021Smickey case T_IPROT: 299137d3021Smickey case T_DATACC: case T_DATACC | T_USER: 300137d3021Smickey case T_ITLBMISS: case T_ITLBMISS | T_USER: 301137d3021Smickey case T_DTLBMISS: case T_DTLBMISS | T_USER: 302137d3021Smickey case T_ITLBMISSNA: case T_ITLBMISSNA | T_USER: 303137d3021Smickey case T_DTLBMISSNA: case T_DTLBMISSNA | T_USER: 304556d2ba7Smickey va = trunc_page(va); 305f17fa196Smickey vm = p->p_vmspace; 3068de28e3eSmickey 3078de28e3eSmickey if (!vm) 3088de28e3eSmickey goto dead_end; 3098de28e3eSmickey 3108de28e3eSmickey /* 311*e494c7cfSmickey * it could be a kernel map for exec_map faults 3128de28e3eSmickey */ 3138de28e3eSmickey if (!(type & T_USER) && space == HPPA_SID_KERNEL) 3148de28e3eSmickey map = kernel_map; 3158de28e3eSmickey else 316f17fa196Smickey map = &vm->vm_map; 317556d2ba7Smickey 318137d3021Smickey ret = uvm_fault(map, va, 0, vftype); 319f17fa196Smickey 320f17fa196Smickey /* 321f17fa196Smickey * If this was a stack access we keep track of the maximum 322f17fa196Smickey * accessed stack size. Also, if uvm_fault gets a protection 323f17fa196Smickey * failure it is due to accessing the stack region outside 324f17fa196Smickey * the current limit and we need to reflect that as an access 325f17fa196Smickey * error. 326f17fa196Smickey */ 327f17fa196Smickey if (va >= (vaddr_t)vm->vm_maxsaddr + vm->vm_ssize) { 328f17fa196Smickey if (ret == KERN_SUCCESS) { 329f17fa196Smickey vsize_t nss = clrnd(btoc(va - USRSTACK + NBPG)); 330f17fa196Smickey if (nss > vm->vm_ssize) 331f17fa196Smickey vm->vm_ssize = nss; 332f17fa196Smickey } else if (ret == KERN_PROTECTION_FAILURE) 333f17fa196Smickey ret = KERN_INVALID_ADDRESS; 334f17fa196Smickey } 335f17fa196Smickey 336af7386c3Smickey if (ret != KERN_SUCCESS) { 337af7386c3Smickey if (type & T_USER) { 338137d3021Smickey printf("trapsignal: uvm_fault\n"); 339af7386c3Smickey sv.sival_int = frame->tf_ior; 340af7386c3Smickey trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv); 341137d3021Smickey } else { 3428de28e3eSmickey if (p && p->p_addr->u_pcb.pcb_onfault) { 3438de28e3eSmickey #ifdef PMAPDEBUG 3448de28e3eSmickey printf("trap: copyin/out %d\n",ret); 345137d3021Smickey #endif 3468de28e3eSmickey pcbp = &p->p_addr->u_pcb; 3478de28e3eSmickey frame->tf_iioq_tail = 4 + 3488de28e3eSmickey (frame->tf_iioq_head = 3498de28e3eSmickey pcbp->pcb_onfault); 350137d3021Smickey pcbp->pcb_onfault = 0; 351137d3021Smickey break; 352af7386c3Smickey } 353137d3021Smickey #if 1 354137d3021Smickey if (kdb_trap (type, 0, frame)) 355137d3021Smickey return; 356137d3021Smickey #else 357137d3021Smickey panic("trap: uvm_fault(%p, %x, %d, %d): %d", 3582191603aSmickey map, va, 0, vftype, ret); 359137d3021Smickey #endif 360137d3021Smickey } 361137d3021Smickey } 362137d3021Smickey if (type == (T_DATACC|T_USER) && kdb_trap (type, 0, frame)) 363137d3021Smickey return; 364556d2ba7Smickey break; 365d412f1c2Smickey 366af7386c3Smickey case T_DATALIGN | T_USER: 367137d3021Smickey sv.sival_int = va; 368af7386c3Smickey trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv); 369af7386c3Smickey break; 370af7386c3Smickey 371a24c0b7aSmickey case T_INTERRUPT: 372a24c0b7aSmickey case T_INTERRUPT|T_USER: 373a24c0b7aSmickey cpu_intr(frame); 374137d3021Smickey #if 0 375137d3021Smickey if (kdb_trap (type, 0, frame)) 376137d3021Smickey return; 377137d3021Smickey #endif 378a24c0b7aSmickey /* FALLTHROUGH */ 379af7386c3Smickey case T_LOWERPL: 380a24c0b7aSmickey __asm __volatile ("ldcws 0(%1), %0" 381a24c0b7aSmickey : "=r" (si) : "r" (&sir)); 382af7386c3Smickey s = spl0(); 383a24c0b7aSmickey if (si & SIR_CLOCK) { 384af7386c3Smickey splclock(); 385af7386c3Smickey softclock(); 386af7386c3Smickey spl0(); 387af7386c3Smickey } 388af7386c3Smickey 389a24c0b7aSmickey if (si & SIR_NET) { 390af7386c3Smickey register int ni; 391af7386c3Smickey /* use atomic "load & clear" */ 392af7386c3Smickey __asm __volatile ("ldcws 0(%1), %0" 393af7386c3Smickey : "=r" (ni) : "r" (&netisr)); 394af7386c3Smickey splnet(); 395a24c0b7aSmickey #define DONET(m,c) if (ni & (1 << (m))) c() 396a24c0b7aSmickey #include "ether.h" 397af7386c3Smickey #if NETHER > 0 398af7386c3Smickey DONET(NETISR_ARP, arpintr); 399af7386c3Smickey #endif 400af7386c3Smickey #ifdef INET 401af7386c3Smickey DONET(NETISR_IP, ipintr); 402af7386c3Smickey #endif 403af7386c3Smickey #ifdef INET6 4040f823a0bSmickey DONET(NETISR_IPV6, ip6intr); 405af7386c3Smickey #endif 406af7386c3Smickey #ifdef NETATALK 407af7386c3Smickey DONET(NETISR_ATALK, atintr); 408af7386c3Smickey #endif 409af7386c3Smickey #ifdef IMP 410af7386c3Smickey DONET(NETISR_IMP, impintr); 411af7386c3Smickey #endif 412af7386c3Smickey #ifdef IPX 413af7386c3Smickey DONET(NETISR_IPX, ipxintr); 414af7386c3Smickey #endif 415af7386c3Smickey #ifdef NS 416af7386c3Smickey DONET(NETISR_NS, nsintr); 417af7386c3Smickey #endif 418af7386c3Smickey #ifdef ISO 419af7386c3Smickey DONET(NETISR_ISO, clnlintr); 420af7386c3Smickey #endif 421af7386c3Smickey #ifdef CCITT 422af7386c3Smickey DONET(NETISR_CCITT, ccittintr); 423af7386c3Smickey #endif 424af7386c3Smickey #ifdef NATM 425af7386c3Smickey DONET(NETISR_NATM, natmintr); 426af7386c3Smickey #endif 427af7386c3Smickey #include "ppp.h" 428af7386c3Smickey #if NPPP > 0 429af7386c3Smickey DONET(NETISR_PPP, pppintr); 430af7386c3Smickey #endif 431af7386c3Smickey #include "bridge.h" 432af7386c3Smickey #if NBRIDGE > 0 433af7386c3Smickey DONET(NETISR_BRIDGE, bridgeintr) 434af7386c3Smickey #endif 435af7386c3Smickey } 436af7386c3Smickey splx(s); 437af7386c3Smickey break; 438af7386c3Smickey 439af7386c3Smickey case T_OVERFLOW: 440af7386c3Smickey case T_CONDITION: 441af7386c3Smickey case T_ILLEGAL: 442af7386c3Smickey case T_HIGHERPL: 443af7386c3Smickey case T_TAKENBR: 444af7386c3Smickey case T_POWERFAIL: 445af7386c3Smickey case T_LPMC: 446af7386c3Smickey case T_PAGEREF: 447d412f1c2Smickey case T_DATAPID: case T_DATAPID | T_USER: 448d412f1c2Smickey if (0 /* T-chip */) { 449d412f1c2Smickey break; 450556d2ba7Smickey } 451d412f1c2Smickey /* FALLTHROUGH to unimplemented */ 452d412f1c2Smickey default: 453137d3021Smickey #if 1 454137d3021Smickey if (kdb_trap (type, 0, frame)) 455137d3021Smickey return; 456137d3021Smickey #endif 457137d3021Smickey panic ("trap: unimplemented \'%s\' (%d)", tts, type); 458d412f1c2Smickey } 459af7386c3Smickey 460af7386c3Smickey if (type & T_USER) 461af7386c3Smickey userret(p, p->p_md.md_regs->tf_iioq_head, 0); 462d412f1c2Smickey } 463d412f1c2Smickey 464d412f1c2Smickey void 465d412f1c2Smickey child_return(p) 466d412f1c2Smickey struct proc *p; 467d412f1c2Smickey { 468d412f1c2Smickey userret(p, p->p_md.md_regs->tf_iioq_head, 0); 469d412f1c2Smickey #ifdef KTRACE 470d412f1c2Smickey if (KTRPOINT(p, KTR_SYSRET)) 471d412f1c2Smickey ktrsysret(p->p_tracep, SYS_fork, 0, 0); 472d412f1c2Smickey #endif 473556d2ba7Smickey } 474556d2ba7Smickey 475b9b95e0dSmickey /* 476b9b95e0dSmickey * call actual syscall routine 477b9b95e0dSmickey * from the low-level syscall handler: 478b9b95e0dSmickey * - all HPPA_FRAME_NARGS syscall's arguments supposed to be copied onto 479b9b95e0dSmickey * our stack, this wins compared to copyin just needed amount anyway 480b9b95e0dSmickey * - register args are copied onto stack too 481b9b95e0dSmickey */ 482b9b95e0dSmickey void 483b9b95e0dSmickey syscall(frame, args) 484b9b95e0dSmickey struct trapframe *frame; 485b9b95e0dSmickey int *args; 486b9b95e0dSmickey { 487b9b95e0dSmickey register struct proc *p; 488b9b95e0dSmickey register const struct sysent *callp; 489b9b95e0dSmickey int nsys, code, argsize, error; 490b9b95e0dSmickey int rval[2]; 491b9b95e0dSmickey 492b9b95e0dSmickey uvmexp.syscalls++; 493b9b95e0dSmickey 494b9b95e0dSmickey if (!USERMODE(frame->tf_iioq_head)) 495b9b95e0dSmickey panic("syscall"); 496b9b95e0dSmickey 497b9b95e0dSmickey p = curproc; 498137d3021Smickey p->p_md.md_regs = frame; 499b9b95e0dSmickey nsys = p->p_emul->e_nsysent; 500b9b95e0dSmickey callp = p->p_emul->e_sysent; 501137d3021Smickey code = frame->tf_t1; 502b9b95e0dSmickey switch (code) { 503b9b95e0dSmickey case SYS_syscall: 504137d3021Smickey code = frame->tf_arg0; 505b9b95e0dSmickey args += 1; 506b9b95e0dSmickey break; 507b9b95e0dSmickey case SYS___syscall: 508b9b95e0dSmickey if (callp != sysent) 509b9b95e0dSmickey break; 510137d3021Smickey code = frame->tf_arg0; /* XXX or arg1? */ 511b9b95e0dSmickey args += 2; 512b9b95e0dSmickey } 513b9b95e0dSmickey 514b9b95e0dSmickey if (code < 0 || code >= nsys) 515b9b95e0dSmickey callp += p->p_emul->e_nosys; /* bad syscall # */ 516b9b95e0dSmickey else 517b9b95e0dSmickey callp += code; 518b9b95e0dSmickey argsize = callp->sy_argsize; 519b9b95e0dSmickey 520b9b95e0dSmickey #ifdef SYSCALL_DEBUG 521b9b95e0dSmickey scdebug_call(p, code, args); 522b9b95e0dSmickey #endif 523b9b95e0dSmickey #ifdef KTRACE 524b9b95e0dSmickey if (KTRPOINT(p, KTR_SYSCALL)) 525b9b95e0dSmickey ktrsyscall(p->p_tracep, code, argsize, args); 526b9b95e0dSmickey #endif 527b9b95e0dSmickey 528b9b95e0dSmickey rval[0] = 0; 529b9b95e0dSmickey rval[1] = 0; 530b9b95e0dSmickey switch (error = (*callp->sy_call)(p, args, rval)) { 531b9b95e0dSmickey case 0: 532137d3021Smickey /* curproc may change inside the fork() */ 533b9b95e0dSmickey frame->tf_ret0 = rval[0]; 534b9b95e0dSmickey frame->tf_ret1 = rval[1]; 535137d3021Smickey frame->tf_t1 = 0; 536b9b95e0dSmickey break; 537b9b95e0dSmickey case ERESTART: 538b9b95e0dSmickey frame->tf_iioq_head -= 4; /* right? XXX */ 539b9b95e0dSmickey break; 540b9b95e0dSmickey case EJUSTRETURN: 541b9b95e0dSmickey break; 542b9b95e0dSmickey default: 543b9b95e0dSmickey if (p->p_emul->e_errno) 544b9b95e0dSmickey error = p->p_emul->e_errno[error]; 545137d3021Smickey frame->tf_t1 = error; 546b9b95e0dSmickey break; 547b9b95e0dSmickey } 548137d3021Smickey p = curproc; 549b9b95e0dSmickey #ifdef SYSCALL_DEBUG 550b9b95e0dSmickey scdebug_ret(p, code, error, rval); 551b9b95e0dSmickey #endif 552137d3021Smickey userret(p, p->p_md.md_regs->tf_iioq_head, 0); 553b9b95e0dSmickey #ifdef KTRACE 554b9b95e0dSmickey if (KTRPOINT(p, KTR_SYSRET)) 555b9b95e0dSmickey ktrsysret(p->p_tracep, code, error, rval[0]); 556b9b95e0dSmickey #endif 557b9b95e0dSmickey } 558b9b95e0dSmickey 559556d2ba7Smickey /* all the interrupts, minus cpu clock, which is the last */ 560556d2ba7Smickey struct cpu_intr_vector { 5613a81311eSmickey struct evcnt evcnt; 562556d2ba7Smickey int pri; 563556d2ba7Smickey int (*handler) __P((void *)); 564556d2ba7Smickey void *arg; 565a24c0b7aSmickey } cpu_intr_vectors[CPU_NINTS]; 566556d2ba7Smickey 567b9b95e0dSmickey void * 5683a81311eSmickey cpu_intr_establish(pri, irq, handler, arg, dv) 569b9b95e0dSmickey int pri, irq; 570556d2ba7Smickey int (*handler) __P((void *)); 571556d2ba7Smickey void *arg; 5723a81311eSmickey struct device *dv; 573556d2ba7Smickey { 5743a81311eSmickey register struct cpu_intr_vector *iv; 575556d2ba7Smickey 576a24c0b7aSmickey if (0 <= irq && irq < CPU_NINTS && cpu_intr_vectors[irq].handler) 577b9b95e0dSmickey return NULL; 578556d2ba7Smickey 5793a81311eSmickey iv = &cpu_intr_vectors[irq]; 5803a81311eSmickey iv->pri = pri; 5813a81311eSmickey iv->handler = handler; 5823a81311eSmickey iv->arg = arg; 583688a8060Smickey evcnt_attach(dv, dv->dv_xname, &iv->evcnt); 584556d2ba7Smickey 585688a8060Smickey return iv; 586556d2ba7Smickey } 587556d2ba7Smickey 588556d2ba7Smickey void 589a24c0b7aSmickey cpu_intr(frame) 590556d2ba7Smickey struct trapframe *frame; 591556d2ba7Smickey { 592b9b95e0dSmickey u_int32_t eirr; 5933a81311eSmickey register struct cpu_intr_vector *iv; 594556d2ba7Smickey register int bit; 595556d2ba7Smickey 596556d2ba7Smickey do { 597b9b95e0dSmickey mfctl(CR_EIRR, eirr); 598a24c0b7aSmickey eirr &= frame->tf_eiem; 599b9b95e0dSmickey bit = ffs(eirr) - 1; 600556d2ba7Smickey if (bit >= 0) { 601556d2ba7Smickey mtctl(1 << bit, CR_EIRR); 602b9b95e0dSmickey eirr &= ~(1 << bit); 603b9b95e0dSmickey /* ((struct iomod *)cpu_gethpa(0))->io_eir = 0; */ 604556d2ba7Smickey #ifdef INTRDEBUG 605a24c0b7aSmickey if (bit != 31) 606137d3021Smickey db_printf ("cpu_intr: 0x%08x\n", (1 << bit)); 607556d2ba7Smickey #endif 6083a81311eSmickey iv = &cpu_intr_vectors[bit]; 6093a81311eSmickey if (iv->handler) { 610688a8060Smickey register int s, r; 6113a81311eSmickey 6123a81311eSmickey iv->evcnt.ev_count++; 613688a8060Smickey s = splx(iv->pri); 6147cd4d71fSmickey /* no arg means pass the frame */ 615688a8060Smickey r = (iv->handler)(iv->arg? iv->arg:frame); 616688a8060Smickey splx(s); 6177cd4d71fSmickey #ifdef DEBUG 618688a8060Smickey if (!r) 619137d3021Smickey db_printf ("%s: can't handle interrupt\n", 620688a8060Smickey iv->evcnt.ev_name); 621b9b95e0dSmickey #endif 6227cd4d71fSmickey } else 623137d3021Smickey db_printf ("cpu_intr: stray interrupt %d\n", bit); 624b9b95e0dSmickey } 625b9b95e0dSmickey } while (eirr); 626556d2ba7Smickey } 627