|
|
1.1 ! root 1: /* ! 2: * <vectors.S> ! 3: * ! 4: * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions. ! 5: * ! 6: * Copyright (C) 1996, 2001 David S. Miller ([email protected]) ! 7: * ! 8: * This program is free software; you can redistribute it and/or ! 9: * modify it under the terms of the GNU General Public License ! 10: * version 2 as published by the Free Software Foundation. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, ! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: * GNU General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU General Public License ! 18: * along with this program; if not, write to the Free Software ! 19: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ! 20: * MA 02110-1301, USA. ! 21: * This program is free software; you can redistribute it and/or ! 22: * modify it under the terms of the GNU General Public License V2 ! 23: * as published by the Free Software Foundation ! 24: */ ! 25: ! 26: #define __ASSEMBLY__ ! 27: #include "pstate.h" ! 28: #include <asm/asi.h> ! 29: #define ASI_BP ASI_PHYS_BYPASS_EC_E ! 30: #define PROM_ADDR 0x1fff0000000 ! 31: #define SER_ADDR 0x1fe020003f8 ! 32: #define TICK_INT_DIS 0x8000000000000000 ! 33: #define TICK_INTERVAL 10*1000*1000 ! 34: ! 35: .section ".text.vectors", "ax" ! 36: .align 16384 ! 37: /* Sparc64 trap table */ ! 38: .globl trap_table, __divide_error, softint_irq, softint_irq_tl1 ! 39: .register %g2, #scratch ! 40: .register %g3, #scratch ! 41: .register %g6, #scratch ! 42: .register %g7, #scratch ! 43: trap_table: ! 44: #define SPILL_WINDOW \ ! 45: btst 1, %sp; \ ! 46: be spill_32bit; \ ! 47: nop; \ ! 48: stx %l0, [%sp + STACK_BIAS + 0x00]; \ ! 49: stx %l1, [%sp + STACK_BIAS + 0x08]; \ ! 50: stx %l2, [%sp + STACK_BIAS + 0x10]; \ ! 51: stx %l3, [%sp + STACK_BIAS + 0x18]; \ ! 52: stx %l4, [%sp + STACK_BIAS + 0x20]; \ ! 53: stx %l5, [%sp + STACK_BIAS + 0x28]; \ ! 54: stx %l6, [%sp + STACK_BIAS + 0x30]; \ ! 55: stx %l7, [%sp + STACK_BIAS + 0x38]; \ ! 56: stx %i0, [%sp + STACK_BIAS + 0x40]; \ ! 57: stx %i1, [%sp + STACK_BIAS + 0x48]; \ ! 58: stx %i2, [%sp + STACK_BIAS + 0x50]; \ ! 59: stx %i3, [%sp + STACK_BIAS + 0x58]; \ ! 60: stx %i4, [%sp + STACK_BIAS + 0x60]; \ ! 61: stx %i5, [%sp + STACK_BIAS + 0x68]; \ ! 62: stx %i6, [%sp + STACK_BIAS + 0x70]; \ ! 63: stx %i7, [%sp + STACK_BIAS + 0x78]; \ ! 64: saved; retry; nop; nop; nop; nop; nop; nop; \ ! 65: nop; nop; nop; nop; nop; ! 66: ! 67: #define FILL_WINDOW \ ! 68: btst 1, %sp; \ ! 69: be fill_32bit; \ ! 70: nop; \ ! 71: ldx [%sp + STACK_BIAS + 0x00], %l0; \ ! 72: ldx [%sp + STACK_BIAS + 0x08], %l1; \ ! 73: ldx [%sp + STACK_BIAS + 0x10], %l2; \ ! 74: ldx [%sp + STACK_BIAS + 0x18], %l3; \ ! 75: ldx [%sp + STACK_BIAS + 0x20], %l4; \ ! 76: ldx [%sp + STACK_BIAS + 0x28], %l5; \ ! 77: ldx [%sp + STACK_BIAS + 0x30], %l6; \ ! 78: ldx [%sp + STACK_BIAS + 0x38], %l7; \ ! 79: ldx [%sp + STACK_BIAS + 0x40], %i0; \ ! 80: ldx [%sp + STACK_BIAS + 0x48], %i1; \ ! 81: ldx [%sp + STACK_BIAS + 0x50], %i2; \ ! 82: ldx [%sp + STACK_BIAS + 0x58], %i3; \ ! 83: ldx [%sp + STACK_BIAS + 0x60], %i4; \ ! 84: ldx [%sp + STACK_BIAS + 0x68], %i5; \ ! 85: ldx [%sp + STACK_BIAS + 0x70], %i6; \ ! 86: ldx [%sp + STACK_BIAS + 0x78], %i7; \ ! 87: restored; retry; nop; nop; nop; nop; nop; nop; \ ! 88: nop; nop; nop; nop; nop; ! 89: ! 90: #define CLEAN_WINDOW \ ! 91: rdpr %cleanwin, %l0; add %l0, 1, %l0; \ ! 92: wrpr %l0, 0x0, %cleanwin; \ ! 93: clr %o0; clr %o1; clr %o2; clr %o3; \ ! 94: clr %o4; clr %o5; clr %o6; clr %o7; \ ! 95: clr %l0; clr %l1; clr %l2; clr %l3; \ ! 96: clr %l4; clr %l5; clr %l6; clr %l7; \ ! 97: retry; \ ! 98: nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; ! 99: ! 100: #define TRAP_IRQ(routine, level) \ ! 101: ba routine; mov level, %g1; nop; nop; nop; nop; nop; nop; ! 102: #define BTRAP(lvl) \ ! 103: ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop; ! 104: #define BTRAPTL1(lvl) BTRAP(lvl) ! 105: #define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7) ! 106: #define BTRAPS4(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) ! 107: #define TRAP_HANDLER(routine) ba routine; nop; nop; nop; nop; nop; nop; nop; ! 108: ! 109: #define STACK_BIAS 2047 ! 110: .globl sparc64_ttable_tl0, sparc64_ttable_tl1 ! 111: sparc64_ttable_tl0: ! 112: ba entry; nop; nop; nop; nop; nop; nop; nop;! XXX remove ! 113: ba entry; nop; nop; nop; nop; nop; nop; nop;! Power-on reset ! 114: ba entry; nop; nop; nop; nop; nop; nop; nop;! Watchdog reset ! 115: ba entry; nop; nop; nop; nop; nop; nop; nop;! External reset ! 116: ba entry; nop; nop; nop; nop; nop; nop; nop;! Software reset ! 117: ba entry; nop; nop; nop; nop; nop; nop; nop;! RED state ! 118: BTRAP(0x06) BTRAP(0x07) BTRAPS(0x08) ! 119: BTRAPS(0x10) BTRAPS(0x18) ! 120: BTRAP(0x20) BTRAP(0x21) BTRAP(0x22) BTRAP(0x23) ! 121: CLEAN_WINDOW ! 24-27 ! 122: BTRAPS(0x28) ! 123: BTRAPS(0x30) BTRAPS(0x38) ! 124: BTRAP(0x40) BTRAP(0x41) BTRAP(0x42) BTRAP(0x43) ! 125: tl0_irq4: TRAP_IRQ(handler_irq, 4) ! 126: tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) ! 127: tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) ! 128: tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) ! 129: tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) ! 130: tl0_irq13: TRAP_IRQ(handler_irq, 13) ! 131: tl0_irq14: TRAP_IRQ(softint_irq, 14) ! 132: tl0_irq15: TRAP_IRQ(handler_irq, 15) ! 133: BTRAPS(0x50) BTRAPS(0x58) ! 134: BTRAPS4(0x60) ! 135: TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss ! 136: TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss ! 137: TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss ! 138: TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss ! 139: TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss ! 140: TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss ! 141: TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss ! 142: TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss ! 143: BTRAPS4(0x6C) ! data_access_protection ! 144: BTRAPS(0x70) BTRAPS(0x78) ! 145: tl0_s0n: SPILL_WINDOW ! 146: tl0_s1n: SPILL_WINDOW ! 147: tl0_s2n: SPILL_WINDOW ! 148: tl0_s3n: SPILL_WINDOW ! 149: tl0_s4n: SPILL_WINDOW ! 150: tl0_s5n: SPILL_WINDOW ! 151: tl0_s6n: SPILL_WINDOW ! 152: tl0_s7n: SPILL_WINDOW ! 153: tl0_s0o: SPILL_WINDOW ! 154: tl0_s1o: SPILL_WINDOW ! 155: tl0_s2o: SPILL_WINDOW ! 156: tl0_s3o: SPILL_WINDOW ! 157: tl0_s4o: SPILL_WINDOW ! 158: tl0_s5o: SPILL_WINDOW ! 159: tl0_s6o: SPILL_WINDOW ! 160: tl0_s7o: SPILL_WINDOW ! 161: tl0_f0n: FILL_WINDOW ! 162: tl0_f1n: FILL_WINDOW ! 163: tl0_f2n: FILL_WINDOW ! 164: tl0_f3n: FILL_WINDOW ! 165: tl0_f4n: FILL_WINDOW ! 166: tl0_f5n: FILL_WINDOW ! 167: tl0_f6n: FILL_WINDOW ! 168: tl0_f7n: FILL_WINDOW ! 169: tl0_f0o: FILL_WINDOW ! 170: tl0_f1o: FILL_WINDOW ! 171: tl0_f2o: FILL_WINDOW ! 172: tl0_f3o: FILL_WINDOW ! 173: tl0_f4o: FILL_WINDOW ! 174: tl0_f5o: FILL_WINDOW ! 175: tl0_f6o: FILL_WINDOW ! 176: tl0_f7o: FILL_WINDOW ! 177: tl0_resv100: BTRAPS(0x100) BTRAPS(0x108) ! 178: tl0_resv110: BTRAPS(0x110) BTRAPS(0x118) ! 179: tl0_resv120: BTRAPS(0x120) BTRAPS(0x128) ! 180: tl0_resv130: BTRAPS(0x130) BTRAPS(0x138) ! 181: tl0_resv140: BTRAPS(0x140) BTRAPS(0x148) ! 182: tl0_resv150: BTRAPS(0x150) BTRAPS(0x158) ! 183: tl0_resv160: BTRAPS(0x160) BTRAPS(0x168) ! 184: tl0_resv170: BTRAPS(0x170) BTRAPS(0x178) ! 185: tl0_resv180: BTRAPS(0x180) BTRAPS(0x188) ! 186: tl0_resv190: BTRAPS(0x190) BTRAPS(0x198) ! 187: tl0_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8) ! 188: tl0_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8) ! 189: tl0_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8) ! 190: tl0_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8) ! 191: tl0_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8) ! 192: tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) ! 193: ! 194: #undef BTRAPS ! 195: #define BTRAPS(x) BTRAPTL1(x) BTRAPTL1(x+1) BTRAPTL1(x+2) BTRAPTL1(x+3) BTRAPTL1(x+4) BTRAPTL1(x+5) BTRAPTL1(x+6) BTRAPTL1(x+7) ! 196: ! 197: #define SKIP_IRQ(routine, level) \ ! 198: retry; nop; nop; nop; nop; nop; nop; nop; ! 199: ! 200: sparc64_ttable_tl1: ! 201: BTRAPS(0x00) BTRAPS(0x08) ! 202: BTRAPS(0x10) BTRAPS(0x18) ! 203: BTRAPTL1(0x20) BTRAPTL1(0x21) BTRAPTL1(0x22) BTRAPTL1(0x23) ! 204: CLEAN_WINDOW ! 24-27 ! 205: BTRAPS(0x28) ! 206: BTRAPS(0x30) BTRAPS(0x38) ! 207: BTRAPTL1(0x40) BTRAPTL1(0x41) BTRAPTL1(0x42) BTRAPTL1(0x43) ! 208: tl1_irq4: TRAP_IRQ(handler_irq, 4) ! 209: tl1_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) ! 210: tl1_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) ! 211: tl1_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) ! 212: tl1_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) ! 213: tl1_irq13: TRAP_IRQ(handler_irq, 13) ! 214: tl1_irq14: SKIP_IRQ(softint_irq, 14) ! 215: tl1_irq15: TRAP_IRQ(handler_irq, 15) ! 216: BTRAPS(0x50) BTRAPS(0x58) ! 217: BTRAPS4(0x60) ! 218: TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss ! 219: TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss ! 220: TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss ! 221: TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss ! 222: TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss ! 223: TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss ! 224: TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss ! 225: TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss ! 226: BTRAPS4(0x6C) ! data_access_protection ! 227: BTRAPS(0x70) BTRAPS(0x78) ! 228: tl1_s0n: SPILL_WINDOW ! 229: tl1_s1n: SPILL_WINDOW ! 230: tl1_s2n: SPILL_WINDOW ! 231: tl1_s3n: SPILL_WINDOW ! 232: tl1_s4n: SPILL_WINDOW ! 233: tl1_s5n: SPILL_WINDOW ! 234: tl1_s6n: SPILL_WINDOW ! 235: tl1_s7n: SPILL_WINDOW ! 236: tl1_s0o: SPILL_WINDOW ! 237: tl1_s1o: SPILL_WINDOW ! 238: tl1_s2o: SPILL_WINDOW ! 239: tl1_s3o: SPILL_WINDOW ! 240: tl1_s4o: SPILL_WINDOW ! 241: tl1_s5o: SPILL_WINDOW ! 242: tl1_s6o: SPILL_WINDOW ! 243: tl1_s7o: SPILL_WINDOW ! 244: tl1_f0n: FILL_WINDOW ! 245: tl1_f1n: FILL_WINDOW ! 246: tl1_f2n: FILL_WINDOW ! 247: tl1_f3n: FILL_WINDOW ! 248: tl1_f4n: FILL_WINDOW ! 249: tl1_f5n: FILL_WINDOW ! 250: tl1_f6n: FILL_WINDOW ! 251: tl1_f7n: FILL_WINDOW ! 252: tl1_f0o: FILL_WINDOW ! 253: tl1_f1o: FILL_WINDOW ! 254: tl1_f2o: FILL_WINDOW ! 255: tl1_f3o: FILL_WINDOW ! 256: tl1_f4o: FILL_WINDOW ! 257: tl1_f5o: FILL_WINDOW ! 258: tl1_f6o: FILL_WINDOW ! 259: tl1_f7o: FILL_WINDOW ! 260: tl1_resv100: BTRAPS(0x100) BTRAPS(0x108) ! 261: tl1_resv110: BTRAPS(0x110) BTRAPS(0x118) ! 262: tl1_resv120: BTRAPS(0x120) BTRAPS(0x128) ! 263: tl1_resv130: BTRAPS(0x130) BTRAPS(0x138) ! 264: tl1_resv140: BTRAPS(0x140) BTRAPS(0x148) ! 265: tl1_resv150: BTRAPS(0x150) BTRAPS(0x158) ! 266: tl1_resv160: BTRAPS(0x160) BTRAPS(0x168) ! 267: tl1_resv170: BTRAPS(0x170) BTRAPS(0x178) ! 268: tl1_resv180: BTRAPS(0x180) BTRAPS(0x188) ! 269: tl1_resv190: BTRAPS(0x190) BTRAPS(0x198) ! 270: tl1_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8) ! 271: tl1_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8) ! 272: tl1_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8) ! 273: tl1_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8) ! 274: tl1_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8) ! 275: tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) ! 276: ! 277: .section ".data" ! 278: .align 8 ! 279: .globl tlb_handler_stack_top, tlb_handler_stack_pointer ! 280: ! 281: ! Stack for the tlb MMU trap handlers ! 282: tlb_handler_stack_bottom: ! 283: .skip 8192 ! 284: tlb_handler_stack_top: ! 285: .skip 8 ! 286: ! 287: ! MMU trap handler stack pointer ! 288: tlb_handler_stack_pointer: ! 289: .xword tlb_handler_stack_top ! 290: ! 291: .section ".text", "ax" ! 292: ! 293: spill_32bit: ! 294: srl %sp, 0, %sp ! 295: stw %l0, [%sp + 0x00] ! 296: stw %l1, [%sp + 0x04] ! 297: stw %l2, [%sp + 0x08] ! 298: stw %l3, [%sp + 0x0c] ! 299: stw %l4, [%sp + 0x10] ! 300: stw %l5, [%sp + 0x14] ! 301: stw %l6, [%sp + 0x18] ! 302: stw %l7, [%sp + 0x1c] ! 303: stw %i0, [%sp + 0x20] ! 304: stw %i1, [%sp + 0x24] ! 305: stw %i2, [%sp + 0x28] ! 306: stw %i3, [%sp + 0x2c] ! 307: stw %i4, [%sp + 0x30] ! 308: stw %i5, [%sp + 0x34] ! 309: stw %i6, [%sp + 0x38] ! 310: stw %i7, [%sp + 0x3c] ! 311: saved ! 312: retry ! 313: ! 314: fill_32bit: ! 315: srl %sp, 0, %sp ! 316: lduw [%sp + 0x00], %l0 ! 317: lduw [%sp + 0x04], %l1 ! 318: lduw [%sp + 0x08], %l2 ! 319: lduw [%sp + 0x0c], %l3 ! 320: lduw [%sp + 0x10], %l4 ! 321: lduw [%sp + 0x14], %l5 ! 322: lduw [%sp + 0x18], %l6 ! 323: lduw [%sp + 0x1c], %l7 ! 324: lduw [%sp + 0x20], %i0 ! 325: lduw [%sp + 0x24], %i1 ! 326: lduw [%sp + 0x28], %i2 ! 327: lduw [%sp + 0x2c], %i3 ! 328: lduw [%sp + 0x30], %i4 ! 329: lduw [%sp + 0x34], %i5 ! 330: lduw [%sp + 0x38], %i6 ! 331: lduw [%sp + 0x3c], %i7 ! 332: restored ! 333: retry ! 334: ! 335: /* ! 336: * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch ! 337: * to C to occur within the MMU I/D TLB miss handlers. ! 338: * ! 339: * Because these handlers are called on a TLB miss, we cannot use flushw to store ! 340: * processor window state on the stack, as the memory areas used by each window's ! 341: * stack pointer may not be in the TLB, causing recursive TLB miss traps. ! 342: * ! 343: * For this reason, we save window state by manually rotating the window registers ! 344: * and saving their contents (along with other vital registers) into a special ! 345: * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and ! 346: * so won't cause issues with trap recursion. ! 347: * ! 348: * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow ! 349: * window fill/spill traps if required), switch to our safe tlb_handler_stack and ! 350: * invoke the miss handler. ! 351: */ ! 352: ! 353: #define SAVE_CPU_STATE(type) \ ! 354: /* Set up our exception stack pointer in %g1 */ \ ! 355: setx tlb_handler_stack_pointer, %g7, %g6; \ ! 356: ldx [%g6], %g1; \ ! 357: add %g1, -0x510, %g1; \ ! 358: \ ! 359: /* First save the various state registers */ \ ! 360: rdpr %cwp, %g7; \ ! 361: stx %g7, [%g1]; \ ! 362: rdpr %cansave, %g7; \ ! 363: stx %g7, [%g1 + 0x8]; \ ! 364: rdpr %canrestore, %g7; \ ! 365: stx %g7, [%g1 + 0x10]; \ ! 366: rdpr %otherwin, %g7; \ ! 367: stx %g7, [%g1 + 0x18]; \ ! 368: rdpr %wstate, %g7; \ ! 369: stx %g7, [%g1 + 0x20]; \ ! 370: rdpr %cleanwin, %g7; \ ! 371: stx %g7, [%g1 + 0x28]; \ ! 372: rdpr %pstate, %g7; \ ! 373: stx %g7, [%g1 + 0x30]; \ ! 374: \ ! 375: rd %y, %g7; \ ! 376: stx %g7, [%g1 + 0x38]; \ ! 377: rd %fprs, %g7; \ ! 378: stx %g7, [%g1 + 0x40]; \ ! 379: \ ! 380: rdpr %tl, %g7; \ ! 381: stx %g7, [%g1 + 0x48]; \ ! 382: \ ! 383: /* Trap state */ \ ! 384: add %g1, 0x50, %g5; \ ! 385: mov 4, %g6; \ ! 386: \ ! 387: save_trap_state_##type: \ ! 388: deccc %g6; \ ! 389: wrpr %g6, %tl; \ ! 390: rdpr %tpc, %g7; \ ! 391: stx %g7, [%g5]; \ ! 392: rdpr %tnpc, %g7; \ ! 393: stx %g7, [%g5 + 0x8]; \ ! 394: rdpr %tstate, %g7; \ ! 395: stx %g7, [%g5 + 0x10]; \ ! 396: rdpr %tt, %g7; \ ! 397: stx %g7, [%g5 + 0x18]; \ ! 398: bne save_trap_state_##type; \ ! 399: add %g5, 0x20, %g5; \ ! 400: \ ! 401: /* For 4 trap levels with 4 registers, memory required is ! 402: 4*8*4 = 0x80 bytes */ \ ! 403: \ ! 404: /* Save the o registers */ \ ! 405: stx %o0, [%g1 + 0xd0]; \ ! 406: stx %o1, [%g1 + 0xd8]; \ ! 407: stx %o2, [%g1 + 0xe0]; \ ! 408: stx %o3, [%g1 + 0xe8]; \ ! 409: stx %o4, [%g1 + 0xf0]; \ ! 410: stx %o5, [%g1 + 0xf8]; \ ! 411: stx %o6, [%g1 + 0x100]; \ ! 412: stx %o7, [%g1 + 0x108]; \ ! 413: \ ! 414: /* Now iterate through all of the windows saving all l and i registers */ \ ! 415: add %g1, 0x110, %g5; \ ! 416: \ ! 417: /* Get the number of windows in %g6 */ \ ! 418: rdpr %ver, %g6; \ ! 419: and %g6, 0xf, %g6; \ ! 420: inc %g6; \ ! 421: \ ! 422: save_cpu_window_##type: \ ! 423: deccc %g6; \ ! 424: wrpr %g6, %cwp; \ ! 425: stx %l0, [%g5]; \ ! 426: stx %l1, [%g5 + 0x8]; \ ! 427: stx %l2, [%g5 + 0x10]; \ ! 428: stx %l3, [%g5 + 0x18]; \ ! 429: stx %l4, [%g5 + 0x20]; \ ! 430: stx %l5, [%g5 + 0x28]; \ ! 431: stx %l6, [%g5 + 0x30]; \ ! 432: stx %l7, [%g5 + 0x38]; \ ! 433: stx %i0, [%g5 + 0x40]; \ ! 434: stx %i1, [%g5 + 0x48]; \ ! 435: stx %i2, [%g5 + 0x50]; \ ! 436: stx %i3, [%g5 + 0x58]; \ ! 437: stx %i4, [%g5 + 0x60]; \ ! 438: stx %i5, [%g5 + 0x68]; \ ! 439: stx %i6, [%g5 + 0x70]; \ ! 440: stx %i7, [%g5 + 0x78]; \ ! 441: bne save_cpu_window_##type; \ ! 442: add %g5, 0x80, %g5; \ ! 443: \ ! 444: /* For 8 windows with 16 registers to save in the window, memory required ! 445: is 16*8*8 = 0x400 bytes */ \ ! 446: \ ! 447: /* Now we should be in window 0 so update the other window registers */ \ ! 448: rdpr %ver, %g6; \ ! 449: and %g6, 0xf, %g6; \ ! 450: dec %g6; \ ! 451: wrpr %g6, %cansave; \ ! 452: \ ! 453: wrpr %g0, %cleanwin; \ ! 454: wrpr %g0, %canrestore; \ ! 455: wrpr %g0, %otherwin; \ ! 456: \ ! 457: /* Update our exception stack pointer */ \ ! 458: setx tlb_handler_stack_pointer, %g7, %g6; \ ! 459: stx %g1, [%g6]; ! 460: ! 461: ! 462: #define RESTORE_CPU_STATE(type) \ ! 463: /* Set up our exception stack pointer in %g1 */ \ ! 464: setx tlb_handler_stack_pointer, %g7, %g6; \ ! 465: ldx [%g6], %g1; \ ! 466: \ ! 467: /* Get the number of windows in %g6 */ \ ! 468: rdpr %ver, %g6; \ ! 469: and %g6, 0xf, %g6; \ ! 470: inc %g6; \ ! 471: \ ! 472: /* Now iterate through all of the windows restoring all l and i registers */ \ ! 473: add %g1, 0x110, %g5; \ ! 474: \ ! 475: restore_cpu_window_##type: \ ! 476: deccc %g6; \ ! 477: wrpr %g6, %cwp; \ ! 478: ldx [%g5], %l0; \ ! 479: ldx [%g5 + 0x8], %l1; \ ! 480: ldx [%g5 + 0x10], %l2; \ ! 481: ldx [%g5 + 0x18], %l3; \ ! 482: ldx [%g5 + 0x20], %l4; \ ! 483: ldx [%g5 + 0x28], %l5; \ ! 484: ldx [%g5 + 0x30], %l6; \ ! 485: ldx [%g5 + 0x38], %l7; \ ! 486: ldx [%g5 + 0x40], %i0; \ ! 487: ldx [%g5 + 0x48], %i1; \ ! 488: ldx [%g5 + 0x50], %i2; \ ! 489: ldx [%g5 + 0x58], %i3; \ ! 490: ldx [%g5 + 0x60], %i4; \ ! 491: ldx [%g5 + 0x68], %i5; \ ! 492: ldx [%g5 + 0x70], %i6; \ ! 493: ldx [%g5 + 0x78], %i7; \ ! 494: bne restore_cpu_window_##type; \ ! 495: add %g5, 0x80, %g5; \ ! 496: \ ! 497: /* Restore the window registers to their original value */ \ ! 498: ldx [%g1], %g7; \ ! 499: wrpr %g7, %cwp; \ ! 500: ldx [%g1 + 0x8], %g7; \ ! 501: wrpr %g7, %cansave; \ ! 502: ldx [%g1 + 0x10], %g7; \ ! 503: wrpr %g7, %canrestore; \ ! 504: ldx [%g1 + 0x18], %g7; \ ! 505: wrpr %g7, %otherwin; \ ! 506: ldx [%g1 + 0x20], %g7; \ ! 507: wrpr %g7, %wstate; \ ! 508: ldx [%g1 + 0x28], %g7; \ ! 509: wrpr %g7, %cleanwin; \ ! 510: ldx [%g1 + 0x30], %g7; \ ! 511: wrpr %g7, %pstate; \ ! 512: \ ! 513: /* Restore the o registers */ \ ! 514: ldx [%g1 + 0xd0], %o0; \ ! 515: ldx [%g1 + 0xd8], %o1; \ ! 516: ldx [%g1 + 0xe0], %o2; \ ! 517: ldx [%g1 + 0xe8], %o3; \ ! 518: ldx [%g1 + 0xf0], %o4; \ ! 519: ldx [%g1 + 0xf8], %o5; \ ! 520: ldx [%g1 + 0x100], %o6; \ ! 521: ldx [%g1 + 0x108], %o7; \ ! 522: \ ! 523: /* Restore the trap state */ \ ! 524: add %g1, 0x50, %g5; \ ! 525: mov 4, %g6; \ ! 526: \ ! 527: restore_trap_state_##type: \ ! 528: deccc %g6; \ ! 529: wrpr %g6, %tl; \ ! 530: ldx [%g5], %g7; \ ! 531: wrpr %g7, %tpc; \ ! 532: ldx [%g5 + 0x8], %g7; \ ! 533: wrpr %g7, %tnpc; \ ! 534: ldx [%g5 + 0x10], %g7; \ ! 535: wrpr %g7, %tstate; \ ! 536: ldx [%g5 + 0x18], %g7; \ ! 537: wrpr %g7, %tt; \ ! 538: bne restore_trap_state_##type; \ ! 539: add %g5, 0x20, %g5; \ ! 540: \ ! 541: ldx [%g1 + 0x38], %g7; \ ! 542: wr %g7, 0, %y; \ ! 543: ldx [%g1 + 0x40], %g7; \ ! 544: wr %g7, 0, %fprs; \ ! 545: ldx [%g1 + 0x48], %g7; \ ! 546: wrpr %g7, %tl; \ ! 547: \ ! 548: /* Restore exception stack pointer to previous value */ \ ! 549: setx tlb_handler_stack_pointer, %g7, %g6; \ ! 550: add %g1, 0x510, %g1; \ ! 551: stx %g1, [%g6]; ! 552: ! 553: ! 554: .globl reload_DMMU_tlb, reload_IMMU_tlb, bug ! 555: ! 556: reload_DMMU_tlb: ! 557: ! 558: SAVE_CPU_STATE(dtlb) ! 559: ! 560: /* Switch to TLB locked stack space (note we add an additional 192 bytes required for ! 561: gcc to save its arguments when building with -O0) */ ! 562: add %g1, -STACK_BIAS - 192, %sp ! 563: ! 564: /* Enable interrupts for window spill/fill traps */ ! 565: rdpr %pstate, %g7 ! 566: or %g7, PSTATE_IE, %g7 ! 567: wrpr %g7, %pstate ! 568: ! 569: call dtlb_miss_handler ! 570: nop ! 571: ! 572: /* Disable interrupts */ ! 573: rdpr %pstate, %g7 ! 574: andn %g7, PSTATE_IE, %g7 ! 575: wrpr %g7, %pstate ! 576: ! 577: RESTORE_CPU_STATE(dtlb) ! 578: ! 579: retry ! 580: ! 581: reload_IMMU_tlb: ! 582: ! 583: SAVE_CPU_STATE(itlb) ! 584: ! 585: /* Switch to TLB locked stack space (note we add an additional 192 bytes required for ! 586: gcc to save its arguments when building with -O0) */ ! 587: add %g1, -STACK_BIAS - 192, %sp ! 588: ! 589: /* Enable interrupts for window spill/fill traps */ ! 590: rdpr %pstate, %g7 ! 591: or %g7, PSTATE_IE, %g7 ! 592: wrpr %g7, %pstate ! 593: ! 594: call itlb_miss_handler ! 595: nop ! 596: ! 597: /* Disable interrupts */ ! 598: rdpr %pstate, %g7 ! 599: andn %g7, PSTATE_IE, %g7 ! 600: wrpr %g7, %pstate ! 601: ! 602: RESTORE_CPU_STATE(itlb) ! 603: ! 604: retry ! 605: ! 606: softint_irq_tl1: ! 607: softint_irq: ! 608: mov 1, %g2 ! 609: /* clear tick interrupt */ ! 610: wr %g2, 0x0, %clear_softint ! 611: sll %g2, %g1, %g2 ! 612: sra %g2, 0, %g2 ! 613: /* clear softint interrupt */ ! 614: wr %g2, 0x0, %clear_softint ! 615: ! 616: setx TICK_INT_DIS, %g2, %g1 ! 617: rd %tick, %g2 ! 618: and %g1, %g2, %g1 ! 619: brnz,pn %g1, tick_compare_disabled ! 620: nop ! 621: set TICK_INTERVAL, %g1 ! 622: add %g1, %g2, %g1 ! 623: wr %g1, 0, %tick_cmpr ! 624: tick_compare_disabled: ! 625: retry ! 626: ! 627: handler_irq: ! 628: __divide_error: ! 629: bug: ! 630: /* Dump the exception and its context */ ! 631: ! Set up CPU state ! 632: ! Don't change the global register set or we lose %g1 (exception level) ! 633: rdpr %pstate, %g2 ! 634: or %g2, PSTATE_PRIV, %g2 ! 635: wrpr %g2, %pstate ! 636: wr %g0, 0, %fprs ! 637: ! 638: ! Jump to ROM ... ! 639: setx _start, %g2, %g3 ! 640: setx highmem, %g2, %g4 ! 641: sub %g4, %g3, %g4 ! 642: setx PROM_ADDR, %g2, %g3 ! 643: add %g4, %g3, %g3 ! 644: jmp %g3 ! 645: ! ... while disabling I/D MMUs and caches ! 646: stxa %g0, [%g0] ASI_LSU_CONTROL ! 647: ! 648: highmem: ! 649: ! Extract NWINDOWS from %ver ! 650: rdpr %ver, %g2 ! 651: and %g2, 0xf, %g2 ! 652: wrpr %g2, 0, %cleanwin ! 653: wrpr %g2, 0, %cansave ! 654: wrpr %g0, 0, %canrestore ! 655: wrpr %g0, 0, %otherwin ! 656: wrpr %g0, 0, %wstate ! 657: ! 658: b dump_exception ! 659: nop ! 660: ! 661: outstr: ! 662: /* void outstr (unsigned long port, const unsigned char *str); ! 663: * Writes a string on an IO port. ! 664: */ ! 665: 1: ldub [%o1], %o3 ! 666: cmp %o3, 0 ! 667: be 2f ! 668: nop ! 669: stba %o3, [%o0] ASI_BP ! 670: b 1b ! 671: inc %o1 ! 672: 2: retl ! 673: nop ! 674: ! 675: outdigit: ! 676: /* void outdigit (unsigned long port, uint8_t digit); ! 677: * Dumps a single digit on serial port. ! 678: */ ! 679: add %o1, '0', %o1 ! 680: retl ! 681: stba %o1, [%o0] ASI_BP ! 682: ! 683: outhex: ! 684: /* void outhex (unsigned long port, uint64_t value); ! 685: * Dumps a 64 bits hex number on serial port ! 686: */ ! 687: mov %o1, %o2 ! 688: set 60, %o3 ! 689: srlx %o2, %o3, %o1 ! 690: 1: and %o1, 0xf, %o1 ! 691: cmp %o1, 9 ! 692: bgt 2f ! 693: nop ! 694: b 3f ! 695: add %o1, '0', %o1 ! 696: 2: add %o1, 'a' - 10, %o1 ! 697: 3: stba %o1, [%o0] ASI_BP ! 698: subcc %o3, 4, %o3 ! 699: bge 1b ! 700: srlx %o2, %o3, %o1 ! 701: retl ! 702: nop ! 703: ! 704: /* void dump_exception (); ! 705: * ! 706: * Dump a message when catching an exception ! 707: */ ! 708: dump_exception: ! 709: setx SER_ADDR, %o3, %o0 ! 710: set _start, %g3 ! 711: set (_BUG_message_0), %o1 ! 712: sub %o1, %g3, %g4 ! 713: setx PROM_ADDR, %g2, %g3 ! 714: add %g4, %g3, %g3 ! 715: call outstr ! 716: mov %g3, %o1 ! 717: ! 718: call outhex ! 719: mov %g1, %o1 ! 720: ! 721: call outstr ! 722: add %g3, (_BUG_message_1 - _BUG_message_0), %o1 ! 723: ! 724: call outhex ! 725: rdpr %tpc, %o1 ! 726: ! 727: call outstr ! 728: add %g3, (_BUG_message_2 - _BUG_message_0), %o1 ! 729: ! 730: call outhex ! 731: rdpr %tnpc, %o1 ! 732: ! 733: call outstr ! 734: add %g3, (_BUG_message_3 - _BUG_message_0), %o1 ! 735: ! 736: _forever: ! 737: /* Loop forever */ ! 738: b _forever ; ! 739: nop ! 740: ! 741: .section .rodata ! 742: _BUG_message_0: ! 743: .string "Unhandled Exception 0x" ! 744: _BUG_message_1: ! 745: .string "\nPC = 0x" ! 746: _BUG_message_2: ! 747: .string " NPC = 0x" ! 748: _BUG_message_3: ! 749: .string "\nStopping execution\n"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.