1/* $NetBSD: intvec.S,v 1.3 2002/05/13 21:11:23 matt Exp $ */ 2 3/* 4 * Copyright (c) 1994, 1997 Ludd, University of Lule}, Sweden. 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 at Ludd, University of Lule}. 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 34#include "assym.h" 35#include <sys/cdefs.h> 36#include <net/netisr.h> 37 38#define __HAVE_GENERIC_SOFT_INTERRUPTS /* XXX - cannot include types.h! */ 39 40#include "opt_ddb.h" 41#include "opt_cputype.h" 42#include "opt_emulate.h" 43#include "opt_multiprocessor.h" 44#include "opt_lockdebug.h" 45#include "leds.h" 46 47#define SCBENTRY(name) \ 48 .text ; \ 49 .align 2 ; \ 50 .globl __CONCAT(X,name) ; \ 51__CONCAT(X,name): 52 53#define TRAPCALL(namn, typ) \ 54SCBENTRY(namn) ; \ 55 pushl $0 ; \ 56 pushl $typ ; \ 57 jbr Xtrap 58 59#define TRAPARGC(namn, typ) \ 60SCBENTRY(namn) ; \ 61 pushl $typ ; \ 62 jbr Xtrap 63 64#define FASTINTR(namn, rutin) \ 65SCBENTRY(namn) ; \ 66 pushr $0x3f ; \ 67 calls $0,_C_LABEL(rutin) ; \ 68 popr $0x3f ; \ 69 rei 70 71#define PUSHR pushr $0x3f 72#define POPR popr $0x3f 73 74#define KSTACK 0 75#define ISTACK 1 76#define NOVEC .long 0 77#define INTVEC(label,stack) \ 78 .long __CONCAT(X,label)+stack; 79 80 .text 81 82 .globl _C_LABEL(kernbase), _C_LABEL(rpb), _C_LABEL(kernel_text) 83 .set _C_LABEL(kernel_text),KERNBASE 84_C_LABEL(kernbase): 85_C_LABEL(rpb): 86/* 87 * First page in memory we have rpb; so that we know where 88 * (must be on a 64k page boundary, easiest here). We use it 89 * to store SCB vectors generated when compiling the kernel, 90 * and move the SCB later to somewhere else. 91 */ 92 93 NOVEC; # Unused, 0 94 INTVEC(mcheck, ISTACK) # Machine Check., 4 95 INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8 96 NOVEC; # Power Failed., C 97 INTVEC(privinflt, KSTACK) # Privileged/Reserved Instruction. 98 INTVEC(xfcflt, KSTACK) # Customer Reserved Instruction, 14 99 INTVEC(resopflt, KSTACK) # Reserved Operand/Boot Vector(?), 18 100 INTVEC(resadflt, KSTACK) # Reserved Address Mode., 1C 101 INTVEC(access_v, KSTACK) # Access Control Violation, 20 102 INTVEC(transl_v, KSTACK) # Translation Invalid, 24 103 INTVEC(tracep, KSTACK) # Trace Pending, 28 104 INTVEC(breakp, KSTACK) # Breakpoint Instruction, 2C 105 NOVEC; # Compatibility Exception, 30 106 INTVEC(arithflt, KSTACK) # Arithmetic Fault, 34 107 NOVEC; # Unused, 38 108 NOVEC; # Unused, 3C 109 INTVEC(syscall, KSTACK) # main syscall trap, chmk, 40 110 INTVEC(resopflt, KSTACK) # chme, 44 111 INTVEC(resopflt, KSTACK) # chms, 48 112 INTVEC(resopflt, KSTACK) # chmu, 4C 113 NOVEC; # System Backplane Exception/BIerror, 50 114 INTVEC(cmrerr, ISTACK) # Corrected Memory Read, 54 115 NOVEC; # System Backplane Alert/RXCD, 58 116 INTVEC(sbiflt, ISTACK) # System Backplane Fault, 5C 117 NOVEC; # Memory Write Timeout, 60 118 NOVEC; # Unused, 64 119 NOVEC; # Unused, 68 120 NOVEC; # Unused, 6C 121 NOVEC; # Unused, 70 122 NOVEC; # Unused, 74 123 NOVEC; # Unused, 78 124 NOVEC; # Unused, 7C 125 NOVEC; # Unused, 80 126 NOVEC; # Unused, 84 127 INTVEC(astintr, KSTACK) # Asynchronous Sustem Trap, AST (IPL 02) 128 NOVEC; # Unused, 8C 129 NOVEC; # Unused, 90 130 NOVEC; # Unused, 94 131 NOVEC; # Unused, 98 132 NOVEC; # Unused, 9C 133 INTVEC(softclock,ISTACK) # Software clock interrupt (IPL 08) 134 NOVEC; # Unused, A4 (IPL 09) 135 NOVEC; # Unused, A8 (IPL 10) 136 NOVEC; # Unused, AC (IPL 11) 137 INTVEC(softnet, ISTACK) # Software network interrupt (IPL 12) 138 INTVEC(softserial, ISTACK) # Software serial interrupt (IPL 13) 139 NOVEC; # Unused, B8 (IPL 14) 140 INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC (IPL 15) 141 INTVEC(hardclock,ISTACK) # Interval Timer 142 NOVEC; # Unused, C4 143 INTVEC(emulate, KSTACK) # Subset instruction emulation, C8 144 NOVEC; # Unused, CC 145 NOVEC; # Unused, D0 146 NOVEC; # Unused, D4 147 NOVEC; # Unused, D8 148 NOVEC; # Unused, DC 149 NOVEC; # Unused, E0 150 NOVEC; # Unused, E4 151 NOVEC; # Unused, E8 152 NOVEC; # Unused, EC 153 NOVEC; 154 NOVEC; 155 NOVEC; 156 NOVEC; 157 158 /* space for adapter vectors */ 159 .space 0x100 160 161 .align 2 162# 163# mcheck is the badaddress trap, also called when referencing 164# a invalid address (busserror) 165# _memtest (memtest in C) holds the address to continue execution 166# at when returning from a intentional test. 167# 168SCBENTRY(mcheck) 169 tstl _C_LABEL(cold) # Ar we still in coldstart? 170 bneq L4 # Yes. 171 172 pushr $0x7f 173 pushab 24(%sp) 174 movl _C_LABEL(dep_call),%r6 # CPU dependent mchk handling 175 calls $1,*MCHK(%r6) 176 tstl %r0 # If not machine check, try memory error 177 beql 1f 178 calls $0,*MEMERR(%r6) 179 pushab 2f 180 calls $1,_C_LABEL(panic) 1812: .asciz "mchk" 1821: popr $0x7f 183 addl2 (%sp)+,%sp 184 185 rei 186 187L4: addl2 (%sp)+,%sp # remove info pushed on stack 188 pushr $0x3f # save regs for clobbering 189 movl _C_LABEL(dep_call),%r0 # get cpu-specific mchk handler 190 tstl BADADDR(%r0) # any handler available? 191 bneq 4f # yep, call it 192 popr $0x3f # nope, restore regs 193 brb 0f # continue 1944: calls $0,*BADADDR(%r0) # call machine-specific handler 195 popr $0x3f # restore regs 196 brb 2f 197 1980: cmpl _C_LABEL(vax_cputype),$1 # Is it a 11/780? 199 bneq 1f # No... 200 201 mtpr $0, $PR_SBIFS # Clear SBI fault register 202 brb 2f 203 2041: cmpl _C_LABEL(vax_cputype),$4 # Is it a 8600? 205 bneq 3f 206 207 mtpr $0, $PR_EHSR # Clear Error status register 208 brb 2f 209 2103: mtpr $0xF,$PR_MCESR # clear the bus error bit 2112: movl _C_LABEL(memtest),(%sp) # REI to new adress 212 rei 213 214 TRAPCALL(invkstk, T_KSPNOTVAL) 215 216SCBENTRY(privinflt) # Privileged/unimplemented instruction 217#ifndef NO_INSN_EMULATE 218 jsb _C_LABEL(unimemu) # do not return if insn emulated 219#endif 220 pushl $0 221 pushl $T_PRIVINFLT 222 jbr Xtrap 223 224 TRAPCALL(xfcflt, T_XFCFLT); 225 TRAPCALL(resopflt, T_RESOPFLT) 226 TRAPCALL(resadflt, T_RESADFLT) 227 228/* 229 * Translation fault, used only when simulating page reference bit. 230 * Therefore it is done a fast revalidation of the page if it is 231 * referenced. Trouble here is the hardware bug on KA650 CPUs that 232 * put in a need for an extra check when the fault is gotten during 233 * PTE reference. Handled in pmap.c. 234 */ 235SCBENTRY(transl_v) # 20: Translation violation 236 pushr $0x3f 237 pushl 28(%sp) 238 pushl 28(%sp) 239 calls $2,_C_LABEL(pmap_simulref) 240 tstl %r0 241 bneq 1f 242 popr $0x3f 243 addl2 $8,%sp 244 rei 2451: popr $0x3f 246 brb Xaccess_v 247 248SCBENTRY(access_v) # 24: Access cntrl viol fault 249 blbs (%sp), ptelen 250 pushl $T_ACCFLT 251 bbc $1,4(%sp),1f 252 bisl2 $T_PTEFETCH,(%sp) 2531: bbc $2,4(%sp),2f 254 bisl2 $T_WRITE,(%sp) 2552: movl (%sp), 4(%sp) 256 addl2 $4, %sp 257 jbr Xtrap 258 259ptelen: movl $T_PTELEN, (%sp) # PTE must expand (or send segv) 260 jbr Xtrap; 261 262TRAPCALL(tracep, T_TRCTRAP) 263TRAPCALL(breakp, T_BPTFLT) 264 265TRAPARGC(arithflt, T_ARITHFLT) 266 267SCBENTRY(syscall) # Main system call 268 pushl $T_SYSCALL 269 pushr $0xfff 270 mfpr $PR_USP, -(%sp) 271 pushl %ap 272 pushl %fp 273 pushl %sp # pointer to syscall frame; defined in trap.h 274 calls $1, _C_LABEL(syscall) 275 movl (%sp)+, %fp 276 movl (%sp)+, %ap 277 mtpr (%sp)+, $PR_USP 278 popr $0xfff 279 addl2 $8, %sp 280 mtpr $IPL_HIGH, $PR_IPL # Be sure we can REI 281 rei 282 283 284SCBENTRY(cmrerr) 285 PUSHR 286 movl _C_LABEL(dep_call),%r0 287 calls $0,*MEMERR(%r0) 288 POPR 289 rei 290 291SCBENTRY(sbiflt); 292 pushab sbifltmsg 293 calls $1, _C_LABEL(panic) 294 295TRAPCALL(astintr, T_ASTFLT) 296 297SCBENTRY(softclock) 298 PUSHR 299 movab _C_LABEL(softclock_head),%r0 300 jsb softintr_dispatch 301 incl _C_LABEL(softclock_intrcnt)+EV_COUNT 302 adwc $0,_C_LABEL(softclock_intrcnt)+EV_COUNT+4 303 POPR 304 rei 305 306SCBENTRY(softnet) 307 PUSHR 308 309# tstl _C_LABEL(netisr) # any netisr's set 310# beql 2f # no, skip looking at them one by one 311#define DONETISR(bit, fn) \ 312 bbcci $bit,_C_LABEL(netisr),1f; \ 313 calls $0,_C_LABEL(fn); \ 314 1: 315 316#include <net/netisr_dispatch.h> 317 318#undef DONETISR 319 3202: movab _C_LABEL(softnet_head),%r0 321 jsb softintr_dispatch 322 incl _C_LABEL(softnet_intrcnt)+EV_COUNT 323 adwc $0,_C_LABEL(softnet_intrcnt)+EV_COUNT+4 324 POPR 325 rei 326 327SCBENTRY(softserial) 328 PUSHR 329 movab _C_LABEL(softserial_head),%r0 330 jsb softintr_dispatch 331 incl _C_LABEL(softserial_intrcnt)+EV_COUNT 332 adwc $0,_C_LABEL(softserial_intrcnt)+EV_COUNT+4 333 POPR 334 rei 335 336 .align 2 337softintr_dispatch: 338#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 339 pushl %r0 340 calls $0,_C_LABEL(krnlock) 341 movl (%sp)+,%r0 342#endif 343 movl SHD_INTRS(%r0), %r0 # anything to do? (get first handler) 344 beql 3f # nope return 345 pushl %r7 # we need to use %r7 so save it 346 movl %r0, %r7 # move first item to %r7 3471: tstl SH_PENDING(%r7) # need call this one? 348 bneq 2f # nope, go to next one 349 clrl SH_PENDING(%r7) # clear pending flag 350 pushl SH_ARG(%r7) # push function argument 351 calls $1, *SH_FUNC(%r7) # call function 3522: movl SH_NEXT(%r7), %r7 # get next handler 353 bneq 1b # if not null, process it 354 movl (%sp)+, %r7 # done, restore %r7 3553: 356#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 357 calls $0,_C_LABEL(krnunlock) 358#endif 359 rsb # return to caller 360 361TRAPCALL(ddbtrap, T_KDBTRAP) 362 363SCBENTRY(hardclock) 364 mtpr $0xc1,$PR_ICCS # Reset interrupt flag 365#ifdef DDB 366 tstl 0x80000100 # rpb wait element 367 beql 1f # set, jmp to debugger 368 pushl $0 369 pushl $T_KDBTRAP 370 jbr Xtrap 371#endif 3721: pushr $0x3f 373 incl _C_LABEL(clock_intrcnt)+EV_COUNT # count the number of clock interrupts 374 adwc $0,_C_LABEL(clock_intrcnt)+EV_COUNT+4 375#if VAX46 || VAXANY 376 cmpl _C_LABEL(vax_boardtype),$VAX_BTYP_46 377 bneq 1f 378 movl _C_LABEL(ka46_cpu),%r0 379 clrl VC_DIAGTIMM(%r0) 380#endif 3811: pushl %sp 382 addl2 $24,(%sp) 383 calls $1,_C_LABEL(hardclock) 384#if NLEDS 385 calls $0,_C_LABEL(leds_intr) 386#endif 387 popr $0x3f 388 rei 389 390/* 391 * Main routine for traps; all go through this. 392 * Note that we put USP on the frame here, which sometimes should 393 * be KSP to be correct, but because we only alters it when we are 394 * called from user space it doesn't care. 395 * _sret is used in cpu_set_kpc to jump out to user space first time. 396 */ 397 .globl _C_LABEL(sret) 398Xtrap: pushr $0xfff 399 mfpr $PR_USP, -(%sp) 400 pushl %ap 401 pushl %fp 402 pushl %sp 403 calls $1, _C_LABEL(trap) 404_C_LABEL(sret): 405 movl (%sp)+, %fp 406 movl (%sp)+, %ap 407 mtpr (%sp)+, $PR_USP 408 popr $0xfff 409 addl2 $8, %sp 410 mtpr $IPL_HIGH, $PR_IPL # Be sure we can REI 411 rei 412 413sbifltmsg: 414 .asciz "SBI fault" 415 416#ifndef NO_INSN_EMULATE 417/* 418 * Table of emulated Microvax instructions supported by emulate.s. 419 * Use noemulate to convert unimplemented ones to reserved instruction faults. 420 */ 421 .globl _C_LABEL(emtable) 422_C_LABEL(emtable): 423/* f8 */ .long _C_LABEL(EMashp); .long _C_LABEL(EMcvtlp) 424/* fa */ .long noemulate; .long noemulate 425/* fc */ .long noemulate; .long noemulate 426/* fe */ .long noemulate; .long noemulate 427/* 00 */ .long noemulate; .long noemulate 428/* 02 */ .long noemulate; .long noemulate 429/* 04 */ .long noemulate; .long noemulate 430/* 05 */ .long noemulate; .long noemulate 431/* 08 */ .long _C_LABEL(EMcvtps); .long _C_LABEL(EMcvtsp) 432/* 0a */ .long noemulate; .long _C_LABEL(EMcrc) 433/* 0c */ .long noemulate; .long noemulate 434/* 0e */ .long noemulate; .long noemulate 435/* 10 */ .long noemulate; .long noemulate 436/* 12 */ .long noemulate; .long noemulate 437/* 14 */ .long noemulate; .long noemulate 438/* 16 */ .long noemulate; .long noemulate 439/* 18 */ .long noemulate; .long noemulate 440/* 1a */ .long noemulate; .long noemulate 441/* 1c */ .long noemulate; .long noemulate 442/* 1e */ .long noemulate; .long noemulate 443/* 20 */ .long _C_LABEL(EMaddp4); .long _C_LABEL(EMaddp6) 444/* 22 */ .long _C_LABEL(EMsubp4); .long _C_LABEL(EMsubp6) 445/* 24 */ .long _C_LABEL(EMcvtpt); .long _C_LABEL(EMmulp) 446/* 26 */ .long _C_LABEL(EMcvttp); .long _C_LABEL(EMdivp) 447/* 28 */ .long noemulate; .long _C_LABEL(EMcmpc3) 448/* 2a */ .long _C_LABEL(EMscanc); .long _C_LABEL(EMspanc) 449/* 2c */ .long noemulate; .long _C_LABEL(EMcmpc5) 450/* 2e */ .long _C_LABEL(EMmovtc); .long _C_LABEL(EMmovtuc) 451/* 30 */ .long noemulate; .long noemulate 452/* 32 */ .long noemulate; .long noemulate 453/* 34 */ .long _C_LABEL(EMmovp); .long _C_LABEL(EMcmpp3) 454/* 36 */ .long _C_LABEL(EMcvtpl); .long _C_LABEL(EMcmpp4) 455/* 38 */ .long _C_LABEL(EMeditpc); .long _C_LABEL(EMmatchc) 456/* 3a */ .long _C_LABEL(EMlocc); .long _C_LABEL(EMskpc) 457#endif 458/* 459 * The following is called with the stack set up as follows: 460 * 461 * (%sp): Opcode 462 * 4(%sp): Instruction PC 463 * 8(%sp): Operand 1 464 * 12(%sp): Operand 2 465 * 16(%sp): Operand 3 466 * 20(%sp): Operand 4 467 * 24(%sp): Operand 5 468 * 28(%sp): Operand 6 469 * 32(%sp): Operand 7 (unused) 470 * 36(%sp): Operand 8 (unused) 471 * 40(%sp): Return PC 472 * 44(%sp): Return PSL 473 * 48(%sp): TOS before instruction 474 * 475 * Each individual routine is called with the stack set up as follows: 476 * 477 * (%sp): Return address of trap handler 478 * 4(%sp): Opcode (will get return PSL) 479 * 8(%sp): Instruction PC 480 * 12(%sp): Operand 1 481 * 16(%sp): Operand 2 482 * 20(%sp): Operand 3 483 * 24(%sp): Operand 4 484 * 28(%sp): Operand 5 485 * 32(%sp): Operand 6 486 * 36(%sp): saved register 11 487 * 40(%sp): saved register 10 488 * 44(%sp): Return PC 489 * 48(%sp): Return PSL 490 * 52(%sp): TOS before instruction 491 * See the VAX Architecture Reference Manual, Section B-5 for more 492 * information. 493 */ 494 495SCBENTRY(emulate) 496#ifndef NO_INSN_EMULATE 497 movl %r11,32(%sp) # save register %r11 in unused operand 498 movl %r10,36(%sp) # save register %r10 in unused operand 499 cvtbl (%sp),%r10 # get opcode 500 addl2 $8,%r10 # shift negative opcodes 501 subl3 %r10,$0x43,%r11 # forget it if opcode is out of range 502 bcs noemulate 503 movl _C_LABEL(emtable)[%r10],%r10 504 # call appropriate emulation routine 505 jsb (%r10) # routines put return values into regs 0-5 506 movl 32(%sp),%r11 # restore register %r11 507 movl 36(%sp),%r10 # restore register %r10 508 insv (%sp),$0,$4,44(%sp) # and condition codes in Opcode spot 509 addl2 $40,%sp # adjust stack for return 510 rei 511noemulate: 512 addl2 $48,%sp # adjust stack for 513#endif 514 .word 0xffff # "reserved instruction fault" 515 516 .globl _C_LABEL(intrnames), _C_LABEL(eintrnames) 517_C_LABEL(intrnames): 518 .long 0 519_C_LABEL(eintrnames): 520 521 .globl _C_LABEL(intrcnt), _C_LABEL(eintrcnt) 522_C_LABEL(intrcnt): 523 .long 0 524_C_LABEL(eintrcnt): 525