/* $NetBSD: intvec.S,v 1.23 2022/09/02 23:48:10 thorpej Exp $ */ /* * Copyright (c) 1994, 1997 Ludd, University of Lule}, Sweden. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "assym.h" #include #include "opt_ddb.h" #include "opt_cputype.h" #include "opt_emulate.h" #include "opt_multiprocessor.h" #include "opt_lockdebug.h" #include "leds.h" #define SCBENTRY(name) \ .text ; \ .align 2 ; \ .globl __CONCAT(X,name) ; \ __CONCAT(X,name): #define TRAPCALL(namn, typ) \ SCBENTRY(namn) ; \ pushl $0 ; \ pushl $typ ; \ jbr Xtrap #define TRAPARGC(namn, typ) \ SCBENTRY(namn) ; \ pushl $typ ; \ jbr Xtrap #define FASTINTR(namn, rutin) \ SCBENTRY(namn) ; \ pushr $0x3f ; \ calls $0,_C_LABEL(rutin) ; \ popr $0x3f ; \ rei #define PUSHR pushr $0x3f #define POPR popr $0x3f #define KSTACK 0 #define ISTACK 1 #define NOVEC .long 0 #define INTVEC(label,stack) \ .long __CONCAT(X,label)+stack; .text .globl _C_LABEL(kernbase), _C_LABEL(rpb), _C_LABEL(kernel_text) .set _C_LABEL(kernel_text),KERNBASE _C_LABEL(kernbase): _C_LABEL(rpb): /* * First page in memory we have rpb; so that we know where * (must be on a 64k page boundary, easiest here). We use it * to store SCB vectors generated when compiling the kernel, * and move the SCB later to somewhere else. */ NOVEC; # Unused, 0 INTVEC(mcheck, ISTACK) # Machine Check., 4 INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8 NOVEC; # Power Failed., C INTVEC(privinflt, KSTACK) # Privileged/Reserved Instruction. INTVEC(xfcflt, KSTACK) # Customer Reserved Instruction, 14 INTVEC(resopflt, KSTACK) # Reserved Operand/Boot Vector(?), 18 INTVEC(resadflt, KSTACK) # Reserved Address Mode., 1C INTVEC(access_v, KSTACK) # Access Control Violation, 20 INTVEC(transl_v, KSTACK) # Translation Invalid, 24 INTVEC(tracep, KSTACK) # Trace Pending, 28 INTVEC(breakp, KSTACK) # Breakpoint Instruction, 2C NOVEC; # Compatibility Exception, 30 INTVEC(arithflt, KSTACK) # Arithmetic Fault, 34 NOVEC; # Unused, 38 NOVEC; # Unused, 3C INTVEC(syscall, KSTACK) # main syscall trap, chmk, 40 INTVEC(chmx, KSTACK) # chme, 44 INTVEC(chmx, KSTACK) # chms, 48 INTVEC(chmx, KSTACK) # chmu, 4C NOVEC; # System Backplane Exception/BIerror, 50 INTVEC(cmrerr, ISTACK) # Corrected Memory Read, 54 NOVEC; # System Backplane Alert/RXCD, 58 INTVEC(sbiflt, ISTACK) # System Backplane Fault, 5C NOVEC; # Memory Write Timeout, 60 NOVEC; # Unused, 64 NOVEC; # Unused, 68 NOVEC; # Unused, 6C NOVEC; # Unused, 70 NOVEC; # Unused, 74 NOVEC; # Unused, 78 NOVEC; # Unused, 7C NOVEC; # Unused, 80 NOVEC; # Unused, 84 INTVEC(astintr, KSTACK) # Asynchronous Sustem Trap, AST (IPL 02) NOVEC; # Unused, 8C NOVEC; # Unused, 90 NOVEC; # Unused, 94 NOVEC; # Unused, 98 NOVEC; # Unused, 9C INTVEC(softclock, KSTACK); # Software clock interrupt, A0 (IPL 08) NOVEC; # Unused, A4 (IPL 09) NOVEC; # Unused, A8 (IPL 10) INTVEC(softbio, KSTACK); # Software bio interrupt, AC (IPL 11) INTVEC(softnet, KSTACK); # Software net interrupt, B0 (IPL 12) INTVEC(softserial, KSTACK); # Software serial interrupt, B4 (IPL 13) NOVEC; # Unused, B8 (IPL 14) INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC (IPL 15) INTVEC(hardclock,ISTACK) # Interval Timer NOVEC; # Unused, C4 INTVEC(emulate, KSTACK) # Subset instruction emulation, C8 NOVEC; # Unused, CC NOVEC; # Unused, D0 NOVEC; # Unused, D4 NOVEC; # Unused, D8 NOVEC; # Unused, DC NOVEC; # Unused, E0 NOVEC; # Unused, E4 NOVEC; # Unused, E8 NOVEC; # Unused, EC NOVEC; NOVEC; NOVEC; NOVEC; /* space for adapter vectors */ .space 0x100 .align 2 # # mcheck is the badaddress trap, also called when referencing # a invalid address (busserror) # _memtest (memtest in C) holds the address to continue execution # at when returning from a intentional test. # SCBENTRY(mcheck) tstl _C_LABEL(cold) # Ar we still in coldstart? bneq L4 # Yes. pushr $0x7f pushab 24(%sp) movl _C_LABEL(dep_call),%r6 # CPU dependent mchk handling calls $1,*MCHK(%r6) tstl %r0 # If not machine check, try memory error beql 1f calls $0,*MEMERR(%r6) pushab 2f calls $1,_C_LABEL(panic) 2: .asciz "mchk" 1: popr $0x7f addl2 (%sp)+,%sp rei L4: addl2 (%sp)+,%sp # remove info pushed on stack pushr $0x3f # save regs for clobbering movl _C_LABEL(dep_call),%r0 # get CPU-specific mchk handler tstl BADADDR(%r0) # any handler available? bneq 4f # yep, call it popr $0x3f # nope, restore regs brb 0f # continue 4: calls $0,*BADADDR(%r0) # call machine-specific handler popr $0x3f # restore regs brb 2f 0: cmpl _C_LABEL(vax_cputype),$1 # Is it a 11/780? bneq 1f # No... mtpr $0, $PR_SBIFS # Clear SBI fault register brb 2f 1: cmpl _C_LABEL(vax_cputype),$4 # Is it a 8600? bneq 3f mtpr $0, $PR_EHSR # Clear Error status register brb 2f 3: mtpr $0xF,$PR_MCESR # clear the bus error bit 2: movl _C_LABEL(memtest),(%sp) # REI to new address rei TRAPCALL(invkstk, T_KSPNOTVAL) SCBENTRY(privinflt) # Privileged/unimplemented instruction #ifndef NO_INSN_EMULATE jsb _C_LABEL(unimemu) # do not return if insn emulated #endif pushl $0 pushl $T_PRIVINFLT jbr Xtrap TRAPCALL(xfcflt, T_XFCFLT); TRAPCALL(resopflt, T_RESOPFLT) TRAPCALL(resadflt, T_RESADFLT) /* * default handler for CHME and CHMS */ SCBENTRY(chmx) clrl (%sp) # CHM code already on stack pushl $T_RESOPFLT jbr Xtrap /* * Translation fault, used only when simulating page reference bit. * Therefore it is done a fast revalidation of the page if it is * referenced. Trouble here is the hardware bug on KA650 CPUs that * put in a need for an extra check when the fault is gotten during * PTE reference. Handled in pmap.c. */ SCBENTRY(transl_v) # 20: Translation violation pushr $0x3f pushl 28(%sp) pushl 28(%sp) calls $2,_C_LABEL(pmap_simulref) tstl %r0 bneq 1f popr $0x3f addl2 $8,%sp rei 1: popr $0x3f brw Xaccess_v SCBENTRY(access_v) # 24: Access cntrl viol fault blbs (%sp), ptelen pushl $T_ACCFLT bbc $1,4(%sp),1f bisl2 $T_PTEFETCH,(%sp) 1: bbc $2,4(%sp),2f bisl2 $T_WRITE,(%sp) 2: movl (%sp), 4(%sp) addl2 $4, %sp jbr Xtrap ptelen: movl $T_PTELEN, (%sp) # PTE must expand (or send segv) jbr Xtrap; TRAPCALL(tracep, T_TRCTRAP) TRAPCALL(breakp, T_BPTFLT) TRAPARGC(arithflt, T_ARITHFLT) SCBENTRY(syscall) # Main system call #if 1 cmpl (%sp), $SYS__lwp_getprivate bneq 1f mfpr $PR_SSP, %r0 # get curlwp movl L_PRIVATE(%r0), %r0 # get l_private addl2 $4, %sp # eat the code rei 1: #endif pushl $T_SYSCALL pushr $0xfff mfpr $PR_USP, -(%sp) mfpr $PR_SSP, %r0 /* SSP contains curlwp */ movl L_PROC(%r0), %r0 pushl %ap pushl %fp pushl %sp # pointer to syscall frame; defined in trap.h calls $1, *P_MD_SYSCALL(%r0) movl (%sp)+, %fp movl (%sp)+, %ap mtpr (%sp)+, $PR_USP popr $0xfff addl2 $8, %sp mtpr $IPL_HIGH, $PR_IPL # Be sure we can REI rei SCBENTRY(cmrerr) PUSHR movl _C_LABEL(dep_call),%r0 calls $0,*MEMERR(%r0) POPR rei SCBENTRY(sbiflt); pushab sbifltmsg calls $1, _C_LABEL(panic) TRAPCALL(astintr, T_ASTFLT) TRAPCALL(ddbtrap, T_KDBTRAP) SCBENTRY(hardclock) #ifdef DDB tstl 0x80000100 # rpb wait element beql 1f # set, jmp to debugger pushl $0 pushl $T_KDBTRAP jbr Xtrap #endif 1: pushr $0x3f mfpr $PR_ICCS,%r0 tstl %r0 bgeq 2f incl _C_LABEL(clock_misscnt)+EV_COUNT adwc $0,_C_LABEL(clock_misscnt)+EV_COUNT+4 2: mtpr $0x800000c1,$PR_ICCS # Reset interrupt flag incl _C_LABEL(clock_intrcnt)+EV_COUNT # count the number of clock interrupts adwc $0,_C_LABEL(clock_intrcnt)+EV_COUNT+4 mfpr $PR_SSP, %r0 /* SSP contains curlwp */ movl L_CPU(%r0), %r0 /* get current CPU */ incl CI_NINTR(%r0) adwc $0,(CI_NINTR+4)(%r0) #if VAX46 || VAXANY cmpl _C_LABEL(vax_boardtype),$VAX_BTYP_46 bneq 1f movl _C_LABEL(ka46_cpu),%r0 clrl VC_DIAGTIMM(%r0) #endif 1: pushl %sp addl2 $24,(%sp) calls $1,_C_LABEL(hardclock) #if NLEDS calls $0,_C_LABEL(leds_intr) #endif popr $0x3f rei /* * Main routine for traps; all go through this. * Note that we put USP on the frame here, which sometimes should * be KSP to be correct, but because we only alters it when we are * called from user space it doesn't care. * _sret is used in cpu_set_kpc to jump out to user space first time. */ .globl _C_LABEL(sret) Xtrap: pushr $0xfff mfpr $PR_USP, -(%sp) pushl %ap pushl %fp pushl %sp calls $1, _C_LABEL(trap) _C_LABEL(sret): movl (%sp)+, %fp movl (%sp)+, %ap mtpr (%sp)+, $PR_USP popr $0xfff addl2 $8, %sp mtpr $IPL_HIGH, $PR_IPL # Be sure we can REI rei sbifltmsg: .asciz "SBI fault" #ifndef NO_INSN_EMULATE /* * Table of emulated Microvax instructions supported by emulate.s. * Use noemulate to convert unimplemented ones to reserved instruction faults. */ .globl _C_LABEL(emtable) _C_LABEL(emtable): /* f8 */ .long _C_LABEL(EMashp); .long _C_LABEL(EMcvtlp) /* fa */ .long noemulate; .long noemulate /* fc */ .long noemulate; .long noemulate /* fe */ .long noemulate; .long noemulate /* 00 */ .long noemulate; .long noemulate /* 02 */ .long noemulate; .long noemulate /* 04 */ .long noemulate; .long noemulate /* 05 */ .long noemulate; .long noemulate /* 08 */ .long _C_LABEL(EMcvtps); .long _C_LABEL(EMcvtsp) /* 0a */ .long noemulate; .long _C_LABEL(EMcrc) /* 0c */ .long noemulate; .long noemulate /* 0e */ .long noemulate; .long noemulate /* 10 */ .long noemulate; .long noemulate /* 12 */ .long noemulate; .long noemulate /* 14 */ .long noemulate; .long noemulate /* 16 */ .long noemulate; .long noemulate /* 18 */ .long noemulate; .long noemulate /* 1a */ .long noemulate; .long noemulate /* 1c */ .long noemulate; .long noemulate /* 1e */ .long noemulate; .long noemulate /* 20 */ .long _C_LABEL(EMaddp4); .long _C_LABEL(EMaddp6) /* 22 */ .long _C_LABEL(EMsubp4); .long _C_LABEL(EMsubp6) /* 24 */ .long _C_LABEL(EMcvtpt); .long _C_LABEL(EMmulp) /* 26 */ .long _C_LABEL(EMcvttp); .long _C_LABEL(EMdivp) /* 28 */ .long noemulate; .long _C_LABEL(EMcmpc3) /* 2a */ .long _C_LABEL(EMscanc); .long _C_LABEL(EMspanc) /* 2c */ .long noemulate; .long _C_LABEL(EMcmpc5) /* 2e */ .long _C_LABEL(EMmovtc); .long _C_LABEL(EMmovtuc) /* 30 */ .long noemulate; .long noemulate /* 32 */ .long noemulate; .long noemulate /* 34 */ .long _C_LABEL(EMmovp); .long _C_LABEL(EMcmpp3) /* 36 */ .long _C_LABEL(EMcvtpl); .long _C_LABEL(EMcmpp4) /* 38 */ .long _C_LABEL(EMeditpc); .long _C_LABEL(EMmatchc) /* 3a */ .long _C_LABEL(EMlocc); .long _C_LABEL(EMskpc) #endif /* * The following is called with the stack set up as follows: * * (%sp): Opcode * 4(%sp): Instruction PC * 8(%sp): Operand 1 * 12(%sp): Operand 2 * 16(%sp): Operand 3 * 20(%sp): Operand 4 * 24(%sp): Operand 5 * 28(%sp): Operand 6 * 32(%sp): Operand 7 (unused) * 36(%sp): Operand 8 (unused) * 40(%sp): Return PC * 44(%sp): Return PSL * 48(%sp): TOS before instruction * * Each individual routine is called with the stack set up as follows: * * (%sp): Return address of trap handler * 4(%sp): Opcode (will get return PSL) * 8(%sp): Instruction PC * 12(%sp): Operand 1 * 16(%sp): Operand 2 * 20(%sp): Operand 3 * 24(%sp): Operand 4 * 28(%sp): Operand 5 * 32(%sp): Operand 6 * 36(%sp): saved register 11 * 40(%sp): saved register 10 * 44(%sp): Return PC * 48(%sp): Return PSL * 52(%sp): TOS before instruction * See the VAX Architecture Reference Manual, Section B-5 for more * information. */ SCBENTRY(emulate) #ifndef NO_INSN_EMULATE movl %r11,32(%sp) # save register %r11 in unused operand movl %r10,36(%sp) # save register %r10 in unused operand cvtbl (%sp),%r10 # get opcode addl2 $8,%r10 # shift negative opcodes subl3 %r10,$0x43,%r11 # forget it if opcode is out of range bcs noemulate movl _C_LABEL(emtable)[%r10],%r10 # call appropriate emulation routine jsb (%r10) # routines put return values into regs 0-5 movl 32(%sp),%r11 # restore register %r11 movl 36(%sp),%r10 # restore register %r10 insv (%sp),$0,$4,44(%sp) # and condition codes in Opcode spot addl2 $40,%sp # adjust stack for return rei noemulate: addl2 $48,%sp # adjust stack for #endif .word 0xffff # "reserved instruction fault"