1/* $OpenBSD: eh_common.S,v 1.66 2024/06/05 19:22:04 miod Exp $ */ 2/* 3 * Mach Operating System 4 * Copyright (c) 1993-1991 Carnegie Mellon University 5 * Copyright (c) 1991 OMRON Corporation 6 * Copyright (c) 1996 Nivas Madhur 7 * Copyright (c) 1998 Steve Murphree, Jr. 8 * All Rights Reserved. 9 * 10 * Permission to use, copy, modify and distribute this software and its 11 * documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31/* 32 * NOTICE: This is not a standalone file. To use it, define the PFSR_SAVE 33 * macro (if supporting 88100 processors) and #include this file in your 34 * port's eh.S: 35 * #include <m88k/m88k/eh_common.S> 36 */ 37 38/* 39 * In the following discussion, references are made to: 40 * MC88100 - RISC MICROPROCESSOR USER'S MANUAL 41 * (second edition). Reference in []s refer to section numbers. 42 * 43 * This discussion assumes that you are at least vaguely familiar with 88100 44 * exception handling (chapter 6), the BSD kernel, and that you have a brain 45 * (and use it while reading this). 46 * 47 * I also assume (and hope) that you're not offended by frequent misspellings. 48 * 49 * Jeffrey Friedl 50 * jfriedl@rna.ncl.omron.co.jp 51 * December, 1989 52 * ------------------------------------------------------------------- 53 * 54 * EXCEPTIONS, INTERRUPTS, and TRAPS 55 * --------------------------------- 56 * This is the machine exception handler. 57 * In the MC88100, various "conditions" cause an exception, where 58 * processing momentarily jumps here to "service" the exception, 59 * and then continues where it left off. 60 * 61 * There are a number of different types of exceptions. 62 * For example, exception #6 is the privilege violation exception which 63 * is raised when the user tries to execute a supervisor-only instruction. 64 * 65 * Exception #1 is the interrupt exception, and is raised when an 66 * outside device raises the INT line on the CPU. This happens, 67 * for example, when the clock signals that it is time for a context 68 * switch, or perhaps the disk drive signaling that some operation 69 * is complete. 70 * 71 * Traps are also exceptions. Traps are ways for user programs to request 72 * kernel operations. For example, "tcnd eq0, r0, 450" will raise 73 * exception 450, the system call exception. 74 * 75 * 76 * SERVICING AN EXCEPTION 77 * ----------------------- 78 * When an exception occurs, each control register is saved in its 79 * respective shadow register and execution continues from the 80 * appropriate exception handler. The exception handler must 81 * - save the context from the time of the exception 82 * - service the exception 83 * - restore the context (registers, etc) 84 * - pick up from where the exception occurred. 85 * 86 * The context is saved on a stack. Actually, in the user_state area 87 * in the PCB if the exception happens in user mode. 88 * 89 * Servicing the exception is usually straightforward and in fact not dealt 90 * with very much here. Usually a C routine is called to handle it. 91 * For example, when a privilege exception is raised, the routine that sends 92 * an "illegal instruction" signal to the offending process is called. 93 * 94 * When the exception has been serviced, the context is restored from the 95 * stack and execution resumes from where it left off. 96 * 97 * In more detail: 98 * 99 * Saving the exception-time context. 100 * --------------------------------- 101 * In saving the exception-time context, we copy the shadow and general 102 * purpose registers to memory. Since one exception may occur while 103 * servicing another, the memory used to save the exception-time context may 104 * not be static (i.e. the same every time). Thus, memory on a stack is set 105 * aside for the exception frame (area where the exception-time context is 106 * saved). The same stack is also used when C routines are called (to 107 * service the exception). 108 * 109 * Each process has a stack in kernel space (called the "kernel stack", 110 * short for "process's kernel stack) as well as the user space stack. When 111 * entering the kernel from user space, the kernel stack is unused. On this 112 * stack we save the exception state and (most likely call a C routine to) 113 * service the exception. 114 * 115 * Before servicing an exception, several issues must be addressed. 116 * 117 * 1) When an interrupt is recognized by the hardware, the data pipeline is 118 * allowed to clear. However, if one of these data accesses faults (bad 119 * reference, or a reference to a page which needs to be swapped in), that 120 * reference, as well as any others in the pipeline at the time (at most 121 * three total) are left there, to be taken care of by the exception 122 * handler [6.4.1]. This involves swapping in the proper page and 123 * manually doing the appropriate load or store. 124 * 125 * The other (at most, two other) data accesses that might have been in 126 * the pipeline must also be manually completed (even though they may not 127 * be at fault [yes, that's a bad pun, thank you]). 128 * 129 * 2) If any of the (at most three) uncompleted data access in the pipeline 130 * are loads (from memory to a register), then the bit for the destination 131 * register is set in the SSBR. Since the hardware will never complete 132 * that load (since we do it manually), the hardware will never clear that 133 * SSBR bit. Thus, we must clear it manually. If this isn't done, the 134 * system will hang waiting for a bit to clear that will never. 135 * 136 * 3) If the exception is the privilege violation exception, the bounds 137 * check exception, or the misaligned access exception, the 138 * destination register bit in the SSBR may need to be cleared. 139 * 140 * 4) If the exception is one of the floating exceptions, then the 141 * destination register for that floating process won't be written, 142 * and the SSBR must be cleared explicitly. 143 * 144 * 5) The FPU must be enabled (as it is disabled by the exception processing 145 * hardware) and allowed to complete actions in progress. This is 146 * so that it may be used in the servicing of any instruction. 147 * When the FPU is being restarted, operations attempting to complete 148 * may themselves fault (raising another exception). 149 * 150 * More on Restarting the FPU 151 * -------------------------- 152 * The manual [section 6.4.3.4] gives only minor mention to this 153 * rather complex task. Before the FPU is restarted all SSBR bits are 154 * cleared for actions that the exception handler completes (as mentioned 155 * above) so that the SSBR is clear unless there are FPU operations that 156 * have not actually been completed (and hence not written to the registers). 157 * Also, all control registers (at least all those that we care about) are 158 * saved to the stack exception frame before the FPU is restarted (this 159 * is important... the reason comes later). 160 * 161 * The FPU is restarted by doing an rte to a trap-not-taken (the rte 162 * actually enables the fpu because we ensure that the EPSR has the 163 * FPU-enable bit on; the trap-not-taken ensures anything in the FPU 164 * completes by waiting until scoreboard register is clear). 165 * 166 * At the time the FPU is restarted (the rte to the trap-not-taken) the FPU 167 * can write to ANY of the general registers. Thus, we must make sure that 168 * all general registers (r1..r31) are in their pre-exception state so that 169 * when saved to the exception frame after the FPU is enabled, they properly 170 * reflect any changes made by the FPU in being restarted. 171 * 172 * Because we can't save the pointer to the exception frame in a general 173 * register during the FPU restart (it could get overwritten by the FPU!), 174 * we save it in a control register, SR3, during the restart. 175 * 176 * HOWEVER ..... 177 * 178 * Because other uncompleted actions in the FPU may fault when the FPU is 179 * restarted, a new exception may be raised during the restart. This may 180 * happen recursively a number of times. Thus, during a restart, ANY register 181 * whatsoever may be modified, including control registers. Because of this 182 * we must make sure that the exception handler preserves SR3 throughout 183 * servicing an exception so that, if the exception had been raised during 184 * an FPU restart, it is returned unmolested when control returns to the FPU 185 * restart. 186 * 187 * Thus: if an exception is from kernel space, we MUST preserve SR3. 188 * (if it from user space, no FPU-enable can be in progress and SR3 is 189 * unimportant). 190 * 191 * Now is a good time to recap SR1..SR3 usage: 192 * SR1 - CPU flags (exception handler flags) 193 * SR2 - generally free 194 * SR3 - free only if the exception is from user mode 195 * 196 * Once the FPU has been restarted, the general registers are saved to the 197 * exception frame. If the exception is not the interrupt exception, 198 * interrupts are enabled and any faulted data accesses (see above) are 199 * serviced. In either case, the exception is then serviced (usually by 200 * calling a C routine). After servicing, any faulted data accesses are 201 * serviced (if it had been the interrupt exception). The context is then 202 * restored and control returns to where the exception occurred. 203 * 204 */ 205 206#include "assym.h" 207 208#include <machine/param.h> 209#include <machine/asm.h> 210#include <machine/trap.h> 211 212/* 213 * SR1 - CPU FLAGS REGISTER 214 * 215 * SR1 contains flags about the current CPU status. 216 * 217 * The bit FLAG_IGNORE_DATA_EXCEPTION indicates that any data exceptions 218 * should be ignored (well, at least treated in a special way). 219 * The bit FLAG_ENABLING_FPU indicates that the exception handler is 220 * in the process of enabling the FPU (so that an exception can 221 * be serviced). This is needed because enabling the FPU can 222 * cause other exceptions to happen, and the whole system is 223 * in a rather precarious state and so special cautions must 224 * be taken. 225 */ 226#define FLAG_IGNORE_DATA_EXCEPTION 0 227#define FLAG_ENABLING_FPU 1 228#define FLAG_FROM_KERNEL 2 229 230/* GENeral REGister OFFset into the E.F. (exception frame) */ 231#define GENREG_OFF(num) (EF_R0 + (num) * 4) 232 233/* Invoke a C function with 2 arguments */ 234#define CALL(NAME, ARG1, ARG2) \ 235 or %r2, %r0, ARG1; \ 236 bsr.n NAME; \ 237 or %r3, %r0, ARG2 238 239/* Invoke a function and return elsewhere */ 240/* CAREFUL: needs to have `RET' after the XCALL in memory */ 241#define XCALL(NAME, RET) \ 242 bsr.n NAME; \ 243 addu %r1, %r1, RET - . - 4 244 245/* 246 * Some registers used during the setting up of the new exception frame. 247 * Don't choose r1, r30, or r31 for any of them. 248 * 249 * Also, if any are 'r2' or 'r3', be careful using with CALL above! 250 */ 251#define FLAGS %r2 252#define TMP %r3 253#define TMP2 %r10 254#define TMP3 %r11 255#define SAVE_TMP2(ef) st %r10, ef, GENREG_OFF(10) 256#define SAVE_TMP3(ef) st %r11, ef, GENREG_OFF(11) 257#define RESTORE_TMP2(ef) ld %r10, ef, GENREG_OFF(10) 258#define RESTORE_TMP3(ef) ld %r11, ef, GENREG_OFF(11) 259 260/* 261 * EF_SR3 262 * A place to save the exception-time SR3 from just after the 263 * time when an exception is raised until just after the FPU 264 * has been restarted. This does not necessarily conflict with 265 * the general registers (though it can if you're not careful) 266 * and so we can use a spot later used to save a general register. 267 */ 268#define EF_SR3 GENREG_OFF(5) 269 270 .text 271 .align 3 272 273/* 274 * 275 * #define PREP881x0(NAME, NUM, SSBR_STUFF, FLAG_CHECK) 276 * 277 * This is the "exception processing preparation" common to all exception 278 * processing. It is used in the following manner: 279 * 280 * ASGLOBAL(foo_handler) 281 * PREP881x0("foo", 11, SSBR_Stuff, Precheck_Stuff) 282 * or %r2, %r0, T_FOO_FAULT 283 * or %r3, %r0, %r30 284 * XCALL(trapXXX, check_ast) 285 * 286 * This defines the exception handler for the "foo" exception. 287 * The arguments are: 288 * NAME 289 * String for debugging (more info later) 290 * NUM 291 * The exception number [see the manual, Table 6-1] 292 * SSBR_STUFF 293 * If the exception might leave some bits in the SSBR set, 294 * this should indicate how they are cleared. 295 * FLAG_PRECHECK 296 * This is for the data access exception only. See it for 297 * more info. 298 * 299 * What's in between PREP881x0() and check_ast (usually a XCALL) 300 * is the actual servicing of the interrupt. During this time, any 301 * register may be used freely as they've all been saved in the 302 * exception frame (which is pointed to by r30). 303 */ 304 305#ifdef M88100 306#define PREP88100(NAME, NUM, SSBR_STUFF, FLAG_PRECHECK) \ 307 xcr FLAGS, FLAGS, SR1 ; \ 308 FLAG_PRECHECK \ 309 /* the bsr later clobbers r1, so save now */ \ 310 stcr %r1, SR2 /* r1 now free */ ; \ 311 /* set or clear the FLAG_FROM_KERNEL bit */ \ 312 ldcr %r1, EPSR ; \ 313 bb0.n PSR_SUPERVISOR_MODE_BIT, %r1, 1f ; \ 314 clr FLAGS, FLAGS, 1<FLAG_FROM_KERNEL> ; \ 315 set FLAGS, FLAGS, 1<FLAG_FROM_KERNEL> ; \ 316 /* get a stack (exception frame) */ \ 3171: bsr m88100_setup_phase_one ; \ 318 /* TMP2 now free -- use to set EF_VECTOR */ \ 319 or TMP2, %r0, NUM ; \ 320 st TMP2, %r31, EF_VECTOR ; \ 321 /* Clear any bits in the SSBR (held in TMP) */ \ 322 /* SSBR_STUFF may be empty, though. */ \ 323 SSBR_STUFF \ 324 /* call setup_phase_two to restart the FPU */ \ 325 /* and to save all general registers. */ \ 326 bsr m88100_setup_phase_two 327#endif 328 329#ifdef M88110 330#define PREP88110(NAME, NUM, FLAG_PRECHECK) \ 331 xcr FLAGS, FLAGS, SR1 ; \ 332 FLAG_PRECHECK \ 333 /* the bsr later clobbers r1, so save now */ ; \ 334 stcr %r1, SR2 /* r1 now free */ ; \ 335 /* set or clear the FLAG_FROM_KERNEL bit */ ; \ 336 ldcr %r1, EPSR ; \ 337 clr FLAGS, FLAGS, 1<FLAG_FROM_KERNEL> ; \ 338 bb0 PSR_SUPERVISOR_MODE_BIT, %r1, 1f ; \ 339 set FLAGS, FLAGS, 1<FLAG_FROM_KERNEL> ; \ 340 /* get a stack and an exception frame */ ; \ 3411: bsr m88110_setup_phase_one ; \ 342 /* TMP2 now free -- use to set EF_VECTOR */ ; \ 343 or TMP2, %r0, NUM ; \ 344 /* call setup_phase_two to save all general */ ; \ 345 /* registers. */ ; \ 346 st TMP2, %r30, EF_VECTOR ; \ 347 bsr m88110_setup_phase_two 348#endif 349 350/* Some defines for use with PREP88100() */ 351#define Clear_SSBR_Dest \ 352 bsr clear_dest_ssbr_bit; 353#define M88100_Data_Precheck \ 354 bb1.n FLAG_IGNORE_DATA_EXCEPTION, FLAGS, \ 355 m88100_ignore_data_exception; 356#define M88110_Data_Precheck \ 357 bb1.n FLAG_IGNORE_DATA_EXCEPTION, FLAGS, \ 358 m88110_ignore_data_exception; 359 360#ifdef M88100 361/* 362 * 88100 exception handlers 363 */ 364 365/* unknown exception handler */ 366GLOBAL(unknown_handler) 367 PREP88100("unknown", 0,,) 368 or %r2, %r0, T_UNKNOWNFLT 369 or %r3, %r0, %r30 370 XCALL(m88100_trap, check_ast) 371 372/* interrupt exception handler */ 373GLOBAL(interrupt_handler) 374 PREP88100("interrupt", 1,,) 375 or %r2, %r0, %r30 376 XCALL(interrupt, check_ast) 377 378/* instruction access exception handler */ 379GLOBAL(instruction_access_handler) 380 PREP88100("inst", 2,,) 381 or %r2, %r0, T_INSTFLT 382 or %r3, %r0, %r30 383 XCALL(m88100_trap, check_ast) 384 385/* 386 * data access exception handler -- 387 * See badaddr() below for info about Data_Precheck. 388 */ 389GLOBAL(data_exception_handler_bootstrap) 390 PREP88100("data", 3,, M88100_Data_Precheck) 391 /* No need to call m88100_trap(T_DATAFLT) as PREP will do this for us */ 392 br check_ast 393GLOBAL(data_exception_handler) 394 PREP88100("data", 3,,) 395 /* No need to call m88100_trap(T_DATAFLT) as PREP will do this for us */ 396 br check_ast 397 398/* misaligned access exception handler */ 399GLOBAL(misaligned_handler) 400 PREP88100("misalign", 4, Clear_SSBR_Dest,) 401 or %r2, %r0, T_MISALGNFLT 402 or %r3, %r0, %r30 403 XCALL(m88100_trap, check_ast) 404 405/* unimplemented opcode exception handler */ 406GLOBAL(unimplemented_handler) 407 PREP88100("unimp", 5,,) 408 or %r2, %r0, T_ILLFLT 409 or %r3, %r0, %r30 410 XCALL(m88100_trap, check_ast) 411 412/* 413 * Some versions of the chip have a bug whereby false privilege 414 * violation exceptions are raised. If the valid bit in the SXIP is clear, 415 * it is false. If so, just return. The code before PREP handles this.... 416 */ 417GLOBAL(privilege_handler) 418 stcr %r1, SR2 /* hold r1 for a moment */ 419 ldcr %r1, SXIP /* look at the sxip... valid bit set? */ 420 bb1.n RTE_VALID_BIT, %r1, 1f /* skip over if a valid exception */ 421 ldcr %r1, SR2 /* restore r1 */ 422 RTE 4231: PREP88100("privilege", 6, Clear_SSBR_Dest,) 424 or %r2, %r0, T_PRIVINFLT 425 or %r3, %r0, %r30 426 XCALL(m88100_trap, check_ast) 427 428/* bounds checking exception handler */ 429GLOBAL(bounds_handler) 430 PREP88100("bounds", 7, Clear_SSBR_Dest,) 431 or %r2, %r0, T_BNDFLT 432 or %r3, %r0, %r30 433 XCALL(m88100_trap, check_ast) 434 435/* integer divide-by-zero exception handler */ 436GLOBAL(divide_handler) 437 PREP88100("divide", 8, Clear_SSBR_Dest,) 438 or %r2, %r0, T_ZERODIV 439 or %r3, %r0, %r30 440 XCALL(m88100_trap, check_ast) 441 442/* integer overflow exception handler */ 443GLOBAL(overflow_handler) 444 PREP88100("overflow", 9,,) 445 or %r2, %r0, T_OVFFLT 446 or %r3, %r0, %r30 447 XCALL(m88100_trap, check_ast) 448 449/* Floating-point precise handler */ 450#define FPp_SSBR_STUFF \ 451 bsr clear_FPp_ssbr_bit; 452GLOBAL(fp_precise_handler) 453 PREP88100("FPU precise", 114, FPp_SSBR_STUFF,) 454 or %r2, %r0, T_FPEPFLT 455 or %r3, %r0, %r30 456 XCALL(m88100_trap, check_ast) 457 458/* Floating-point imprecise handler */ 459#define FPi_SSBR_STUFF \ 460 bsr clear_FPi_ssbr_bit; 461GLOBAL(fp_imprecise_handler) 462 PREP88100("FPU imprecise", 115, FPi_SSBR_STUFF,) 463 or %r2, %r0, T_FPEIFLT 464 or %r3, %r0, %r30 465 XCALL(m88100_trap, check_ast) 466 467/* trap 450: system calls */ 468GLOBAL(syscall_handler) 469 PREP88100("syscall", 450,,) 470 ld %r2, %r30, GENREG_OFF(13) 471 or %r3, %r0, %r30 472 XCALL(m88100_syscall, check_ast) 473 474/* trap 451: cache flush (necessary for trampolines) */ 475GLOBAL(cache_flush_handler) 476 PREP88100("cache_flush", 451,,) 477 or %r2, %r0, %r30 478 XCALL(cache_flush, check_ast) 479 480GLOBAL(sigsys) 481 PREP88100("sigsys", 501,,) 482 or %r2, %r0, T_SIGSYS 483 or %r3, %r0, %r30 484 XCALL(m88100_trap, check_ast) 485 486GLOBAL(stepbpt) 487 PREP88100("stepbpt", 504,,) 488 or %r2, %r0, T_STEPBPT 489 or %r3, %r0, %r30 490 XCALL(m88100_trap, check_ast) 491 492GLOBAL(userbpt) 493 PREP88100("userbpt", 511,,) 494 or %r2, %r0, T_USERBPT 495 or %r3, %r0, %r30 496 XCALL(m88100_trap, check_ast) 497 498#ifdef DDB 499GLOBAL(break) 500 PREP88100("break", 130,,) 501 or %r2, %r0, T_KDB_BREAK 502 or %r3, %r0, %r30 503 XCALL(m88100_trap, check_ast) 504 505GLOBAL(trace) 506 PREP88100("trace", 131,,) 507 or %r2, %r0, T_KDB_TRACE 508 or %r3, %r0, %r30 509 XCALL(m88100_trap, check_ast) 510 511GLOBAL(entry) 512 PREP88100("kdb", 132,,) 513 or %r2, %r0, T_KDB_ENTRY 514 or %r3, %r0, %r30 515 XCALL(m88100_trap, check_ast) 516#endif 517 518/* 519 * The error exception and reset exception handler. 520 * 521 * The error exception is raised when any other non-trap exception is raised 522 * while shadowing is off. This is Bad News. 523 * 524 * The reset exception is raised when the RST signal is asserted (machine 525 * is reset), the value of VBR is changed after exceptions are enabled, 526 * or when a jmp, br/bsr to addr 0 (accidents do happen :-) 527 * To tell the difference, you should check the value of r1 and the valid 528 * bit of SXIP. 529 * Upon a real reset, VBR is set to zero (0), so code must be at addr 0 530 * to handle it!!! 531 * 532 * The shadow registers are not valid in this case (shadowing was off, if this 533 * was an error exception, and may not be on, if this was a reset exception). 534 * R1-R31 may be interesting though, so we'll save them. 535 * 536 * We'll not worry about trashing r26-29 here, 537 * since they aren't generally used. 538 */ 539GLOBAL(error_handler) 540 br.n 1f 541 or %r29, %r0, 10 542GLOBAL(reset_handler) 543 or %r29, %r0, 0 5441: 545 or %r26, %r0, %r31 /* save old stack */ 546 or.u %r31, %r0, %hi16(initstack_end) 547 or %r31, %r31, %lo16(initstack_end) 548 549#ifdef DEBUG 550 /* zero the stack, so we'll know what we're lookin' at */ 551 or.u %r27, %r0, %hi16(initstack) 552 or %r27, %r27, %lo16(initstack) 5531: cmp %r28, %r27, %r31 554 bb1 ge, %r28, 2f /* branch if at the end of the stack */ 555 st %r0, %r0, %r27 556 br.n 1b 557 addu %r27, %r27, 4 /* bump up */ 5582: /* stack has been cleared */ 559#endif 560 561 /* ensure that stack is 8-byte aligned */ 562 clr %r31, %r31, 3<0> /* round down to 8-byte boundary */ 563 564 /* create exception frame on stack */ 565 subu %r31, %r31, TRAPFRAME_SIZEOF /* r31 now our E.F. */ 566 567 /* save old R31 and other R registers */ 568 st.d %r0 , %r31, GENREG_OFF(0) 569 st.d %r2 , %r31, GENREG_OFF(2) 570 st.d %r4 , %r31, GENREG_OFF(4) 571 st.d %r6 , %r31, GENREG_OFF(6) 572 st.d %r8 , %r31, GENREG_OFF(8) 573 st.d %r10, %r31, GENREG_OFF(10) 574 st.d %r12, %r31, GENREG_OFF(12) 575 st.d %r14, %r31, GENREG_OFF(14) 576 st.d %r16, %r31, GENREG_OFF(16) 577 st.d %r18, %r31, GENREG_OFF(18) 578 st.d %r20, %r31, GENREG_OFF(20) 579 st.d %r22, %r31, GENREG_OFF(22) 580 st.d %r24, %r31, GENREG_OFF(24) 581 st %r30, %r31, GENREG_OFF(30) 582 st %r26, %r31, GENREG_OFF(31) 583 584 /* save shadow registers (are OLD if error_handler, though) */ 585 ldcr %r10, EPSR 586 st %r10, %r31, EF_EPSR 587 ldcr %r10, SXIP 588 st %r10, %r31, EF_SXIP 589 ldcr %r10, SNIP 590 st %r10, %r31, EF_SNIP 591 ldcr %r10, SR1 592 st %r10, %r31, EF_FLAGS 593 ldcr %r10, SFIP 594 st %r10, %r31, EF_SFIP 595 ldcr %r10, SSBR 596 st %r10, %r31, EF_SSBR 597 stcr %r0, SSBR /* won't want shadow bits bothering us later */ 598 599 ldcr %r10, DMT0 600 st %r10, %r31, EF_DMT0 601 ldcr %r11, DMD0 602 st %r11, %r31, EF_DMD0 603 ldcr %r12, DMA0 604 605 st %r12, %r31, EF_DMA0 606 ldcr %r10, DMT1 607 st %r10, %r31, EF_DMT1 608 FLUSH_PIPELINE 609 ldcr %r11, DMD1 610 st %r11, %r31, EF_DMD1 611 ldcr %r12, DMA1 612 st %r12, %r31, EF_DMA1 613 614 ldcr %r10, DMT2 615 st %r10, %r31, EF_DMT2 616 ldcr %r11, DMD2 617 st %r11, %r31, EF_DMD2 618 ldcr %r12, DMA2 619 st %r12, %r31, EF_DMA2 620 621 /* shove sr2 into EF_FPLS1 */ 622 ldcr %r10, SR2 623 st %r10, %r31, EF_FPLS1 624 625 /* shove sr3 into EF_FPHS2 */ 626 ldcr %r10, SR3 627 st %r10, %r31, EF_FPHS2 628 629 /* save error vector */ 630 st %r29, %r31, EF_VECTOR 631 632 /* 633 * Cheap way to enable FPU and start shadowing again. 634 */ 635 ldcr %r10, PSR 636 clr %r10, %r10, 1<PSR_FPU_DISABLE_BIT> /* enable the FPU */ 637 clr %r10, %r10, 1<PSR_SHADOW_FREEZE_BIT> /* and shadowing */ 638 stcr %r10, PSR 639 FLUSH_PIPELINE 640 641 /* put pointer to regs into r30... r31 will become a simple stack */ 642 or %r30, %r31, %r0 643 644 subu %r31, %r31, 0x10 /* make some breathing space */ 645 st %r30, %r31, 0x0c /* store frame pointer on the stack */ 646#ifdef DDB 647 st %r30, %r31, 0x08 /* store again for the debugger to recognize */ 648 or.u %r20, %r0, %hi16(0x87654321) 649 or %r20, %r20, %lo16(0x87654321) 650 st %r20, %r31, 0x04 651 st %r20, %r31, 0x00 652#endif 653 654 bsr.n error_fatal 655 or %r2, %r0, %r30 656 657 /* turn interrupts back on */ 658 ldcr %r1, PSR 659 clr %r1, %r1, 1<PSR_INTERRUPT_DISABLE_BIT> 660 stcr %r1, PSR 661 FLUSH_PIPELINE 662 6631: 664 br 1b 665 /* NOTREACHED */ 666#endif /* M88100 */ 667 668/* 669 * This is part of baddadr (below). 670 */ 671#ifdef M88100 672ASLOCAL(m88100_ignore_data_exception) 673 /* 674 * SR1: previous FLAGS reg 675 * SR2: free 676 * SR3: must preserve 677 * FLAGS: CPU status flags 678 */ 679 xcr FLAGS, FLAGS, SR1 /* replace SR1, FLAGS */ 680 681 /* 682 * For more info, see badaddr() below. 683 * 684 * We just want to jump to "badaddr__return_nonzero" below. 685 * 686 * We don't worry about trashing r2 here because we're 687 * jumping back to the function badaddr() where we're allowed 688 * to blast r2..r9 as we see fit. 689 */ 690 691 /* the "+2" below is to set the VALID bit. */ 692 or.u %r2, %r0, %hi16(badaddr__return_nonzero + 2) 693 or %r2, %r2, %lo16(badaddr__return_nonzero + 2) 694 stcr %r2, SNIP /* Make it the next instruction to execute */ 695 addu %r2, %r2, 4 696 stcr %r2, SFIP /* and the next one after that, too. */ 697 stcr %r0, SSBR /* make the scoreboard happy. */ 698 RTE 699#endif /* M88100 */ 700 701#ifdef M88110 702/* 703 * This is part of baddadr (below). 704 */ 705ASLOCAL(m88110_ignore_data_exception) 706 /* 707 * SR1: previous FLAGS reg 708 * SR2: free 709 * SR3: must preserve 710 * FLAGS: CPU status flags 711 */ 712 xcr FLAGS, FLAGS, SR1 /* replace SR1, FLAGS */ 713 714 /* 715 * For more info, see badaddr() below. 716 * 717 * We just want to jump to "badaddr__return_nonzero" below. 718 * 719 * We don't worry about trashing R2 here because we're 720 * jumping back to the function badaddr() where we're allowed 721 * to blast r2..r9 as we see fit. 722 */ 723 724 or.u %r2, %r0, %hi16(badaddr__return_nonzero) 725 or %r2, %r2, %lo16(badaddr__return_nonzero) 726 stcr %r2, EXIP /* Make it the next instruction to execute */ 727 stcr %r0, DSR /* Clear exception status */ 728 RTE 729#endif /* M88110 */ 730 731/* 732 * extern int badaddr(vaddr_t addr, int len) 733 * 734 * Returns true (non-zero) if the given LEN bytes starting at ADDR are 735 * not all currently accessible by the kernel. 736 * 737 * If all LEN bytes starting at ADDR are accessible, zero is returned. 738 * 739 * Len may be be 1, 2, 4 or 8. 740 * 741 * This is implemented by setting a special flag in SR1 before trying to access 742 * the given address. If a data access exception is raised, the address 743 * is inaccessible. The exception handler will notice the special CPU flag 744 * and not try to swap the address in. Rather, it will return to 745 * "badaddr__return_nonzero" in this routine so that we may return non-zero 746 * to the calling routine. 747 * 748 * If no fault is raised, we continue to where we return zero to the calling 749 * routine (after removing the special CPU flag). 750 */ 751 752GLOBAL(badaddr) 753 /* 754 * Disable interrupts ... don't want a context switch while we're 755 * doing this! Also, save the old PSR in R8 to restore later. 756 */ 757 ldcr %r8, PSR 758 set %r4, %r8, 1<PSR_INTERRUPT_DISABLE_BIT> 759 stcr %r4, PSR 760 FLUSH_PIPELINE 761 762 ldcr %r5, SR1 763 set %r5, %r5, 1<FLAG_IGNORE_DATA_EXCEPTION> 764 /* resetting r5 to SR1 done in the delay slot below. */ 765 766 /* make sure the upper 28 bits of the size are zero... */ 767 ext %r6, %r3, 0<4> 768 bcnd.n ne0, %r6, badaddr__return_nonzero 769 stcr %r5, SR1 770 771 or.u %r6, %r0, %hi16(badaddr_switch) 772 or %r6, %r6, %lo16(badaddr_switch) 773 lda %r3, %r6[%r3] 774 jmp %r3 775 776ASLOCAL(badaddr_switch) 777 br badaddr__return_nonzero 778 br badaddr__b 779 br badaddr__h 780 br badaddr__return_nonzero 781 br badaddr__w 782 br badaddr__return_nonzero 783 br badaddr__return_nonzero 784 br badaddr__return_nonzero 785 br badaddr__d 786 br badaddr__return_nonzero 787 br badaddr__return_nonzero 788 br badaddr__return_nonzero 789 br badaddr__return_nonzero 790 br badaddr__return_nonzero 791 br badaddr__return_nonzero 792 br badaddr__return_nonzero 793 794 /* 795 * The load attempts below will either fault or not. If they fault, 796 * execution will go to data_access_handler, then to 797 * ignore_data_exception, then to badaddr__return_nonzero, which 798 * will return to the calling function. 799 * If there is no fault, execution will just continue as normal. 800 */ 801 802ASLOCAL(badaddr__b) 803 FLUSH_PIPELINE 804 ld.b %r6, %r2, 0 805 FLUSH_PIPELINE 806 br.n badaddr__return 807 or %r2, %r0, %r0 808 809ASLOCAL(badaddr__h) 810 /* It's a bad address if it's misaligned. */ 811 bb1 0, %r2, badaddr__return_nonzero 812 813 FLUSH_PIPELINE 814 ld.h %r6, %r2, 0 815 FLUSH_PIPELINE 816 br.n badaddr__return 817 or %r2, %r0, %r0 818 819ASLOCAL(badaddr__w) 820 /* It's a bad address if it's misaligned. */ 821 bb1 0, %r2, badaddr__return_nonzero 822 bb1 1, %r2, badaddr__return_nonzero 823 824 FLUSH_PIPELINE 825 ld %r6, %r2, 0 826 FLUSH_PIPELINE 827 br.n badaddr__return 828 or %r2, %r0, %r0 /* indicate a zero (address not bad) return.*/ 829 830ASLOCAL(badaddr__d) 831 /* It's a bad address if it's misaligned. */ 832 bb1 0, %r2, badaddr__return_nonzero 833 bb1 1, %r2, badaddr__return_nonzero 834 bb1 2, %r2, badaddr__return_nonzero 835 836 FLUSH_PIPELINE 837 ld.d %r6, %r2, 0 838 FLUSH_PIPELINE 839 br.n badaddr__return 840 or %r2, %r0, %r0 /* indicate a zero (address not bad) return.*/ 841 842ASLOCAL(badaddr__return_nonzero) 843 or %r2, %r0, 1 844 /* FALLTHROUGH */ 845 846ASLOCAL(badaddr__return) 847 ldcr %r4, SR1 848 clr %r4, %r4, 1<FLAG_IGNORE_DATA_EXCEPTION> 849 stcr %r4, SR1 850 851 /* 852 * Restore the PSR to what it was before. 853 * The only difference is that we might be enabling interrupts 854 * (which we turned off above). If interrupts were already off, 855 * we do not want to turn them on now, so we just restore from 856 * where we saved it. 857 */ 858 stcr %r8, PSR 859 FLUSH_PIPELINE 860 jmp %r1 861 862#ifdef M88100 863ASLOCAL(m88100_setup_phase_one) 864 /* 865 * SR1: saved copy of exception-time register now holding FLAGS 866 * SR2: saved copy of exception-time r1 867 * SR3: must be preserved .. may be the exception-time stack 868 * r1: return address to calling exception handler 869 * FLAGS: CPU status flags 870 * 871 * immediate goal: 872 * Decide where we're going to put the exception frame. 873 * Might be at the end of R31, SR3, or the process pcb. 874 */ 875 876 /* Check if we are coming in from a FPU restart exception. 877 If so, the pcb will be in SR3 */ 878 NOP 879 xcr %r1, %r1, SR2 880 NOP 881 NOP 882 NOP 883 884 bb1 FLAG_ENABLING_FPU, FLAGS, m88100_use_SR3_pcb 885 /* are we coming in from user mode? If so, pick up process pcb */ 886 bb0 FLAG_FROM_KERNEL, FLAGS, m88100_pickup_stack 887 888 /* Interrupt in kernel mode, not FPU restart */ 889 /* 890 * SR1: saved copy of exception-time register now holding FLAGS 891 * SR2: return address to the calling exception handler 892 * SR3: must be preserved; may be important for other exceptions 893 * FLAGS: CPU status flags 894 * 895 * immediate goal: 896 * We're already on the kernel stack, but not having 897 * needed to use SR3. We can just make room on the 898 * stack (r31) for our exception frame. 899 */ 900 subu %r31, %r31, TRAPFRAME_SIZEOF /* r31 now our E.F. */ 901 st FLAGS,%r31, EF_FLAGS /* save flags */ 902 st %r1, %r31, GENREG_OFF(1) /* save prev. r1 (now free)*/ 903 904 ldcr %r1, SR3 /* save previous SR3 */ 905 st %r1, %r31, EF_SR3 906 907 addu %r1, %r31, TRAPFRAME_SIZEOF /* save previous r31 */ 908 br.n m88100_have_pcb 909 st %r1, %r31, GENREG_OFF(31) 910 911ASLOCAL(m88100_use_SR3_pcb) 912 /* 913 * SR1: saved copy of exception-time register now holding FLAGS 914 * SR2: return address to the calling exception handler 915 * SR3: must be preserved; exception-time stack pointer 916 * FLAGS: CPU status flags 917 * 918 * immediate goal: 919 * An exception occurred while enabling the FPU. Since r31 920 * is the user's r31 while enabling the FPU, we had put 921 * our pcb pointer into SR3, so make room from 922 * there for our stack pointer. 923 * We need to check if SR3 is the old stack pointer or the 924 * pointer off to the user pcb. If it pointing to the user 925 * pcb, we need to pick up the kernel stack. Otherwise 926 * we need to allocate a frame upon it. 927 * We look at the EPSR to see if it was from user mode 928 * Unfortunately, we have no registers free at the moment 929 * But we know register 0 in the pcb frame will always be 930 * zero, so we can use it as scratch storage. 931 */ 932 xcr %r30, %r30, SR3 /* r30 = old exception frame */ 933 st %r1, %r30, GENREG_OFF(0) /* free up r1 */ 934 ld %r1, %r30, EF_EPSR /* get back the epsr */ 935 bb0.n PSR_SUPERVISOR_MODE_BIT, %r1, 1f/* if user mode */ 936 ld %r1, %r30, GENREG_OFF(0) /* restore r1 */ 937 /* we were in kernel mode - dump frame upon the stack */ 938 st %r0, %r30, GENREG_OFF(0) /* repair old frame */ 939 subu %r30, %r30, TRAPFRAME_SIZEOF /* r30 now our E.F. */ 940 st FLAGS,%r30, EF_FLAGS /* save flags */ 941 st %r1, %r30, GENREG_OFF(1) /* save prev r1 (now free) */ 942 943 st %r31, %r30, GENREG_OFF(31) /* save previous r31 */ 944 or %r31, %r0, %r30 /* make r31 our pointer. */ 945 addu %r30, %r30, TRAPFRAME_SIZEOF /* r30 now has previous SR3 */ 946 st %r30, %r31, EF_SR3 /* save previous SR3 */ 947 br.n m88100_have_pcb 948 xcr %r30, %r30, SR3 /* restore r30 */ 9491: 950 /* we took an exception while restarting the FPU from user space. 951 * Consequently, we never picked up a stack. Do so now. 952 * R1 is currently free (saved in the exception frame pointed at by 953 * r30) */ 954 ldcr %r1, CPU 955 ld %r1, %r1, CI_CURPCB 956 addu %r1, %r1, USPACE - TRAPFRAME_SIZEOF 957 st FLAGS,%r1, EF_FLAGS /* store flags */ 958 st %r31, %r1, GENREG_OFF(31) /* store r31 - now free */ 959 st %r30, %r1, EF_SR3 /* store old SR3 (pcb) */ 960 or %r31, %r1, %r0 /* make r31 our exception fp */ 961 ld %r1, %r30, GENREG_OFF(0) /* restore old r1 */ 962 st %r0, %r30, GENREG_OFF(0) /* repair that frame */ 963 st %r1, %r31, GENREG_OFF(1) /* store r1 */ 964 br.n m88100_have_pcb 965 xcr %r30, %r30, SR3 /* restore r30 */ 966 967ASLOCAL(m88100_pickup_stack) 968 /* 969 * SR1: saved copy of exception-time register now holding FLAGS 970 * SR2: return address to the calling exception handler 971 * SR3: free 972 * FLAGS: CPU status flags 973 * 974 * immediate goal: 975 * Since we're servicing an exception from user mode, we 976 * know that SR3 is free. We use it to free up a temp. 977 * register to be used in getting the process pcb 978 */ 979 stcr %r31, SR3 /* save previous r31 */ 980 981 /* switch to the process kernel stack. */ 982 ldcr %r31, CPU 983 ld %r31, %r31, CI_CURPCB 984 addu %r31, %r31, PCB_USER_STATE /* point to user save area */ 985 986 /* 987 * WARNING! Using pcb->user_state as the exception frame 988 * AND stack pointer, means we can not afford using the stack 989 * until we have saved enough and can go back to the top of the u area, 990 * after the FPU is enabled. 991 */ 992 993 st FLAGS,%r31, EF_FLAGS /* save flags */ 994 st %r1, %r31, GENREG_OFF(1) /* save prev. r1 (now free) */ 995 ldcr %r1, SR3 /* save previous r31 */ 996 st %r1, %r31, GENREG_OFF(31) 997 /* FALLTHROUGH */ 998 999ASLOCAL(m88100_have_pcb) 1000 /* 1001 * SR1: saved copy of exception-time register now holding FLAGS 1002 * SR2: return address to the calling exception handler 1003 * SR3: free 1004 * r1: free 1005 * FLAGS: CPU status flags 1006 * r31: our exception frame 1007 * Valid in the exception frame: 1008 * Exception-time r1, r31, FLAGS. 1009 * Exception SR3, if appropriate. 1010 * 1011 * immediate goal: 1012 * Save the shadow registers that need to be saved to 1013 * the exception frame. 1014 */ 1015 stcr TMP, SR3 /* free up TMP, TMP2, TMP3 */ 1016 SAVE_TMP2(%r31) 1017 SAVE_TMP3(%r31) 1018 1019 /* save some exception-time registers to the exception frame */ 1020 ldcr TMP, EPSR 1021 st TMP, %r31, EF_EPSR 1022 ldcr TMP3, SNIP 1023 st TMP3, %r31, EF_SNIP 1024 ldcr TMP2, SFIP 1025 st TMP2, %r31, EF_SFIP 1026 /* get and store the cpu_info pointer */ 1027 ldcr TMP, CPU 1028 st TMP, %r31, EF_CPU 1029 1030 /* 1031 * Save Pbus fault status register from data and inst CMMU. 1032 * We can afford calling a function since r1 is safe to use here. 1033 */ 1034GLOBAL(pfsr_save) 1035 PFSR_SAVE 1036ASLOCAL(pfsr_done) 1037 1038 ldcr TMP, SSBR 1039 ldcr TMP2, SXIP 1040 ldcr TMP3, DMT0 1041 st TMP2, %r31, EF_SXIP 1042 1043/* 1044 * The above shadow registers are obligatory for any and all 1045 * exceptions. Now, if the data access pipeline is not clear, 1046 * we must save the DMx shadow registers, as well as clear 1047 * the appropriate SSBR bits for the destination registers of 1048 * loads or xmems. 1049 */ 1050 bb0.n DMT_VALID_BIT, TMP3, 8f 1051 st TMP3, %r31, EF_DMT0 1052 1053 ldcr TMP2, DMT1 1054 ldcr TMP3, DMT2 1055 st TMP2, %r31, EF_DMT1 1056 st TMP3, %r31, EF_DMT2 1057 1058 ldcr TMP2, DMA0 1059 ldcr TMP3, DMA1 1060 st TMP2, %r31, EF_DMA0 1061 st TMP3, %r31, EF_DMA1 1062 1063 ldcr TMP2, DMA2 1064 ldcr TMP3, DMD0 1065 st TMP2, %r31, EF_DMA2 1066 st TMP3, %r31, EF_DMD0 1067 1068 FLUSH_PIPELINE 1069 ldcr TMP2, DMD1 1070 ldcr TMP3, DMD2 1071 st TMP2, %r31, EF_DMD1 1072 st TMP3, %r31, EF_DMD2 1073 1074 /* make sure an exception in fpu_enable will not see our DMT0 */ 1075 stcr %r0, DMT0 1076 1077 /* 1078 * need to clear "appropriate" bits in the SSBR before 1079 * we restart the FPU 1080 */ 1081 ld TMP2, %r31, EF_DMT0 1082 bb1 DMT_LOCK_BIT, TMP2, 1f 1083 bb1 DMT_WRITE_BIT, TMP2, 2f 10841: 1085 extu TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET> 1086 set TMP2, TMP2, 1<5> 1087 clr TMP, TMP, TMP2 10882: 1089 ldcr TMP2, DMT1 1090 bb0 DMT_VALID_BIT, TMP2, 4f 1091 bb1 DMT_LOCK_BIT, TMP2, 3f 1092 bb1 DMT_WRITE_BIT, TMP2, 4f 10933: 1094 extu TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET> 1095 set TMP2, TMP2, 1<5> 1096 clr TMP, TMP, TMP2 10974: 1098 ldcr TMP2, DMT2 1099 bb0 DMT_VALID_BIT, TMP2, 8f 1100 bb1 DMT_LOCK_BIT, TMP2, 5f 1101 bb1 DMT_WRITE_BIT, TMP2, 8f 1102 bb1 DMT_DOUBLE_BIT,TMP2, 6f 11035: 1104 extu TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET> 1105 br.n 7f 1106 set TMP2, TMP2, 1<5> /* single */ 11076: 1108 extu TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET> 1109 set TMP2, TMP2, 1<6> /* double */ 11107: 1111 clr TMP, TMP, TMP2 11128: 1113 /* 1114 * SR1: saved copy of exception-time register now holding FLAGS 1115 * SR2: return address to the calling exception handler 1116 * SR3: saved TMP 1117 * r1: free 1118 * TMP: possibly revised SSBR 1119 * TMP2: free 1120 * TMP3: free 1121 * FLAGS: CPU status flags 1122 * r31: exception frame 1123 * Valid in the exception frame: 1124 * Exception-time r1, r31, FLAGS. 1125 * Exception-time TMP2, TMP3. 1126 * Exception-time epsr, sfip, snip, sxip. 1127 * Dmt0. 1128 * Other data pipeline control registers, if appropriate. 1129 * Exception SR3, if appropriate. 1130 */ 1131 ldcr %r1, SR2 1132 jmp %r1 /* allow the handler to clear more SSBR bits */ 1133 1134ASLOCAL(clear_FPi_ssbr_bit) 1135 /* 1136 * Clear floating point imprecise ssbr bits. 1137 * Also, save appropriate FPU control registers to the E.F. 1138 * 1139 * r1: return address to calling exception handler 1140 * TMP: (possibly) revised ssbr 1141 * TMP2: free 1142 * TMP3: free 1143 */ 1144 fldcr TMP2, FPSR 1145 fldcr TMP3, FPCR 1146 st TMP2, %r31, EF_FPSR 1147 st TMP3, %r31, EF_FPCR 1148 1149 fldcr TMP2, FPECR 1150 fldcr TMP3, FPRH 1151 st TMP2, %r31, EF_FPECR 1152 st TMP3, %r31, EF_FPRH 1153 1154 fldcr TMP2, FPIT 1155 fldcr TMP3, FPRL 1156 st TMP2, %r31, EF_FPIT 1157 st TMP3, %r31, EF_FPRL 1158 1159 /* 1160 * We only need clear the bit in the SSBR for the 1161 * 2nd reg of a double result [see section 6.8.5] 1162 */ 1163#define FPIT_SIZE_BIT 10 1164 bb0 FPIT_SIZE_BIT, TMP2, 1f 1165 extu TMP2, TMP2, 5<0> /* get the reg. */ 1166 set TMP2, TMP2, 1<6> /* set width */ 1167 clr TMP, TMP, TMP2 11681: 1169 jmp %r1 1170 1171 1172ASLOCAL(clear_FPp_ssbr_bit) 1173 /* 1174 * Clear floating point precise ssbr bits. 1175 * Also, save appropriate FPU control registers to the E.F. 1176 * 1177 * r1: return address to calling exception handler 1178 * TMP: (possibly) revised ssbr 1179 * TMP2: free 1180 * TMP3: free 1181 */ 1182 fldcr TMP2, FPSR 1183 fldcr TMP3, FPCR 1184 st TMP2, %r31, EF_FPSR 1185 st TMP3, %r31, EF_FPCR 1186 1187 fldcr TMP3, FPECR 1188 st TMP3, %r31, EF_FPECR 1189 fldcr TMP2, FPHS1 1190 fldcr TMP3, FPHS2 1191 st TMP2, %r31, EF_FPHS1 1192 st TMP3, %r31, EF_FPHS2 1193 1194 fldcr TMP2, FPLS1 1195 fldcr TMP3, FPLS2 1196 st TMP2, %r31, EF_FPLS1 1197 st TMP3, %r31, EF_FPLS2 1198 1199 fldcr TMP2, FPPT 1200 st TMP2, %r31, EF_FPPT 1201 1202#define FPPT_SIZE_BIT 5 1203 bb1.n FPPT_SIZE_BIT, TMP2, 2f 1204 extu TMP3, TMP2, 5<0> /* get FP operation dest reg */ 1205 br.n 3f 1206 set TMP3, TMP3, 1<5> /* size=1 - clear one bit for float */ 12072: 1208 set TMP3, TMP3, 1<6> /* size=2 - clear two bits for double */ 12093: 1210 jmp.n %r1 1211 clr TMP, TMP, TMP3 /* clear bit(s) in ssbr. */ 1212 1213 1214ASLOCAL(clear_dest_ssbr_bit) 1215 /* 1216 * There are various cases where an exception can leave the 1217 * destination register's bit in the SB set. 1218 * Examples: 1219 * misaligned or privilege exception on a LD or XMEM 1220 * DIV or DIVU by zero. 1221 * 1222 * I think that if the instruction is LD.D, then two bits must 1223 * be cleared. 1224 * 1225 * Even though there are a number of instructions/exception 1226 * combinations that could fire this code up, it's only required 1227 * to be run for the above cases. However, I don't think it'll 1228 * ever be a problem to run this in other cases (ST instructions, 1229 * for example), so I don't bother checking. If we had to check 1230 * for every possible instruction, this code would be much larger. 1231 * 1232 * The only checking, then, is to see if it's a LD.D or not. 1233 * 1234 * At the moment.... 1235 * r1: return address to calling exception handler 1236 * TMP: (possibly) revised ssbr 1237 * TMP2: free 1238 * TMP3: free 1239 */ 1240 1241 ldcr TMP3, EPSR /* going to check: user or system memory? */ 1242 ldcr TMP2, SXIP /* get the instruction's address */ 1243 bb1.n PSR_SUPERVISOR_MODE_BIT, TMP3, 2f 1244 clr TMP2, TMP2, 2<0> /* get rid of valid and error bits. */ 1245 1246 /* user space load here */ 1247#if ERRATA__XXX_USR 1248 NOP 1249 ld.usr TMP2, TMP2, %r0 /* get the instruction itself */ 1250 NOP 1251 NOP 1252 NOP 1253 br 3f 1254#else 1255 br.n 3f 1256 ld.usr TMP2, TMP2, %r0 /* get the instruction itself */ 1257#endif 1258 12592: /* system space load here */ 1260 ld TMP2, TMP2, %r0 /* get the instruction itself */ 1261 12623: /* now we have the instruction..... */ 1263 /* 1264 * Now see if it's a double load 1265 * There are three forms of double load [IMM16, scaled, unscaled], 1266 * which can be checked by matching against two templates: 1267 * -- 77776666555544443333222211110000 -- 1268 * if (((instruction & 11111100000000000000000000000000) == 1269 * 00010000000000000000000000000000) || 1270 * ((instruction & 11111100000000001111110011100000) == 1271 * 11110100000000000001000000000000)) 1272 * { 1273 * It's a load double, so 1274 * clear two SSBR bits. 1275 * } else { 1276 * It's not a load double. 1277 * Must be a load single, xmem, or st 1278 * Thus, clear one SSBR bit. 1279 * } 1280 */ 1281 /* check the first pattern for ld.d */ 1282 extu TMP3, TMP2, 16<16> /* get the upper 16 bits */ 1283 mask TMP3, TMP3, 0xfc00 /* apply the mask */ 1284 cmp TMP3, TMP3, 0x1000 /* if equal, it's a load double */ 1285 bb1 eq, TMP3, 2f 1286 1287 /* still could be -- check the second pattern for ld.d */ 1288 /* look at the upper 16 bits first */ 1289 extu TMP3, TMP2, 16<16> /* get the upper 16 bits */ 1290 mask TMP3, TMP3, 0xfc00 /* apply the mask */ 1291 cmp TMP3, TMP3, 0xf400 /* if equal, might be a load double */ 1292 bb1 ne, TMP3, 1f /* not equal, must be single */ 1293 1294 /* now look at the lower 16 bits */ 1295 extu TMP3, TMP2, 16<0> /* get the lower 16 bits */ 1296 mask TMP3, TMP3, 0xfce0 /* apply the mask */ 1297 cmp TMP3, TMP3, 0x1000 /* if equal, it's a load double */ 1298 bb1 eq, TMP3, 2f 1299 13001: /* misaligned single */ 1301 extu TMP2, TMP2, 5<21> /* get the destination register */ 1302 br.n 3f 1303 set TMP2, TMP2, 1<5> /* set size=1 */ 1304 13052: /* misaligned double */ 1306 extu TMP2, TMP2, 5<21> /* get the destination register */ 1307 set TMP2, TMP2, 1<6> /* set size=2 -- clear two bits */ 13083: 1309 jmp.n %r1 1310 clr TMP, TMP, TMP2 /* clear bit(s) in ssbr. */ 1311 1312ASLOCAL(m88100_setup_phase_two) 1313 /* 1314 * SR1: saved copy of exception-time register now holding FLAGS 1315 * SR2: free 1316 * SR3: saved TMP 1317 * r1: return address to calling exception handler 1318 * TMP: possibly revised SSBR 1319 * TMP2: free 1320 * TMP3: free 1321 * FLAGS: CPU status flags 1322 * r31: our exception frame 1323 * Valid in the exception frame: 1324 * Exception-time r1, r31, FLAGS. 1325 * Exception-time TMP2, TMP3. 1326 * Exception-time epsr, sfip, snip, sxip. 1327 * Exception number (EF_VECTOR). 1328 * Dmt0 1329 * Other data pipeline control registers, if appropriate. 1330 * FPU control registers, if appropriate. 1331 * Exception SR3, if appropriate. 1332 * 1333 * immediate goal: 1334 * restore the system to the exception-time state (except 1335 * SR3 will be OUR stack pointer) so that we may restart the FPU. 1336 */ 1337 1338 stcr TMP, SSBR /* done with SSBR, TMP now free */ 1339 RESTORE_TMP2(%r31) /* done with extra temp regs */ 1340 RESTORE_TMP3(%r31) /* done with extra temp regs */ 1341 1342 /* Get the current PSR and modify for the rte to enable the FPU */ 1343 ldcr TMP, PSR 1344 clr TMP, TMP, 1<PSR_FPU_DISABLE_BIT> /* enable the FPU */ 1345 clr TMP, TMP, 1<PSR_SHADOW_FREEZE_BIT> /* and shadowing */ 1346 stcr TMP, EPSR 1347 1348 /* the "+2" below is to set the VALID_BIT */ 1349 or.u TMP, %r0, %hi16(m88100_fpu_enable + 2) 1350 or TMP, TMP, %lo16(m88100_fpu_enable + 2) 1351 stcr TMP, SNIP 1352 addu TMP, TMP, 4 1353 stcr TMP, SFIP 1354 1355 set FLAGS, FLAGS, 1<FLAG_ENABLING_FPU> 1356 xcr FLAGS, FLAGS, SR1 1357 st %r1, %r31, EF_RET /* save the return address */ 1358 ld %r1, %r31, GENREG_OFF(1) /* get original r1 */ 1359 1360 xcr TMP, %r31, SR3 /* TMP now restored. R31 now saved in SR3 */ 1361 ld %r31, %r31, GENREG_OFF(31) /* get original r31 */ 1362 1363 /* 1364 * SR1: CPU flags 1365 * SR2: free 1366 * SR3: pointer to our exception frame (our stack pointer) 1367 * r1 through r31: original exception-time values 1368 * 1369 * Valid in the exception frame: 1370 * Exception-time FLAGS. 1371 * Exception-time epsr, sfip, snip, sxip. 1372 * Exception number (EF_VECTOR). 1373 * Dmt0 1374 * Other data pipeline control registers, if appropriate. 1375 * FPU control registers, if appropriate. 1376 * Exception SR3, if appropriate. 1377 * Held temporarily in the exception frame: 1378 * Return address to the calling exception handler. 1379 * 1380 * immediate goal: 1381 * Do an RTE to restart the fpu and jump to "fpu_enable" 1382 * Another exception (or exceptions) may be raised in 1383 * this, which is why FLAG_ENABLING_FPU is set in SR1. 1384 */ 1385 1386 RTE /* jumps to "m88100_fpu_enable" to enable the FPU. */ 1387 1388ASLOCAL(m88100_fpu_enable) 1389 FLUSH_PIPELINE 1390 xcr TMP, TMP, SR3 /* get E.F. pointer */ 1391 st %r30, TMP, GENREG_OFF(30) /* save previous r30, r31 */ 1392 st %r31, TMP, GENREG_OFF(31) /* save previous r30, r31 */ 1393 or %r31, TMP, %r0 /* transfer E.F. pointer to r31 */ 1394 ld TMP, %r31, EF_SR3 /* get previous SR3 */ 1395 1396 /* make sure that the FLAG_ENABLING_FPU bit is off */ 1397 xcr FLAGS,FLAGS,SR1 1398 clr FLAGS,FLAGS,1<FLAG_ENABLING_FPU> 1399 xcr FLAGS,FLAGS,SR1 1400 1401 xcr TMP, TMP, SR3 /* replace TMP, SR3 */ 1402 1403 /* now save all regs to the exception frame. */ 1404 st %r0, %r31, GENREG_OFF(0) 1405 st %r1, %r31, GENREG_OFF(1) 1406 st %r2, %r31, GENREG_OFF(2) 1407 st %r3, %r31, GENREG_OFF(3) 1408 st %r4, %r31, GENREG_OFF(4) 1409 st %r5, %r31, GENREG_OFF(5) 1410 st %r6, %r31, GENREG_OFF(6) 1411 st %r7, %r31, GENREG_OFF(7) 1412 st %r8, %r31, GENREG_OFF(8) 1413 st %r9, %r31, GENREG_OFF(9) 1414 st %r10, %r31, GENREG_OFF(10) 1415 st %r11, %r31, GENREG_OFF(11) 1416 st %r12, %r31, GENREG_OFF(12) 1417 st %r13, %r31, GENREG_OFF(13) 1418 st %r14, %r31, GENREG_OFF(14) 1419 st %r15, %r31, GENREG_OFF(15) 1420 st %r16, %r31, GENREG_OFF(16) 1421 st %r17, %r31, GENREG_OFF(17) 1422 st %r18, %r31, GENREG_OFF(18) 1423 st %r19, %r31, GENREG_OFF(19) 1424 st %r20, %r31, GENREG_OFF(20) 1425 st %r21, %r31, GENREG_OFF(21) 1426 st %r22, %r31, GENREG_OFF(22) 1427 st %r23, %r31, GENREG_OFF(23) 1428 st %r24, %r31, GENREG_OFF(24) 1429 st %r25, %r31, GENREG_OFF(25) 1430 st %r26, %r31, GENREG_OFF(26) 1431 st %r27, %r31, GENREG_OFF(27) 1432 st %r28, %r31, GENREG_OFF(28) 1433 st %r29, %r31, GENREG_OFF(29) 1434 1435 /* 1436 * SR1: free 1437 * SR2: free 1438 * SR3: previous exception-time SR3 1439 * r1: return address to the calling exception handler 1440 * r2 through r30: free 1441 * r31: our exception frame 1442 * 1443 * Valid in the exception frame: 1444 * Exception-time r0 through r31. 1445 * Exception-time FLAGS. 1446 * Exception-time epsr, sfip, snip, sxip. 1447 * Exception number (EF_VECTOR). 1448 * Dmt0 1449 * Other data pipeline control registers, if appropriate. 1450 * FPU control registers, if appropriate. 1451 * Exception SR3, if appropriate. 1452 * 1453 * immediate goal: 1454 * Pick up a stack if we came in from user mode. 1455 * Put a copy of the exception frame pointer into r30 1456 * Bump the stack a doubleword and write the exception frame pointer. 1457 * If not an interrupt exception, turn on interrupts and service any 1458 * outstanding data access exceptions. 1459 * Return to calling exception handler to service the exception. 1460 */ 1461 1462 /* 1463 * If it's not the interrupt exception, enable interrupts and 1464 * take care of any data access exceptions...... 1465 */ 1466 or %r30, %r0, %r31 /* get a copy of the e.f. pointer */ 1467 ld %r6, %r31, EF_EPSR 1468 bb1 PSR_SUPERVISOR_MODE_BIT, %r6, 1f /* if in kernel mode */ 1469 1470 ldcr %r31, CPU 1471 ld %r31, %r31, CI_CURPCB 1472 addu %r31, %r31, USPACE /* point at proper end */ 14731: 1474 1475 /* get and save IPL */ 1476 bsr getipl 1477 st %r2, %r30, EF_MASK 1478 1479 /* 1480 * here - r30 holds a pointer to the exception frame. 1481 * r31 is a pointer to the kernel stack/interrupt stack. 1482 */ 1483 subu %r31, %r31, 8 /* make some breathing space */ 1484 st %r30, %r31, 0 /* store frame pointer on the stack */ 1485#ifdef DDB 1486 st %r30, %r31, 4 /* store it for the debugger to recognize */ 1487#endif 1488 1489 ld %r6, %r30, EF_EPSR 1490 ld %r2, %r30, EF_VECTOR 1491 bcnd.n eq0, %r2, 8f /* error exception */ 1492 ld %r14, %r30, EF_RET 1493 1494 /* 1495 * Do not process possible data exceptions here if this is an interrupt. 1496 * Instead, the interrupt handler will take care of this by itself. 1497 */ 1498 cmp %r3, %r2, 1 /* is an interrupt? */ 1499 bb1.n eq, %r3, 8f /* skip if so */ 1500 1501#ifdef DDB 1502 cmp %r3, %r2, 130 /* DDB break exception */ 1503 bb1.n eq, %r3, 8f 1504 cmp %r3, %r2, 132 /* DDB entry exception */ 1505 bb1 eq, %r3, 8f 1506#else 1507 NOP 1508#endif 1509 1510 /* turn interrupts back on unless they were not enabled when the 1511 trap occurred */ 1512 bb1.n PSR_INTERRUPT_DISABLE_BIT, %r6, 7f 1513 ld %r3, %r30, EF_DMT0 1514 1515 ldcr %r2, PSR 1516 clr %r2, %r2, 1<PSR_INTERRUPT_DISABLE_BIT> 1517 stcr %r2, PSR 1518 FLUSH_PIPELINE 15197: 1520 /* service any outstanding data pipeline stuff */ 1521 bb0 DMT_VALID_BIT, %r3, 8f 1522 1523 /* 1524 * r30 can be clobbered by calls. So stuff its value into a preserved 1525 * register, say r15. R14 is in use (see return_to_... below). 1526 */ 1527 or %r15, %r0, %r30 1528 CALL(m88100_trap, T_DATAFLT, %r15) 1529 or %r30, %r0, %r15 1530 15318: 1532 jmp %r14 /* loaded above */ 1533#endif /* M88100 */ 1534 1535#ifdef M88110 1536/* 1537 * 88110 exception handlers 1538 */ 1539 1540/* unknown exception handler */ 1541GLOBAL(m88110_unknown_handler) 1542 PREP88110("unknown", 0,) 1543 or %r2, %r0, T_UNKNOWNFLT 1544 or %r3, %r0, %r30 1545 XCALL(m88110_trap, check_ast) 1546 1547/* interrupt exception handler */ 1548GLOBAL(m88110_interrupt_handler) 1549 PREP88110("interrupt", 1,) 1550 or %r2, %r0, %r30 1551 XCALL(interrupt, check_ast) 1552 1553/* instruction access exception handler */ 1554GLOBAL(m88110_instruction_access_handler) 1555 PREP88110("inst", 2,) 1556 or %r2, %r0, T_INSTFLT 1557 or %r3, %r0, %r30 1558 XCALL(m88110_trap, check_ast) 1559/* 1560 * data access exception handler -- 1561 * See badaddr() below for info about Data_Precheck. 1562 */ 1563GLOBAL(m88110_data_exception_handler_bootstrap) 1564 PREP88110("data", 3, M88110_Data_Precheck) 1565 or %r2, %r0, T_DATAFLT 1566 or %r3, %r0, %r30 1567 XCALL(m88110_trap, check_ast) 1568GLOBAL(m88110_data_exception_handler) 1569 PREP88110("data", 3,) 1570 or %r2, %r0, T_DATAFLT 1571 or %r3, %r0, %r30 1572 XCALL(m88110_trap, check_ast) 1573 1574/* misaligned access exception handler */ 1575GLOBAL(m88110_misaligned_handler) 1576 PREP88110("misalign", 4,) 1577 or %r2, %r0, T_MISALGNFLT 1578 or %r3, %r0, %r30 1579 XCALL(m88110_trap, check_ast) 1580 1581/* unimplemented opcode exception handler */ 1582GLOBAL(m88110_unimplemented_handler) 1583 PREP88110("unimp", 5,) 1584 or %r2, %r0, T_ILLFLT 1585 or %r3, %r0, %r30 1586 XCALL(m88110_trap, check_ast) 1587 1588/* privilege exception handler */ 1589GLOBAL(m88110_privilege_handler) 1590 PREP88110("privilege", 6,) 1591 or %r2, %r0, T_PRIVINFLT 1592 or %r3, %r0, %r30 1593 XCALL(m88110_trap, check_ast) 1594 1595/* bounds checking exception handler */ 1596GLOBAL(m88110_bounds_handler) 1597 PREP88110("bounds", 7,) 1598 or %r2, %r0, T_BNDFLT 1599 or %r3, %r0, %r30 1600 XCALL(m88110_trap, check_ast) 1601 1602/* integer divide-by-zero exception handler */ 1603GLOBAL(m88110_divide_handler) 1604 PREP88110("divide", 8,) 1605 or %r2, %r0, T_ZERODIV 1606 or %r3, %r0, %r30 1607 XCALL(m88110_trap, check_ast) 1608 1609/* integer overflow exception handler */ 1610GLOBAL(m88110_overflow_handler) 1611 PREP88110("overflow", 9,) 1612 or %r2, %r0, T_OVFFLT 1613 or %r3, %r0, %r30 1614 XCALL(m88110_trap, check_ast) 1615 1616/* Floating-point precise handler */ 1617GLOBAL(m88110_fpu_handler) 1618 PREP88110("FPU", 114,) 1619 or %r2, %r0, T_FPEPFLT 1620 or %r3, %r0, %r30 1621 XCALL(m88110_trap, check_ast) 1622 1623/* non-maskable interrupt handler (IPIs, ABORT button) */ 1624GLOBAL(m88110_nonmaskable) 1625 PREP88110("NMI", 11,) 1626 or %r2, %r0, %r30 1627 XCALL(nmi, nmi_return) 1628 1629/* software walk data MMU read miss handler */ 1630GLOBAL(m88110_data_read_miss) 1631 PREP88110("88110 data read miss", 12,) 1632 or %r2, %r0, T_110_DRM 1633 or %r3, %r0, %r30 1634 XCALL(m88110_trap, check_ast) 1635 1636/* software walk data MMU write miss handler */ 1637GLOBAL(m88110_data_write_miss) 1638 PREP88110("88110 data write miss", 13,) 1639 or %r2, %r0, T_110_DWM 1640 or %r3, %r0, %r30 1641 XCALL(m88110_trap, check_ast) 1642 1643/* software walk inst MMU ATC miss handler */ 1644GLOBAL(m88110_inst_atc_miss) 1645 PREP88110("88110 inst ATC miss", 14,) 1646 or %r2, %r0, T_110_IAM 1647 or %r3, %r0, %r30 1648 XCALL(m88110_trap, check_ast) 1649 1650/* trap 450: system calls */ 1651GLOBAL(m88110_syscall_handler) 1652 PREP88110("syscall", 450,) 1653 ld %r2, %r30, GENREG_OFF(13) 1654 or %r3, %r0, %r30 1655 XCALL(m88110_syscall, check_ast) 1656 1657/* trap 451: cache flush (necessary for trampolines) */ 1658GLOBAL(m88110_cache_flush_handler) 1659 PREP88110("cache_flush", 451,) 1660 or %r2, %r0, %r30 1661 XCALL(cache_flush, check_ast) 1662 1663GLOBAL(m88110_sigsys) 1664 PREP88110("sigsys", 501,) 1665 or %r2, %r0, T_SIGSYS 1666 or %r3, %r0, %r30 1667 XCALL(m88110_trap, check_ast) 1668 1669GLOBAL(m88110_stepbpt) 1670 PREP88110("stepbpt", 504,) 1671 or %r2, %r0, T_STEPBPT 1672 or %r3, %r0, %r30 1673 XCALL(m88110_trap, check_ast) 1674 1675GLOBAL(m88110_userbpt) 1676 PREP88110("userbpt", 511,) 1677 or %r2, %r0, T_USERBPT 1678 or %r3, %r0, %r30 1679 XCALL(m88110_trap, check_ast) 1680 1681#ifdef DDB 1682GLOBAL(m88110_break) 1683 PREP88110("break", 130,) 1684 or %r2, %r0, T_KDB_BREAK 1685 or %r3, %r0, %r30 1686 XCALL(m88110_trap, check_ast) 1687 1688GLOBAL(m88110_trace) 1689 PREP88110("trace", 131,) 1690 or %r2, %r0, T_KDB_TRACE 1691 or %r3, %r0, %r30 1692 XCALL(m88110_trap, check_ast) 1693 1694GLOBAL(m88110_entry) 1695 PREP88110("kdb", 132,) 1696 or %r2, %r0, T_KDB_ENTRY 1697 or %r3, %r0, %r30 1698 XCALL(m88110_trap, check_ast) 1699#endif 1700 1701/* 1702 * The error exception and reset exception handler. 1703 * 1704 * The error exception is raised when any other non-trap exception is raised 1705 * while shadowing is off. This is Bad News. 1706 * 1707 * The reset exception is raised when the RST signal is asserted (machine 1708 * is reset), the value of VBR is changed after exceptions are enabled, 1709 * or when a jmp, br/bsr to addr 0 (accidents do happen :-) 1710 * Upon a real reset, VBR is set to zero (0), so code must be at addr 0 1711 * to handle it!!! 1712 * 1713 * The shadow registers are not valid in this case (shadowing was off, if this 1714 * was an error exception, and may not be on, if this was a reset exception). 1715 * R1-R31 may be interesting though, so we'll save them. 1716 * 1717 * We'll not worry about trashing r26-29 here, 1718 * since they aren't generally used. 1719 */ 1720GLOBAL(m88110_error_handler) 1721 or %r29, %r0, 10 1722 br 1f 1723GLOBAL(m88110_reset_handler) 1724 or %r29, %r0, 0 17251: 1726 or %r26, %r0, %r31 /* save old stack */ 1727 or.u %r31, %r0, %hi16(initstack_end) 1728 or %r31, %r31, %lo16(initstack_end) 1729 1730#ifdef DEBUG 1731 /* zero the stack, so we'll know what we're lookin' at */ 1732 or.u %r27, %r0, %hi16(initstack) 1733 or %r27, %r27, %lo16(initstack) 17341: cmp %r28, %r27, %r31 1735 bb1 ge, %r28, 2f /* branch if at the end of the stack */ 1736 st %r0, %r0, %r27 1737 addu %r27, %r27, 4 /* bump up */ 1738 br 1b 17392: /* stack has been cleared */ 1740#endif 1741 1742 /* ensure that stack is 8-byte aligned */ 1743 clr %r31, %r31, 3<0> /* round down to 8-byte boundary */ 1744 1745 /* create exception frame on stack */ 1746 subu %r31, %r31, TRAPFRAME_SIZEOF /* r31 now our E.F. */ 1747 1748 /* save old R31 and other R registers */ 1749 st.d %r0, %r31, GENREG_OFF(0) 1750 st.d %r2, %r31, GENREG_OFF(2) 1751 st.d %r4, %r31, GENREG_OFF(4) 1752 st.d %r6, %r31, GENREG_OFF(6) 1753 st.d %r8, %r31, GENREG_OFF(8) 1754 st.d %r10, %r31, GENREG_OFF(10) 1755 st.d %r12, %r31, GENREG_OFF(12) 1756 st.d %r14, %r31, GENREG_OFF(14) 1757 st.d %r16, %r31, GENREG_OFF(16) 1758 st.d %r18, %r31, GENREG_OFF(18) 1759 st.d %r20, %r31, GENREG_OFF(20) 1760 st.d %r22, %r31, GENREG_OFF(22) 1761 st.d %r24, %r31, GENREG_OFF(24) 1762 st %r30, %r31, GENREG_OFF(30) 1763 st %r26, %r31, GENREG_OFF(31) 1764 1765 /* vector is put in SRO (either 0 or 10 at this point) */ 1766 st %r29, %r31, EF_VECTOR 1767 1768 /* save shadow registers (are OLD if error_handler, though) */ 1769 ldcr %r10, EPSR 1770 st %r10, %r31, EF_EPSR 1771 ldcr %r10, EXIP 1772 st %r10, %r31, EF_EXIP 1773 ldcr %r10, ENIP 1774 st %r10, %r31, EF_ENIP 1775 ldcr %r10, DSR 1776 st %r10, %r31, EF_DSR 1777 ldcr %r10, DLAR 1778 st %r10, %r31, EF_DLAR 1779 ldcr %r10, DPAR 1780 st %r10, %r31, EF_DPAR 1781 ldcr %r10, ISR 1782 st %r10, %r31, EF_ISR 1783 ldcr %r10, ILAR 1784 st %r10, %r31, EF_ILAR 1785 ldcr %r10, IPAR 1786 st %r10, %r31, EF_IPAR 1787 ldcr %r10, SR1 1788 st %r10, %r31, EF_FLAGS 1789 1790 /* shove sr2 into EF_FPLS1 */ 1791 ldcr %r10, SR2 1792 st %r10, %r31, EF_FPLS1 1793 1794 /* shove sr3 into EF_FPHS2 */ 1795 ldcr %r10, SR3 1796 st %r10, %r31, EF_FPHS2 1797 1798 /* 1799 * Cheap way to enable FPU and start shadowing again. 1800 */ 1801 ldcr %r10, PSR 1802 clr %r10, %r10, 1<PSR_FPU_DISABLE_BIT> /* enable the FPU */ 1803 clr %r10, %r10, 1<PSR_SHADOW_FREEZE_BIT> /* and shadowing */ 1804 stcr %r10, PSR 1805 FLUSH_PIPELINE 1806 1807 /* put pointer to regs into r30... r31 will become a simple stack */ 1808 or %r30, %r31, %r0 1809 1810 subu %r31, %r31, 0x10 /* make some breathing space */ 1811 st %r30, %r31, 0x0c /* store frame pointer on the stack */ 1812#ifdef DDB 1813 st %r30, %r31, 0x08 /* store again for the debugger to recognize */ 1814 or.u %r20, %r0, %hi16(0x87654321) 1815 or %r20, %r20, %lo16(0x87654321) 1816 st %r20, %r31, 0x04 1817 st %r20, %r31, 0x00 1818#endif 1819 1820 or %r2, %r0, %r30 1821 bsr error_fatal 1822 1823 /* turn interrupts back on */ 1824 ldcr %r1, PSR 1825 clr %r1, %r1, 1<PSR_INTERRUPT_DISABLE_BIT> 1826 stcr %r1, PSR 1827 FLUSH_PIPELINE 1828 18291: 1830 br 1b 1831 /* NOTREACHED */ 1832 1833/* 1834 * 88110 exception handling setup 1835 * 1836 * This is much simpler than for 88100, because all exception are 1837 * precise. Therefore, when reenabling shadowing, we do not risk 1838 * getting new exceptions caught by the execution pipeline and not 1839 * reported yet. 1840 * 1841 * However, as soon as shadow freezing is over, we can receive a 1842 * non-maskable interrupt at any time. The code below will cope with 1843 * this, as long as the stack pointer (r31) is valid in the kernel 1844 * all the time shadowing is enabled. 1845 * 1846 * Thus, unlike the 88100 code, we setup both the exception frame 1847 * (in r30) and the exception stack (in r31) as early as possible. 1848 */ 1849 1850ASLOCAL(m88110_setup_phase_one) 1851 /* 1852 * SR1: saved copy of exception-time register now holding FLAGS 1853 * SR2: saved copy of exception-time r1 1854 * SR3: free 1855 * r1: return address to calling exception handler 1856 * FLAGS: CPU status flags 1857 * 1858 * immediate goal: 1859 * Find out where to put the exception frame, and which 1860 * stack to use. 1861 */ 1862 1863 NOP 1864 xcr %r1, %r1, SR2 /* recover exception-time r1 */ 1865 NOP 1866 NOP 1867 NOP 1868 1869 /* 1870 * If we were in the kernel when the exception occurred, we have 1871 * a valid stack. Keep using it, and build the frame on it. 1872 * 1873 * Note that if this exception is an NMI, we might be currently 1874 * switching processes, and curpcb and curproc won't match. It 1875 * is nevertheless safe to use curpcb, since nmi are processed 1876 * with interrupts disabled, and we won't check for AST or soft 1877 * interrupts before returning to the cpu_switchto kernel code. 1878 */ 1879 bb1 FLAG_FROM_KERNEL, FLAGS, m88110_kernel_stack 1880 1881 /* 1882 * Otherwise, this is an exception in user mode, we'll use the PCB 1883 * for the exception frame and the top of the PCB as the stack. 1884 */ 1885 1886 /* compute frame address: in PCB */ 1887 stcr %r30, SR3 /* save r30, now free */ 1888 ldcr %r30, CPU 1889 ld %r30, %r30, CI_CURPCB 1890 addu %r30, %r30, PCB_USER_STATE /* point to user save area */ 1891 1892 /* save a few registers before we lose them*/ 1893 st %r1, %r30, GENREG_OFF(1) /* save prev. r1 (now free)*/ 1894 ldcr %r1, SR3 /* save previous r30 */ 1895 st %r31, %r30, GENREG_OFF(31) 1896 st %r1, %r30, GENREG_OFF(30) 1897 1898 /* compute stack address: top of U area */ 1899 ldcr %r1, CPU 1900 ld %r31, %r1, CI_CURPCB 1901 addu %r31, %r31, USPACE 1902 1903 br m88110_have_stack 1904 1905ASLOCAL(m88110_kernel_stack) /* Exception in kernel mode */ 1906 1907 /* compute stack and frame address: allocate them on current stack */ 1908 subu %r31, %r31, TRAPFRAME_SIZEOF /* r31 now our E.F. */ 1909 1910 /* save a few registers before we lose them */ 1911 st %r1, %r31, GENREG_OFF(1) /* save prev. r1 (now free) */ 1912 addu %r1, %r31, TRAPFRAME_SIZEOF /* save previous r31 */ 1913 st %r30, %r31, GENREG_OFF(30) 1914 st %r1, %r31, GENREG_OFF(31) 1915 1916 /* frame = stack */ 1917 or %r30, %r31, %r0 1918 1919 /* FALLTHROUGH */ 1920 1921ASLOCAL(m88110_have_stack) 1922 /* 1923 * SR1: saved copy of exception-time register now holding FLAGS 1924 * SR2: return address to the calling exception handler 1925 * SR3: free 1926 * r1: free 1927 * FLAGS: CPU status flags 1928 * r30: incomplete exception frame 1929 * r31: exception stack 1930 * Valid in the exception frame: 1931 * Exception-time r1, r30, r31, FLAGS. 1932 */ 1933 1934 stcr TMP, SR3 /* free up TMP, TMP2, TMP3 */ 1935 SAVE_TMP2(%r30) 1936 SAVE_TMP3(%r30) 1937 1938 /* save some exception-time registers to the exception frame */ 1939 st FLAGS,%r30, EF_FLAGS /* save flags */ 1940 1941 ldcr TMP, EPSR 1942 st TMP, %r30, EF_EPSR 1943 ldcr TMP2, EXIP 1944 ldcr TMP3, ENIP 1945 st TMP2, %r30, EF_EXIP 1946 st TMP3, %r30, EF_ENIP 1947 1948 /* get and store the cpu_info pointer */ 1949 ldcr TMP, CPU 1950 st TMP, %r30, EF_CPU 1951 1952 /* 1953 * Save and clear fault status registers. 1954 */ 1955 ldcr TMP, ISR 1956 st TMP, %r30, EF_ISR 1957 bcnd eq0, TMP, 1f 1958 ldcr TMP2, ILAR 1959 ldcr TMP3, IPAR 1960 st TMP2, %r30, EF_ILAR 1961 st TMP3, %r30, EF_IPAR 1962 ldcr TMP, ISAP 1963 ldcr TMP2, IUAP 1964 st TMP, %r30, EF_ISAP 1965 st TMP2, %r30, EF_IUAP 1966 stcr %r0, ISR 19671: 1968 ldcr TMP, DSR 1969 st TMP, %r30, EF_DSR 1970 bcnd eq0, TMP, 1f 1971 ldcr TMP2, DLAR 1972 ldcr TMP3, DPAR 1973 st TMP2, %r30, EF_DLAR 1974 st TMP3, %r30, EF_DPAR 1975 ldcr TMP, DSAP 1976 ldcr TMP2, DUAP 1977 st TMP, %r30, EF_DSAP 1978 st TMP2, %r30, EF_DUAP 1979 stcr %r0, DSR 19801: 1981 ldcr %r1, SR2 1982 jmp %r1 1983 1984ASLOCAL(m88110_setup_phase_two) 1985 /* 1986 * SR1: saved copy of exception-time register now holding FLAGS 1987 * SR2: free 1988 * SR3: saved TMP 1989 * r1: return address to calling exception handler 1990 * TMP2: free 1991 * TMP3: free 1992 * FLAGS: CPU status flags 1993 * r30: incomplete exception frame 1994 * r31: exception stack 1995 * Valid in the exception frame: 1996 * Exception-time r1, r30, r31, FLAGS. 1997 * Exception-time TMP2, TMP3. 1998 * Exception-time epsr, enip, exip. 1999 * Exception number (EF_VECTOR). 2000 * 2001 * immediate goal: 2002 * restore the system to the exception-time state. 2003 */ 2004 2005 RESTORE_TMP2(%r30) /* done with extra temp regs */ 2006 RESTORE_TMP3(%r30) /* done with extra temp regs */ 2007 2008 ldcr TMP, PSR 2009 clr TMP, TMP, 1<PSR_SHADOW_FREEZE_BIT> /* enable shadowing */ 2010 stcr TMP, EPSR 2011 2012 or.u TMP, %r0, %hi16(m88110_shadow_enable) 2013 or TMP, TMP, %lo16(m88110_shadow_enable) 2014 stcr TMP, EXIP 2015 2016 xcr FLAGS,FLAGS,SR1 2017 st %r1, %r30, EF_RET /* save the return address */ 2018 2019 xcr TMP, %r31, SR3 /* TMP now restored. R31 now saved in SR3 */ 2020 2021 /* 2022 * SR1: CPU flags 2023 * SR2: free 2024 * SR3: pointer to our exception frame (our stack pointer) 2025 * r2 through r29: original exception-time values 2026 * r30: exception frame 2027 * r31: exception stack 2028 * 2029 * Valid in the exception frame: 2030 * Exception-time r1, r30, r31, FLAGS. 2031 * Exception-time epsr, sfip, enip, exip. 2032 * Exception number (EF_VECTOR). 2033 * DSR/ISR, fault registers, if appropriate. 2034 * Held temporarily in the exception frame: 2035 * Return address to the calling exception handler. 2036 * 2037 * immediate goal: 2038 * Do an RTE to unfreeze the shadow registers. 2039 * Another exception (NMI) may be raised in this. 2040 */ 2041 RTE /* jumps to "m88110_shadow_enable" */ 2042 2043ASLOCAL(m88110_shadow_enable) 2044 FLUSH_PIPELINE /* XXX necessary? */ 2045 2046 /* now save all missing regs to the exception frame. */ 2047 st %r0, %r30, GENREG_OFF(0) 2048 st %r2, %r30, GENREG_OFF(2) 2049 st %r3, %r30, GENREG_OFF(3) 2050 st %r4, %r30, GENREG_OFF(4) 2051 st %r5, %r30, GENREG_OFF(5) 2052 st %r6, %r30, GENREG_OFF(6) 2053 st %r7, %r30, GENREG_OFF(7) 2054 st %r8, %r30, GENREG_OFF(8) 2055 st %r9, %r30, GENREG_OFF(9) 2056 st %r10, %r30, GENREG_OFF(10) 2057 st %r11, %r30, GENREG_OFF(11) 2058 st %r12, %r30, GENREG_OFF(12) 2059 st %r13, %r30, GENREG_OFF(13) 2060 st %r14, %r30, GENREG_OFF(14) 2061 st %r15, %r30, GENREG_OFF(15) 2062 st %r16, %r30, GENREG_OFF(16) 2063 st %r17, %r30, GENREG_OFF(17) 2064 st %r18, %r30, GENREG_OFF(18) 2065 st %r19, %r30, GENREG_OFF(19) 2066 st %r20, %r30, GENREG_OFF(20) 2067 st %r21, %r30, GENREG_OFF(21) 2068 st %r22, %r30, GENREG_OFF(22) 2069 st %r23, %r30, GENREG_OFF(23) 2070 st %r24, %r30, GENREG_OFF(24) 2071 st %r25, %r30, GENREG_OFF(25) 2072 st %r26, %r30, GENREG_OFF(26) 2073 st %r27, %r30, GENREG_OFF(27) 2074 st %r28, %r30, GENREG_OFF(28) 2075 st %r29, %r30, GENREG_OFF(29) 2076 2077 /* 2078 * SR1: free 2079 * SR2: free 2080 * SR3: free 2081 * r1 through r29: free 2082 * r30: exception frame 2083 * r31: exception stack 2084 * 2085 * Valid in the exception frame: 2086 * Exception-time r0 through r31. 2087 * Exception-time FLAGS. 2088 * Exception-time epsr, enip, exip. 2089 * Exception number (EF_VECTOR). 2090 * Return value (EF_RET). 2091 * DSR/ISR, fault registers, if appropriate. 2092 * 2093 * immediate goal: 2094 * Bump the stack a doubleword and write the exception frame pointer. 2095 * If not an interrupt exception or an NMI, turn on interrupts. 2096 * Return to calling exception handler to service the exception. 2097 */ 2098 2099 /* get and save IPL */ 2100 bsr getipl 2101 st %r2, %r30, EF_MASK 2102 2103 subu %r31, %r31, 8 /* make some breathing space */ 2104 st %r30, %r31, 0 /* store frame pointer on the stack */ 2105#ifdef DDB 2106 st %r30, %r31, 4 /* store it again for the debugger */ 2107#endif 2108 2109 ld %r6, %r30, EF_EPSR 2110 ld %r14, %r30, EF_RET 2111 2112 /* don't turn interrupts back on unless they were enabled when the 2113 trap occurred */ 2114 bb1 PSR_INTERRUPT_DISABLE_BIT, %r6, 8f 2115 2116 ld %r2, %r30, EF_VECTOR 2117 bcnd eq0, %r2, 8f 2118 cmp %r3, %r2, 1 /* is this an interrupt? */ 2119 bb1 eq, %r3, 8f 2120 cmp %r3, %r2, 11 /* or NMI? */ 2121 bb1 eq, %r3, 8f 2122 2123#ifdef DDB 2124 cmp %r3, %r2, 130 /* DDB break exception */ 2125 bb1 eq, %r3, 8f 2126 cmp %r3, %r2, 132 /* DDB entry exception */ 2127 bb1 eq, %r3, 8f 2128#endif 2129 2130 ldcr %r2, PSR 2131 clr %r2, %r2, 1<PSR_INTERRUPT_DISABLE_BIT> 2132 stcr %r2, PSR 2133 FLUSH_PIPELINE 2134 21358: 2136 jmp %r14 /* loaded above */ 2137#endif /* M88110 */ 2138 2139 .text 2140 2141#define FPTR %r14 2142 2143ASGLOBAL(check_ast) 2144 /* 2145 * Regs r1-r30 are free. r31 is pointing at the word 2146 * on the kernel stack where our pointer to the exception frame 2147 * it stored. Reload it now. 2148 * 2149 * We load it into r14 since it is preserved across function 2150 * calls, and we may have to call some routines from within here. 2151 * 2152 * Control is transferred here from obvious places in this file. 2153 */ 2154 ld FPTR, %r31, 0 /* grab exception frame pointer */ 2155 2156 /* 2157 * If the saved ipl is 0, then call spl0() to process soft 2158 * interrupts. And if returning to userland, look for ASTs. 2159 */ 2160 2161 /* do not service AST and soft interrupts if interrupts were disabled */ 2162 ld %r2, FPTR, EF_EPSR 2163 bb1 PSR_INTERRUPT_DISABLE_BIT, %r2, ast_done 2164 /* ...or we were not at spl0 */ 2165 ld %r2, FPTR, EF_MASK 2166 bcnd ne0, %r2, ast_done 2167 2168#ifdef MULTIPROCESSOR 2169 /* 2170 * Check for IPI soft interrupt 2171 */ 2172 ldcr %r3, CPU 2173 or %r15, %r0, %r0 2174 addu %r3, %r3, CI_SOFTIPI_CB 2175 xmem %r15, %r3, %r0 2176 bcnd eq0, %r15, do_softint 2177 2178 bsr.n setipl 2179 or %r2, %r0, IPL_NONE 2180 2181 jsr %r15 2182ASLOCAL(do_softint) 2183#endif 2184 2185 /* 2186 * Process soft interrupts, if any. 2187 */ 2188 bsr spl0 2189 2190 /* do not service AST if not returning to user mode */ 2191 ld %r2, FPTR, EF_EPSR 2192 bb1 PSR_SUPERVISOR_MODE_BIT, %r2, ast_done 21931: 2194 ldcr %r2, CPU 2195 ld %r3, %r2, CI_CURPROC 2196 ld %r2, %r3, P_ASTPENDING 2197 bcnd eq0, %r2, ast_done 2198 2199 bsr.n ast 2200 or %r2, %r0, FPTR 2201 2202 br 1b 2203 2204/* 2205 * void proc_trampoline() 2206 * 2207 * When a process setup by cpu_fork() resumes, it will find itself in 2208 * proc_trampoline, with r14 and r15 referring to a function and its 2209 * argument. proc_trampoline will call the function, and return to userland. 2210 */ 2211 2212ENTRY(proc_trampoline) 2213 bsr proc_trampoline_mi 2214 2215 jsr.n %r14 2216 or %r2, %r15, 0 /* arg */ 2217 2218/* 2219 * Load FPTR with a pointer to the trap frame for the current proc and 2220 * continue near the end of check_ast, bypassing soft interrupts and AST 2221 * checks, to load all the registers and do an RTE. 2222 */ 2223 2224 ldcr %r3, CPU 2225 ld %r2, %r3, CI_CURPROC 2226 2227 ld FPTR, %r2, P_ADDR /* p->p_addr */ 2228 addu FPTR, FPTR, PCB_USER_STATE /* p->p_addr.u_pcb.user_state */ 2229 2230 /* FALLTHROUGH */ 2231 2232ASGLOBAL(ast_done) 2233 /* disable interrupts */ 2234 ldcr %r1, PSR 2235 set %r1, %r1, 1<PSR_INTERRUPT_DISABLE_BIT> 2236 stcr %r1, PSR 2237 FLUSH_PIPELINE 2238 2239 /* now ready to return....*/ 2240 bsr.n setipl 2241 ld %r2, FPTR, EF_MASK /* get pre-exception ipl */ 2242 2243#if defined(M88100) && defined(M88110) 2244 ldcr %r2, PID 2245 extu %r3, %r2, 8<8> 2246 bcnd ne0, %r3, m88110_user_rte 2247 /* FALLTHROUGH */ 2248#endif 2249 2250#ifdef M88100 2251ASGLOBAL(m88100_user_rte) 2252 /* 2253 * Transfer the frame pointer to r31, since we no longer need a stack. 2254 * No page faults here, and interrupts are disabled. 2255 */ 2256 or %r31, %r0, FPTR 2257 2258 /* restore r1 later */ 2259 ld %r2, %r31, GENREG_OFF(2) 2260 ld %r3, %r31, GENREG_OFF(3) 2261 ld %r4, %r31, GENREG_OFF(4) 2262 ld %r5, %r31, GENREG_OFF(5) 2263 ld %r6, %r31, GENREG_OFF(6) 2264 ld %r7, %r31, GENREG_OFF(7) 2265 ld %r8, %r31, GENREG_OFF(8) 2266 ld %r9, %r31, GENREG_OFF(9) 2267 ld %r10, %r31, GENREG_OFF(10) 2268 ld %r11, %r31, GENREG_OFF(11) 2269 ld %r12, %r31, GENREG_OFF(12) 2270 ld %r13, %r31, GENREG_OFF(13) 2271 ld %r14, %r31, GENREG_OFF(14) 2272 ld %r15, %r31, GENREG_OFF(15) 2273 ld %r16, %r31, GENREG_OFF(16) 2274 ld %r17, %r31, GENREG_OFF(17) 2275 ld %r18, %r31, GENREG_OFF(18) 2276 ld %r19, %r31, GENREG_OFF(19) 2277 ld %r20, %r31, GENREG_OFF(20) 2278 ld %r21, %r31, GENREG_OFF(21) 2279 ld %r22, %r31, GENREG_OFF(22) 2280 ld %r23, %r31, GENREG_OFF(23) 2281 ld %r24, %r31, GENREG_OFF(24) 2282 ld %r25, %r31, GENREG_OFF(25) 2283 ld %r26, %r31, GENREG_OFF(26) 2284 ld %r27, %r31, GENREG_OFF(27) 2285 ld %r28, %r31, GENREG_OFF(28) 2286 ld %r29, %r31, GENREG_OFF(29) 2287 /* restore r1, r30, r31 later */ 2288 2289 /* disable shadowing */ 2290 ldcr %r1, PSR 2291 set %r1, %r1, 1<PSR_SHADOW_FREEZE_BIT> 2292 stcr %r1, PSR 2293 FLUSH_PIPELINE 2294 2295 /* reload the control regs*/ 2296 /* 2297 * RTE will cause execution to continue first with the 2298 * instruction pointed to by the NIP and then the FIP; 2299 * it is not necessary to restore XIP. 2300 */ 2301 stcr %r0, SSBR 2302 ld %r30, %r31, EF_SNIP 2303 ld %r1, %r31, EF_SFIP 2304 stcr %r30, SNIP 2305 stcr %r1, SFIP 2306 2307 ld %r30, %r31, EF_EPSR 2308 stcr %r30, EPSR 2309 2310 /* Now restore r1, r30, and r31 */ 2311 ld %r1, %r31, GENREG_OFF(1) 2312 ld %r30, %r31, GENREG_OFF(30) 2313 ld %r31, %r31, GENREG_OFF(31) 2314 2315 RTE 2316#endif 2317 2318#ifdef M88110 2319ASGLOBAL(m88110_user_rte) 2320 /* 2321 * Disable shadowing. This used to be done after all the registers 2322 * from the E.F. have been restored, but on 88110 we may receive 2323 * an NMI anytime, unless shadowing is frozen, and we rely on r31 2324 * being valid. 2325 */ 2326 ldcr %r1, PSR 2327 set %r1, %r1, 1<PSR_SHADOW_FREEZE_BIT> 2328 stcr %r1, PSR 2329 FLUSH_PIPELINE 2330 2331ASLOCAL(m88110_restore) 2332 /* 2333 * Transfer the frame pointer to r31, since we no longer need a stack. 2334 * No page faults here, and interrupts are disabled. 2335 */ 2336 or %r31, %r0, FPTR 2337 /* restore r1 later */ 2338 ld %r2, %r31, GENREG_OFF(2) 2339 ld %r3, %r31, GENREG_OFF(3) 2340 ld %r4, %r31, GENREG_OFF(4) 2341 ld %r5, %r31, GENREG_OFF(5) 2342 ld %r6, %r31, GENREG_OFF(6) 2343 ld %r7, %r31, GENREG_OFF(7) 2344 ld %r8, %r31, GENREG_OFF(8) 2345 ld %r9, %r31, GENREG_OFF(9) 2346 ld %r10, %r31, GENREG_OFF(10) 2347 ld %r11, %r31, GENREG_OFF(11) 2348 ld %r12, %r31, GENREG_OFF(12) 2349 ld %r13, %r31, GENREG_OFF(13) 2350 ld %r14, %r31, GENREG_OFF(14) 2351 ld %r15, %r31, GENREG_OFF(15) 2352 ld %r16, %r31, GENREG_OFF(16) 2353 ld %r17, %r31, GENREG_OFF(17) 2354 ld %r18, %r31, GENREG_OFF(18) 2355 ld %r19, %r31, GENREG_OFF(19) 2356 ld %r20, %r31, GENREG_OFF(20) 2357 ld %r21, %r31, GENREG_OFF(21) 2358 ld %r22, %r31, GENREG_OFF(22) 2359 ld %r23, %r31, GENREG_OFF(23) 2360 ld %r24, %r31, GENREG_OFF(24) 2361 ld %r25, %r31, GENREG_OFF(25) 2362 ld %r26, %r31, GENREG_OFF(26) 2363 ld %r27, %r31, GENREG_OFF(27) 2364 ld %r28, %r31, GENREG_OFF(28) 2365 ld %r29, %r31, GENREG_OFF(29) 2366 /* restore r1, r30, r31 later */ 2367 2368 /* reload the control regs*/ 2369 ld %r30, %r31, EF_ENIP 2370 ld %r1, %r31, EF_EXIP 2371 stcr %r30, ENIP 2372 stcr %r1, EXIP 2373 2374 ld %r30, %r31, EF_EPSR 2375 stcr %r30, EPSR 2376 2377 /* Now restore r1, r30, and r31 */ 2378 ld %r1, %r31, GENREG_OFF(1) 2379 ld %r30, %r31, GENREG_OFF(30) 2380 ld %r31, %r31, GENREG_OFF(31) 2381 2382 /* 2383 * 88110 errata #18 (fixed in revision 5 cpus): 2384 * ``An rte to user mode where the logical address of the rte 2385 * instruction is within two cache lines of the logical address 2386 * in the exip can cause the wrong instruction to be returned 2387 * to if the rte instruction misses in the icache.'' 2388 * 2389 * Since we run with interrupts disabled at this point, all we 2390 * need is make sure that the rte will not appear as the first 2391 * instruction of a cache line. 2392 */ 2393 br 1f 2394 2395 .align 6 /* 32 bytes might not be enough */ 23961: 2397 NOP 2398 RTE 2399 2400 /* 2401 * NMI return here after processing. 2402 * We then decide whether to check for AST and soft interrupts, 2403 * or not. 2404 */ 2405ASLOCAL(nmi_return) 2406 bcnd ne0, %r2, check_ast 2407 2408 ld FPTR, %r31, 0 /* grab exception frame pointer */ 2409 2410 /* 2411 * Disable interrupts and shadowing. The latter used to be done 2412 * after all the registers from the E.F. have been restored, but 2413 * on 88110 we may receive an NMI anytime, unless shadowing is frozen, 2414 * and we rely on r31 being valid. 2415 */ 2416 ldcr %r1, PSR 2417 set %r1, %r1, 1<PSR_INTERRUPT_DISABLE_BIT> 2418 set %r1, %r1, 1<PSR_SHADOW_FREEZE_BIT> 2419 stcr %r1, PSR 2420 FLUSH_PIPELINE 2421 2422 /* now ready to return....*/ 2423 bsr.n setipl 2424 ld %r2, FPTR, EF_MASK /* get pre-exception ipl */ 2425 2426#ifdef MULTIPROCESSOR 2427 /* 2428 * Reenable NMIs if necessary. 2429 */ 2430 or %r2, FPTR, %r0 2431 bsr nmi_wrapup 2432#endif 2433 2434 br m88110_restore 2435#endif 2436