platform.S revision 8029
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * Copyright (c) 1993 Hewlett-Packard Development Company 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Ali G. Saidi 30 * Nathan L. Binkert 31 */ 32 33#define max_cpuid 1 34#define hw_rei_spe hw_rei 35 36#include "ev5_defs.h" 37#include "ev5_impure.h" 38#include "ev5_alpha_defs.h" 39#include "ev5_paldef.h" 40#include "ev5_osfalpha_defs.h" 41#include "fromHudsonMacros.h" 42#include "fromHudsonOsf.h" 43#include "dc21164FromGasSources.h" 44#include "cserve.h" 45#include "tlaser.h" 46 47#define pt_entInt pt_entint 48#define pt_entArith pt_entarith 49#define mchk_size ((mchk_cpu_base + 7 + 8) &0xfff8) 50#define mchk_flag CNS_Q_FLAG 51#define mchk_sys_base 56 52#define mchk_cpu_base (CNS_Q_LD_LOCK + 8) 53#define mchk_offsets CNS_Q_EXC_ADDR 54#define mchk_mchk_code 8 55#define mchk_ic_perr_stat CNS_Q_ICPERR_STAT 56#define mchk_dc_perr_stat CNS_Q_DCPERR_STAT 57#define mchk_sc_addr CNS_Q_SC_ADDR 58#define mchk_sc_stat CNS_Q_SC_STAT 59#define mchk_ei_addr CNS_Q_EI_ADDR 60#define mchk_bc_tag_addr CNS_Q_BC_TAG_ADDR 61#define mchk_fill_syn CNS_Q_FILL_SYN 62#define mchk_ei_stat CNS_Q_EI_STAT 63#define mchk_exc_addr CNS_Q_EXC_ADDR 64#define mchk_ld_lock CNS_Q_LD_LOCK 65#define osfpcb_q_Ksp pcb_q_ksp 66#define pal_impure_common_size ((0x200 + 7) & 0xfff8) 67 68#if defined(BIG_TSUNAMI) 69#define MAXPROC 0x3f 70#define IPIQ_addr 0x800 71#define IPIQ_shift 0 72#define IPIR_addr 0x840 73#define IPIR_shift 0 74#define RTC_addr 0x880 75#define RTC_shift 0 76#define DIR_addr 0xa2 77#elif defined(TSUNAMI) 78#define MAXPROC 0x3 79#define IPIQ_addr 0x080 80#define IPIQ_shift 12 81#define IPIR_addr 0x080 82#define IPIR_shift 8 83#define RTC_addr 0x080 84#define RTC_shift 4 85#define DIR_addr 0xa0 86#elif defined(TLASER) 87#define MAXPROC 0xf 88#else 89#error Must define BIG_TSUNAMI, TSUNAMI, or TLASER 90#endif 91 92#define ALIGN_BLOCK \ 93 .align 5 94 95#define ALIGN_BRANCH \ 96 .align 3 97 98#define EXPORT(_x) \ 99 .align 5; \ 100 .globl _x; \ 101_x: 102 103// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 104// XXX the following is 'made up' 105// XXX bugnion 106 107// XXX bugnion not sure how to align 'quad' 108#define ALIGN_QUAD \ 109 .align 3 110 111#define ALIGN_128 \ 112 .align 7 113 114 115#define GET_IMPURE(_r) mfpr _r,pt_impure 116#define GET_ADDR(_r1,_off,_r2) lda _r1,_off(_r2) 117 118 119#define BIT(_x) (1<<(_x)) 120 121 122// System specific code - beh model version 123// 124// 125// Entry points 126// SYS_CFLUSH - Cache flush 127// SYS_CSERVE - Console service 128// SYS_WRIPIR - interprocessor interrupts 129// SYS_HALT_INTERRUPT - Halt interrupt 130// SYS_PASSIVE_RELEASE - Interrupt, passive release 131// SYS_INTERRUPT - Interrupt 132// SYS_RESET - Reset 133// SYS_ENTER_CONSOLE 134// 135// 136// Macro to read TLINTRSUMx 137// 138// Based on the CPU_NUMBER, read either the TLINTRSUM0 or TLINTRSUM1 register 139// 140// Assumed register usage: 141// rsum TLINTRSUMx contents 142// raddr node space address 143// scratch scratch register 144// 145#define Read_TLINTRSUMx(_rsum, _raddr, _scratch) \ 146 nop; \ 147 mfpr _scratch, pt_whami; /* Get our whami (VID) */ \ 148 extbl _scratch, 1, _scratch; /* shift down to bit 0 */ \ 149 lda _raddr, 0xff88(zero); /* Get base node space address bits */ \ 150 sll _raddr, 24, _raddr; /* Shift up to proper position */ \ 151 srl _scratch, 1, _rsum; /* Shift off the cpu number */ \ 152 sll _rsum, 22, _rsum; /* Get our node offset */ \ 153 addq _raddr, _rsum, _raddr; /* Get our base node space address */ \ 154 blbs _scratch, 1f; \ 155 lda _raddr, 0x1180(_raddr); \ 156 br r31, 2f; \ 1571: lda _raddr, 0x11c0(_raddr); \ 1582: ldl_p _rsum, 0(_raddr) /* read the right tlintrsum reg */ 159 160// 161// Macro to write TLINTRSUMx 162// 163// Based on the CPU_NUMBER, write either the TLINTRSUM0 or TLINTRSUM1 register 164// 165// Assumed register usage: 166// rsum TLINTRSUMx write data 167// raddr node space address 168// scratch scratch register 169// 170#define Write_TLINTRSUMx(_rsum,_raddr,_whami) \ 171 nop; \ 172 mfpr _whami, pt_whami; /* Get our whami (VID) */ \ 173 extbl _whami, 1, _whami; /* shift down to bit 0 */ \ 174 lda _raddr, 0xff88(zero); /* Get base node space address bits */ \ 175 sll _raddr, 24, _raddr; /* Shift up to proper position */ \ 176 blbs _whami, 1f; \ 177 lda _raddr, 0x1180(_raddr); \ 178 br zero, 2f; \ 1791: lda _raddr, 0x11c0(_raddr); \ 1802: srl _whami, 1, _whami; /* Get our node offset */ \ 181 addq _raddr, _whami, _raddr; /* Get our base node space address */ \ 182 mb; \ 183 stq_p _rsum, 0(_raddr); /* write the right tlintrsum reg */ \ 184 ldq_p _rsum, 0(_raddr); /* dummy read to tlintrsum */ \ 185 bis _rsum, _rsum, _rsum /* needed to complete the ldqp above */ 186 187 188// 189// Macro to determine highest priority TIOP Node ID from interrupt pending mask 190// 191// Assumed register usage: 192// rmask - TLINTRSUMx contents, shifted to isolate IOx bits 193// rid - TLSB Node ID of highest TIOP 194// 195#define Intr_Find_TIOP(_rmask,_rid) \ 196 srl _rmask,3,_rid; /* check IOP8 */ \ 197 blbc _rid,1f; /* not IOP8 */ \ 198 lda _rid,8(zero); /* IOP8 */ \ 199 br zero,6f; \ 2001: srl _rmask,3,_rid; /* check IOP7 */ \ 201 blbc _rid, 2f; /* not IOP7 */ \ 202 lda _rid, 7(r31); /* IOP7 */ \ 203 br r31, 6f; \ 2042: srl _rmask, 2, _rid; /* check IOP6 */ \ 205 blbc _rid, 3f; /* not IOP6 */ \ 206 lda _rid, 6(r31); /* IOP6 */ \ 207 br r31, 6f; \ 2083: srl _rmask, 1, _rid; /* check IOP5 */ \ 209 blbc _rid, 4f; /* not IOP5 */ \ 210 lda _rid, 5(r31); /* IOP5 */ \ 211 br r31, 6f; \ 2124: srl _rmask, 0, _rid; /* check IOP4 */ \ 213 blbc _rid, 5f; /* not IOP4 */ \ 214 lda r14, 4(r31); /* IOP4 */ \ 215 br r31, 6f; \ 2165: lda r14, 0(r31); /* passive release */ \ 2176: 218 219// 220// Macro to calculate base node space address for given node id 221// 222// Assumed register usage: 223// rid - TLSB node id 224// raddr - base node space address 225#define Get_TLSB_Node_Address(_rid,_raddr) \ 226 sll _rid, 22, _rid; \ 227 lda _raddr, 0xff88(zero); \ 228 sll _raddr, 24, _raddr; \ 229 addq _raddr, _rid, _raddr 230 231 232#define OSFmchk_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \ 233 lda _rs1, tlep_##_tlepreg(zero); \ 234 or _rs1, _nodebase, _rs1; \ 235 ldl_p _rs1, 0(_rs1); \ 236 stl_p _rs, mchk_##_tlepreg(_rlog) /* store in frame */ 237 238#define OSFmchk_TLEPstore(_tlepreg) \ 239 OSFmchk_TLEPstore_1(r14,r8,r4,r13,_tlepreg) 240 241#define OSFcrd_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \ 242 lda _rs1, tlep_##_tlepreg(zero); \ 243 or _rs1, _nodebase, _rs1; \ 244 ldl_p _rs1, 0(_rs1); \ 245 stl_p _rs, mchk_crd_##_tlepreg(_rlog) 246 247#define OSFcrd_TLEPstore_tlsb_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \ 248 lda _rs1, tlsb_##_tlepreg(zero); \ 249 or _rs1, _nodebase, _rs1; \ 250 ldl_p _rs1, 0(_rs1); \ 251 stl_p _rs,mchk_crd_##_tlepreg(_rlog) 252 253#define OSFcrd_TLEPstore_tlsb_clr_1(_rlog,_rs,_rs1,_nodebase,_tlepreg) \ 254 lda _rs1,tlsb_##_tlepreg(zero); \ 255 or _rs1, _nodebase,_rs1; \ 256 ldl_p _rs1, 0(_rs1); \ 257 stl_p _rs, mchk_crd_##_tlepreg(_rlog); \ 258 stl_p _rs, 0(_rs1) 259 260#define OSFcrd_TLEPstore(_tlepreg) \ 261 OSFcrd_TLEPstore_1(r14,r8,r4,r13,_tlepreg) 262#define OSFcrd_TLEPstore_tlsb(_tlepreg) \ 263 OSFcrd_TLEPstore_tlsb_1(r14,r8,r4,r13,_tlepreg) 264#define OSFcrd_TLEPstore_tlsb_clr(_tlepreg) \ 265 OSFcrd_TLEPstore_tlsb_clr_1(r14,r8,r4,r13,_tlepreg) 266 267 268#define save_pcia_intr(_irq) \ 269 and r13, 0xf, r25; /* isolate low 4 bits */ \ 270 addq r14, 4, r14; /* format the TIOP Node id field */ \ 271 sll r14, 4, r14; /* shift the TIOP Node id */ \ 272 or r14, r25, r10; /* merge Node id/hose/HPC */ \ 273 mfpr r14, pt14; /* get saved value */ \ 274 extbl r14, _irq, r25; /* confirm none outstanding */ \ 275 bne r25, sys_machine_check_while_in_pal; \ 276 insbl r10, _irq, r10; /* align new info */ \ 277 or r14, r10, r14; /* merge info */ \ 278 mtpr r14, pt14; /* save it */ \ 279 bic r13, 0xf, r13 /* clear low 4 bits of vector */ 280 281 282// wripir - PALcode for wripir instruction 283// R16 has the processor number. 284// 285 ALIGN_BLOCK 286EXPORT(sys_wripir) 287 // 288 // Convert the processor number to a CPU mask 289 // 290 and r16, MAXPROC, r14 // mask the top stuff: MAXPROC+1 CPUs supported 291 bis r31, 0x1, r16 // get a one 292 sll r16, r14, r14 // shift the bit to the right place 293#if defined(TSUNAMI) || defined(BIG_TSUNAMI) 294 sll r14,IPIQ_shift,r14 295#endif 296 297 298 // 299 // Build the Broadcast Space base address 300 // 301#if defined(TSUNAMI) || defined(BIG_TSUNAMI) 302 lda r16,0xf01(r31) 303 sll r16,32,r16 304 ldah r13,0xa0(r31) 305 sll r13,8,r13 306 bis r16,r13,r16 307 lda r16,IPIQ_addr(r16) 308#elif defined(TLASER) 309 lda r13, 0xff8e(r31) // Load the upper address bits 310 sll r13, 24, r13 // shift them to the top 311#endif 312 313 // 314 // Send out the IP Intr 315 // 316#if defined(TSUNAMI) || defined(BIG_TSUNAMI) 317 stq_p r14, 0(r16) // Tsunami MISC Register 318#elif defined(TLASER) 319 stq_p r14, 0x40(r13) // Write to TLIPINTR reg 320#endif 321 wmb // Push out the store 322 hw_rei 323 324 325// cflush - PALcode for CFLUSH instruction 326// 327// SYS_CFLUSH 328// Entry: 329// R16 - contains the PFN of the page to be flushed 330// 331// Function: 332// Flush all Dstream caches of 1 entire page 333// 334// 335 ALIGN_BLOCK 336EXPORT(sys_cflush) 337 338// #convert pfn to addr, and clean off <63:20> 339// #sll r16, <page_offset_size_bits>+<63-20>>, r12 340 sll r16, page_offset_size_bits+(63-20),r12 341 342// #ldah r13,<<1@22>+32768>@-16(r31)// + xxx<31:16> 343// # stolen from srcmax code. XXX bugnion 344 lda r13, 0x10(r31) // assume 16Mbytes of cache 345 sll r13, 20, r13 // convert to bytes 346 347 348 srl r12, 63-20, r12 // shift back to normal position 349 xor r12, r13, r12 // xor addr<18> 350 351 or r31, 8192/(32*8), r13 // get count of loads 352 nop 353 354cflush_loop: 355 subq r13, 1, r13 // decr counter 356 mfpr r25, ev5__intid // Fetch level of interruptor 357 358 ldq_p r31, 32*0(r12) // do a load 359 ldq_p r31, 32*1(r12) // do next load 360 361 ldq_p r31, 32*2(r12) // do next load 362 ldq_p r31, 32*3(r12) // do next load 363 364 ldq_p r31, 32*4(r12) // do next load 365 ldq_p r31, 32*5(r12) // do next load 366 367 ldq_p r31, 32*6(r12) // do next load 368 ldq_p r31, 32*7(r12) // do next load 369 370 mfpr r14, ev5__ipl // Fetch current level 371 lda r12, (32*8)(r12) // skip to next cache block addr 372 373 cmple r25, r14, r25 // R25 = 1 if intid .less than or eql ipl 374 beq r25, 1f // if any int's pending, re-queue CFLUSH -- need to check for hlt interrupt??? 375 376 bne r13, cflush_loop // loop till done 377 hw_rei // back to user 378 379 ALIGN_BRANCH 3801: // Here if interrupted 381 mfpr r12, exc_addr 382 subq r12, 4, r12 // Backup PC to point to CFLUSH 383 384 mtpr r12, exc_addr 385 nop 386 387 mfpr r31, pt0 // Pad exc_addr write 388 hw_rei 389 390 391 ALIGN_BLOCK 392// 393// sys_cserve - PALcode for CSERVE instruction 394// 395// Function: 396// Various functions for private use of console software 397// 398// option selector in r0 399// arguments in r16.... 400// 401// 402// r0 = 0 unknown 403// 404// r0 = 1 ldq_p 405// r0 = 2 stq_p 406// args, are as for normal STQ_P/LDQ_P in VMS PAL 407// 408// r0 = 3 dump_tb's 409// r16 = detination PA to dump tb's to. 410// 411// r0<0> = 1, success 412// r0<0> = 0, failure, or option not supported 413// r0<63:1> = (generally 0, but may be function dependent) 414// r0 - load data on ldq_p 415// 416// 417EXPORT(sys_cserve) 418 419 /* taken from scrmax */ 420 cmpeq r18, CSERVE_K_RD_IMPURE, r0 421 bne r0, Sys_Cserve_Rd_Impure 422 423 cmpeq r18, CSERVE_K_JTOPAL, r0 424 bne r0, Sys_Cserve_Jtopal 425 call_pal 0 426 427 or r31, r31, r0 428 hw_rei // and back we go 429 430Sys_Cserve_Rd_Impure: 431 mfpr r0, pt_impure // Get base of impure scratch area. 432 hw_rei 433 434 ALIGN_BRANCH 435 436Sys_Cserve_Jtopal: 437 bic a0, 3, t8 // Clear out low 2 bits of address 438 bis t8, 1, t8 // Or in PAL mode bit 439 mtpr t8,exc_addr 440 hw_rei 441 442 // ldq_p 443 ALIGN_QUAD 4441: 445 ldq_p r0,0(r17) // get the data 446 nop // pad palshadow write 447 448 hw_rei // and back we go 449 450 451 // stq_p 452 ALIGN_QUAD 4532: 454 stq_p r18, 0(r17) // store the data 455 lda r0,17(r31) // bogus 456 hw_rei // and back we go 457 458 459 ALIGN_QUAD 460csrv_callback: 461 ldq r16, 0(r17) // restore r16 462 ldq r17, 8(r17) // restore r17 463 lda r0, hlt_c_callback(r31) 464 br r31, sys_enter_console 465 466 467csrv_identify: 468 mfpr r0, pal_base 469 ldq_p r0, 8(r0) 470 hw_rei 471 472 473// dump tb's 474 ALIGN_QUAD 4750: 476 // DTB PTEs - 64 entries 477 addq r31, 64, r0 // initialize loop counter 478 nop 479 4801: mfpr r12, ev5__dtb_pte_temp // read out next pte to temp 481 mfpr r12, ev5__dtb_pte // read out next pte to reg file 482 483 subq r0, 1, r0 // decrement loop counter 484 nop // Pad - no Mbox instr in cycle after mfpr 485 486 stq_p r12, 0(r16) // store out PTE 487 addq r16, 8 ,r16 // increment pointer 488 489 bne r0, 1b 490 491 ALIGN_BRANCH 492 // ITB PTEs - 48 entries 493 addq r31, 48, r0 // initialize loop counter 494 nop 495 4962: mfpr r12, ev5__itb_pte_temp // read out next pte to temp 497 mfpr r12, ev5__itb_pte // read out next pte to reg file 498 499 subq r0, 1, r0 // decrement loop counter 500 nop // 501 502 stq_p r12, 0(r16) // store out PTE 503 addq r16, 8 ,r16 // increment pointer 504 505 bne r0, 2b 506 or r31, 1, r0 // set success 507 508 hw_rei // and back we go 509 510 511// 512// SYS_INTERRUPT - Interrupt processing code 513// 514// Current state: 515// Stack is pushed 516// ps, sp and gp are updated 517// r12, r14 - available 518// r13 - INTID (new EV5 IPL) 519// r25 - ISR 520// r16, r17, r18 - available 521// 522// 523EXPORT(sys_interrupt) 524 cmpeq r13, 31, r12 // Check for level 31 interrupt 525 bne r12, sys_int_mchk_or_crd // machine check or crd 526 527 cmpeq r13, 30, r12 // Check for level 30 interrupt 528 bne r12, sys_int_powerfail // powerfail 529 530 cmpeq r13, 29, r12 // Check for level 29 interrupt 531 bne r12, sys_int_perf_cnt // performance counters 532 533 cmpeq r13, 23, r12 // Check for level 23 interrupt 534 bne r12, sys_int_23 // IPI in Tsunami 535 536 cmpeq r13, 22, r12 // Check for level 22 interrupt 537 bne r12, sys_int_22 // timer interrupt 538 539 cmpeq r13, 21, r12 // Check for level 21 interrupt 540 bne r12, sys_int_21 // I/O 541 542 cmpeq r13, 20, r12 // Check for level 20 interrupt 543 bne r12, sys_int_20 // system error interrupt 544 // (might be corrected) 545 546 mfpr r14, exc_addr // ooops, something is wrong 547 br r31, pal_pal_bug_check_from_int 548 549 550// 551//sys_int_2* 552// Routines to handle device interrupts at IPL 23-20. 553// System specific method to ack/clear the interrupt, detect passive 554// release, detect interprocessor (22), interval clock (22), corrected 555// system error (20) 556// 557// Current state: 558// Stack is pushed 559// ps, sp and gp are updated 560// r12, r14 - available 561// r13 - INTID (new EV5 IPL) 562// r25 - ISR 563// 564// On exit: 565// Interrupt has been ack'd/cleared 566// a0/r16 - signals IO device interrupt 567// a1/r17 - contains interrupt vector 568// exit to ent_int address 569// 570// 571 572#if defined(TSUNAMI) || defined(BIG_TSUNAMI) 573 ALIGN_BRANCH 574sys_int_23: 575 or r31,0,r16 // IPI interrupt A0 = 0 576 lda r12,0xf01(r31) // build up an address for the MISC register 577 sll r12,16,r12 578 lda r12,0xa000(r12) 579 sll r12,16,r12 580 lda r12,IPIR_addr(r12) 581 582 mfpr r10, pt_whami // get CPU ID 583 extbl r10, 1, r10 // Isolate just whami bits 584 or r31,0x1,r14 // load r14 with bit to clear 585 sll r14,r10,r14 // left shift by CPU ID 586 sll r14,IPIR_shift,r14 587 stq_p r14, 0(r12) // clear the ipi interrupt 588 589 br r31, pal_post_interrupt // Notify the OS 590 591 592 ALIGN_BRANCH 593sys_int_22: 594 or r31,1,r16 // a0 means it is a clock interrupt 595 lda r12,0xf01(r31) // build up an address for the MISC register 596 sll r12,16,r12 597 lda r12,0xa000(r12) 598 sll r12,16,r12 599 lda r12,RTC_addr(r12) 600 601 mfpr r10, pt_whami // get CPU ID 602 extbl r10, 1, r10 // Isolate just whami bits 603 or r31,0x1,r14 // load r14 with bit to clear 604 sll r14,r10,r14 // left shift by CPU ID 605 sll r14,RTC_shift,r14 // put the bits in the right position 606 stq_p r14, 0(r12) // clear the rtc interrupt 607 608 br r31, pal_post_interrupt // Tell the OS 609 610 611 ALIGN_BRANCH 612sys_int_20: 613 Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx 614 srl r13, 12, r13 // shift down to examine IPL15 615 616 Intr_Find_TIOP(r13,r14) 617 beq r14, 1f 618 619 Get_TLSB_Node_Address(r14,r10) 620 lda r10, 0xa40(r10) // Get base TLILID address 621 622 ldl_p r13, 0(r10) // Read the TLILID register 623 bne r13, pal_post_dev_interrupt 624 beq r13, 1f 625 626 and r13, 0x3, r10 // check for PCIA bits 627 beq r10, pal_post_dev_interrupt // done if nothing set 628 save_pcia_intr(1) 629 br r31, pal_post_dev_interrupt // 630 6311: lda r16, osfint_c_passrel(r31) // passive release 632 br r31, pal_post_interrupt // 633 634 635 ALIGN_BRANCH 636sys_int_21: 637 638 lda r12,0xf01(r31) // calculate DIRn address 639 sll r12,32,r12 640 ldah r13,DIR_addr(r31) 641 sll r13,8,r13 642 bis r12,r13,r12 643 644 mfpr r13, pt_whami // get CPU ID 645 extbl r13, 1, r13 // Isolate just whami bits 646 647#ifdef BIG_TSUNAMI 648 sll r13,4,r13 649 or r12,r13,r12 650#else 651 lda r12,0x0080(r12) 652 and r13,0x1,r14 // grab LSB and shift left 6 653 sll r14,6,r14 654 and r13,0x2,r10 // grabl LSB+1 and shift left 9 655 sll r10,9,r10 656 657 mskbl r12,0,r12 // calculate DIRn address 658 lda r13,0x280(r31) 659 bis r12,r13,r12 660 or r12,r14,r12 661 or r12,r10,r12 662#endif 663 664 ldq_p r13, 0(r12) // read DIRn 665 666 or r31,1,r14 // set bit 55 (ISA Interrupt) 667 sll r14,55,r14 668 669 and r13, r14, r14 // check if bit 55 is set 670 lda r16,0x900(r31) // load offset for normal into r13 671 beq r14, normal_int // if not compute the vector normally 672 673 lda r16,0x800(r31) // replace with offset for pic 674 lda r12,0xf01(r31) // build an addr to access PIC 675 sll r12,32,r12 // at f01fc000000 676 ldah r13,0xfc(r31) 677 sll r13,8,r13 678 bis r12,r13,r12 679 ldq_p r13,0x0020(r12) // read PIC1 ISR for interrupting dev 680 681normal_int: 682 //ctlz r13,r14 // count the number of leading zeros 683 // EV5 doesn't have ctlz, but we do, so lets use it 684 .byte 0x4e 685 .byte 0x06 686 .byte 0xed 687 .byte 0x73 688 lda r10,63(r31) 689 subq r10,r14,r17 // subtract from 690 691 lda r13,0x10(r31) 692 mulq r17,r13,r17 // compute 0x900 + (0x10 * Highest DIRn-bit) 693 addq r17,r16,r17 694 695 or r31,3,r16 // a0 means it is a I/O interrupt 696 697 br r31, pal_post_interrupt 698 699#elif defined(TLASER) 700 ALIGN_BRANCH 701sys_int_23: 702 Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx 703 srl r13, 22, r13 // shift down to examine IPL17 704 705 Intr_Find_TIOP(r13,r14) 706 beq r14, 1f 707 708 Get_TLSB_Node_Address(r14,r10) 709 lda r10, 0xac0(r10) // Get base TLILID address 710 711 ldl_p r13, 0(r10) // Read the TLILID register 712 bne r13, pal_post_dev_interrupt 713 7141: lda r16, osfint_c_passrel(r31) // passive release 715 br r31, pal_post_interrupt // 716 717 718 ALIGN_BRANCH 719sys_int_22: 720 Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx 721 srl r13, 6, r14 // check the Intim bit 722 723 blbs r14, tlep_intim // go service Intim 724 srl r13, 5, r14 // check the IP Int bit 725 726 blbs r14, tlep_ipint // go service IP Int 727 srl r13, 17, r13 // shift down to examine IPL16 728 729 Intr_Find_TIOP(r13,r14) 730 beq r14, 1f 731 732 Get_TLSB_Node_Address(r14,r10) 733 lda r10, 0xa80(r10) // Get base TLILID address 734 735 ldl_p r13, 0(r10) // Read the TLILID register 736 bne r13, pal_post_dev_interrupt 737 beq r13, 1f 738 739 and r13, 0x3, r10 // check for PCIA bits 740 beq r10, pal_post_dev_interrupt // done if nothing set 741 save_pcia_intr(2) 742 br r31, pal_post_dev_interrupt // 743 7441: lda r16, osfint_c_passrel(r31) // passive release 745 br r31, pal_post_interrupt // 746 747 748 ALIGN_BRANCH 749sys_int_21: 750 Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx 751 srl r13, 12, r13 // shift down to examine IPL15 752 753 Intr_Find_TIOP(r13,r14) 754 beq r14, 1f 755 756 Get_TLSB_Node_Address(r14,r10) 757 lda r10, 0xa40(r10) // Get base TLILID address 758 759 ldl_p r13, 0(r10) // Read the TLILID register 760 bne r13, pal_post_dev_interrupt 761 beq r13, 1f 762 763 and r13, 0x3, r10 // check for PCIA bits 764 beq r10, pal_post_dev_interrupt // done if nothing set 765 save_pcia_intr(1) 766 br r31, pal_post_dev_interrupt // 767 7681: lda r16, osfint_c_passrel(r31) // passive release 769 br r31, pal_post_interrupt // 770 771 772 ALIGN_BRANCH 773sys_int_20: 774 lda r13, 1(r31) // Duart0 bit 775 Write_TLINTRSUMx(r13,r10,r14) // clear the duart0 bit 776 777 Read_TLINTRSUMx(r13,r10,r14) // read the right TLINTRSUMx 778 blbs r13, tlep_uart0 // go service UART int 779 780 srl r13, 7, r13 // shift down to examine IPL14 781 Intr_Find_TIOP(r13,r14) 782 783 beq r14, tlep_ecc // Branch if not IPL14 784 Get_TLSB_Node_Address(r14,r10) 785 786 lda r10, 0xa00(r10) // Get base TLILID0 address 787 ldl_p r13, 0(r10) // Read the TLILID register 788 789 bne r13, pal_post_dev_interrupt 790 beq r13, 1f 791 792 and r13, 0x3, r10 // check for PCIA bits 793 beq r10, pal_post_dev_interrupt // done if nothing set 794 save_pcia_intr(0) 795 br r31, pal_post_dev_interrupt // 7961: lda r16, osfint_c_passrel(r31) // passive release 797 br r31, pal_post_interrupt // 798 799 800 ALIGN_BRANCH 801tlep_intim: 802 lda r13, 0xffb(r31) // get upper GBUS address bits 803 sll r13, 28, r13 // shift up to top 804 805 lda r13, (0x300)(r13) // full CSRC address (tlep watch csrc offset) 806 ldq_p r13, 0(r13) // read CSRC 807 808 lda r13, 0x40(r31) // load Intim bit 809 Write_TLINTRSUMx(r13,r10,r14) // clear the Intim bit 810 811 lda r16, osfint_c_clk(r31) // passive release 812 br r31, pal_post_interrupt // Build the stack frame 813 814 815 ALIGN_BRANCH 816tlep_ipint: 817 lda r13, 0x20(r31) // load IP Int bit 818 Write_TLINTRSUMx(r13,r10,r14) // clear the IP Int bit 819 820 lda r16, osfint_c_ip(r31) // passive release 821 br r31, pal_post_interrupt // Build the stack frame 822 823 824 ALIGN_BRANCH 825tlep_uart0: 826 lda r13, 0xffa(r31) // get upper GBUS address bits 827 sll r13, 28, r13 // shift up to top 828 829 ldl_p r14, 0x80(r13) // zero pointer register 830 lda r14, 3(r31) // index to RR3 831 832 stl_p r14, 0x80(r13) // write pointer register 833 mb 834 835 mb 836 ldl_p r14, 0x80(r13) // read RR3 837 838 srl r14, 5, r10 // is it Channel A RX? 839 blbs r10, uart0_rx 840 841 srl r14, 4, r10 // is it Channel A TX? 842 blbs r10, uart0_tx 843 844 srl r14, 2, r10 // is it Channel B RX? 845 blbs r10, uart1_rx 846 847 srl r14, 1, r10 // is it Channel B TX? 848 blbs r10, uart1_tx 849 850 lda r8, 0(r31) // passive release 851 br r31, clear_duart0_int // clear tlintrsum and post 852 853 854 ALIGN_BRANCH 855uart0_rx: 856 lda r8, 0x680(r31) // UART0 RX vector 857 br r31, clear_duart0_int // clear tlintrsum and post 858 859 860 ALIGN_BRANCH 861uart0_tx: 862 lda r14, 0x28(r31) // Reset TX Int Pending code 863 mb 864 stl_p r14, 0x80(r13) // write Channel A WR0 865 mb 866 867 lda r8, 0x6c0(r31) // UART0 TX vector 868 br r31, clear_duart0_int // clear tlintrsum and post 869 870 871 ALIGN_BRANCH 872uart1_rx: 873 lda r8, 0x690(r31) // UART1 RX vector 874 br r31, clear_duart0_int // clear tlintrsum and post 875 876 877 ALIGN_BRANCH 878uart1_tx: 879 lda r14, 0x28(r31) // Reset TX Int Pending code 880 stl_p r14, 0(r13) // write Channel B WR0 881 882 lda r8, 0x6d0(r31) // UART1 TX vector 883 br r31, clear_duart0_int // clear tlintrsum and post 884 885 886 ALIGN_BRANCH 887clear_duart0_int: 888 lda r13, 1(r31) // load duart0 bit 889 Write_TLINTRSUMx(r13,r10,r14) // clear the duart0 bit 890 891 beq r8, 1f 892 or r8, r31, r13 // move vector to r13 893 br r31, pal_post_dev_interrupt // Build the stack frame 8941: nop 895 nop 896 hw_rei 897// lda r16, osfint_c_passrel(r31) // passive release 898// br r31, pal_post_interrupt // 899 900 901 ALIGN_BRANCH 902tlep_ecc: 903 mfpr r14, pt_whami // get our node id 904 extbl r14, 1, r14 // shift to bit 0 905 906 srl r14, 1, r14 // shift off cpu number 907 Get_TLSB_Node_Address(r14,r10) // compute our nodespace address 908 909 ldl_p r13, 0x40(r10) // read our TLBER WAS tlsb_tlber_offset 910 srl r13, 17, r13 // shift down the CWDE/CRDE bits 911 912 and r13, 3, r13 // mask the CWDE/CRDE bits 913 beq r13, 1f 914 915 ornot r31, r31, r12 // set flag 916 lda r9, mchk_c_sys_ecc(r31) // System Correctable error MCHK code 917 br r31, sys_merge_sys_corr // jump to CRD logout frame code 918 9191: lda r16, osfint_c_passrel(r31) // passive release 920 921#endif // if TSUNAMI || BIG_TSUNAMI elif TLASER 922 923 ALIGN_BRANCH 924pal_post_dev_interrupt: 925 or r13, r31, r17 // move vector to a1 926 or r31, osfint_c_dev, r16 // a0 signals IO device interrupt 927 928pal_post_interrupt: 929 mfpr r12, pt_entint 930 931 mtpr r12, exc_addr 932 933 nop 934 nop 935 936 hw_rei_spe 937 938 939// 940// sys_passive_release 941// Just pretend the interrupt never occurred. 942// 943 944EXPORT(sys_passive_release) 945 mtpr r11, ev5__dtb_cm // Restore Mbox current mode for ps 946 nop 947 948 mfpr r31, pt0 // Pad write to dtb_cm 949 hw_rei 950 951// 952// sys_int_powerfail 953// A powerfail interrupt has been detected. The stack has been pushed. 954// IPL and PS are updated as well. 955// 956// I'm not sure what to do here, I'm treating it as an IO device interrupt 957// 958// 959 960 ALIGN_BLOCK 961sys_int_powerfail: 962 lda r12, 0xffc4(r31) // get GBUS_MISCR address bits 963 sll r12, 24, r12 // shift to proper position 964 ldq_p r12, 0(r12) // read GBUS_MISCR 965 srl r12, 5, r12 // isolate bit <5> 966 blbc r12, 1f // if clear, no missed mchk 967 968 // Missed a CFAIL mchk 969 lda r13, 0xffc7(r31) // get GBUS$SERNUM address bits 970 sll r13, 24, r13 // shift to proper position 971 lda r14, 0x40(r31) // get bit <6> mask 972 ldq_p r12, 0(r13) // read GBUS$SERNUM 973 or r12, r14, r14 // set bit <6> 974 stq_p r14, 0(r13) // clear GBUS$SERNUM<6> 975 mb 976 mb 977 9781: br r31, sys_int_mchk // do a machine check 979 980 lda r17, scb_v_pwrfail(r31) // a1 to interrupt vector 981 mfpr r25, pt_entint 982 983 lda r16, osfint_c_dev(r31) // a0 to device code 984 mtpr r25, exc_addr 985 986 nop // pad exc_addr write 987 nop 988 989 hw_rei_spe 990 991// 992// sys_halt_interrupt 993// A halt interrupt has been detected. Pass control to the console. 994// 995// 996// 997 EXPORT(sys_halt_interrupt) 998 999 ldah r13, 0x1800(r31) // load Halt/^PHalt bits 1000 Write_TLINTRSUMx(r13,r10,r14) // clear the ^PHalt bits 1001 1002 mtpr r11, dtb_cm // Restore Mbox current mode 1003 nop 1004 nop 1005 mtpr r0, pt0 1006 lda r0, hlt_c_hw_halt(r31) // set halt code to hw halt 1007 br r31, sys_enter_console // enter the console 1008 1009 1010 1011// 1012// sys_int_mchk_or_crd 1013// 1014// Current state: 1015// Stack is pushed 1016// ps, sp and gp are updated 1017// r12 1018// r13 - INTID (new EV5 IPL) 1019// r14 - exc_addr 1020// r25 - ISR 1021// r16, r17, r18 - available 1022// 1023// 1024 ALIGN_BLOCK 1025sys_int_mchk_or_crd: 1026 srl r25, isr_v_mck, r12 1027 blbs r12, sys_int_mchk 1028 // 1029 // Not a Machine check interrupt, so must be an Internal CRD interrupt 1030 // 1031 1032 mb //Clear out Cbox prior to reading IPRs 1033 srl r25, isr_v_crd, r13 //Check for CRD 1034 blbc r13, pal_pal_bug_check_from_int //If CRD not set, shouldn't be here!!! 1035 1036 lda r9, 1(r31) 1037 sll r9, hwint_clr_v_crdc, r9 // get ack bit for crd 1038 mtpr r9, ev5__hwint_clr // ack the crd interrupt 1039 1040 or r31, r31, r12 // clear flag 1041 lda r9, mchk_c_ecc_c(r31) // Correctable error MCHK code 1042 1043sys_merge_sys_corr: 1044 ldah r14, 0xfff0(r31) 1045 mtpr r0, pt0 // save r0 for scratch 1046 zap r14, 0xE0, r14 // Get Cbox IPR base 1047 mtpr r1, pt1 // save r0 for scratch 1048 1049 ldq_p r0, ei_addr(r14) // EI_ADDR IPR 1050 ldq_p r10, fill_syn(r14) // FILL_SYN IPR 1051 bis r0, r10, r31 // Touch lds to make sure they complete before doing scrub 1052 1053 blbs r12, 1f // no scrubbing for IRQ0 case 1054// XXX bugnion pvc_jsr crd_scrub_mem, bsr=1 1055 bsr r13, sys_crd_scrub_mem // and go scrub 1056 1057 // ld/st pair in scrub routine will have finished due 1058 // to ibox stall of stx_c. Don't need another mb. 1059 ldq_p r8, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN 1060 or r8, r31, r12 // Must only be executed once in this flow, and must 1061 br r31, 2f // be after the scrub routine. 1062 10631: ldq_p r8, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN 1064 // For IRQ0 CRD case only - meaningless data. 1065 10662: mfpr r13, pt_mces // Get MCES 1067 srl r12, ei_stat_v_ei_es, r14 // Isolate EI_STAT:EI_ES 1068 blbc r14, 6f // branch if 630 1069 srl r13, mces_v_dsc, r14 // check if 620 reporting disabled 1070 blbc r14, 5f // branch if enabled 1071 or r13, r31, r14 // don't set SCE if disabled 1072 br r31, 8f // continue 10735: bis r13, BIT(mces_v_sce), r14 // Set MCES<SCE> bit 1074 br r31, 8f 1075 10766: srl r13, mces_v_dpc, r14 // check if 630 reporting disabled 1077 blbc r14, 7f // branch if enabled 1078 or r13, r31, r14 // don't set PCE if disabled 1079 br r31, 8f // continue 10807: bis r13, BIT(mces_v_pce), r14 // Set MCES<PCE> bit 1081 1082 // Setup SCB if dpc is not set 10838: mtpr r14, pt_mces // Store updated MCES 1084 srl r13, mces_v_sce, r1 // Get SCE 1085 srl r13, mces_v_pce, r14 // Get PCE 1086 or r1, r14, r1 // SCE OR PCE, since they share 1087 // the CRD logout frame 1088 // Get base of the logout area. 1089 GET_IMPURE(r14) // addr of per-cpu impure area 1090 GET_ADDR(r14,(pal_logout_area+mchk_crd_base),r14) 1091 1092 blbc r1, sys_crd_write_logout_frame // If pce/sce not set, build the frame 1093 1094 // Set the 2nd error flag in the logout area: 1095 1096 lda r1, 3(r31) // Set retry and 2nd error flags 1097 sll r1, 30, r1 // Move to bits 31:30 of logout frame flag longword 1098 stl_p r1, mchk_crd_flag+4(r14) // store flag longword 1099 br sys_crd_ack 1100 1101sys_crd_write_logout_frame: 1102 // should only be here if neither the pce or sce bits are set 1103 1104 // 1105 // Write the mchk code to the logout area 1106 // 1107 stq_p r9, mchk_crd_mchk_code(r14) 1108 1109 1110 // 1111 // Write the first 2 quadwords of the logout area: 1112 // 1113 lda r1, 1(r31) // Set retry flag 1114 sll r1, 63, r9 // Move retry flag to bit 63 1115 lda r1, mchk_crd_size(r9) // Combine retry flag and frame size 1116 stq_p r1, mchk_crd_flag(r14) // store flag/frame size 1117 1118 // 1119 // Write error IPRs already fetched to the logout area 1120 // 1121 stq_p r0, mchk_crd_ei_addr(r14) 1122 stq_p r10, mchk_crd_fill_syn(r14) 1123 stq_p r8, mchk_crd_ei_stat(r14) 1124 stq_p r25, mchk_crd_isr(r14) 1125 // 1126 // Log system specific info here 1127 // 1128crd_storeTLEP_: 1129 lda r1, 0xffc4(r31) // Get GBUS$MISCR address 1130 sll r1, 24, r1 1131 ldq_p r1, 0(r1) // Read GBUS$MISCR 1132 sll r1, 16, r1 // shift up to proper field 1133 mfpr r10, pt_whami // get our node id 1134 extbl r10, 1, r10 // shift to bit 0 1135 or r1, r10, r1 // merge MISCR and WHAMI 1136 stl_p r1, mchk_crd_whami(r14) // write to crd logout area 1137 srl r10, 1, r10 // shift off cpu number 1138 1139 Get_TLSB_Node_Address(r10,r0) // compute our nodespace address 1140 1141 OSFcrd_TLEPstore_tlsb(tldev) 1142 OSFcrd_TLEPstore_tlsb_clr(tlber) 1143 OSFcrd_TLEPstore_tlsb_clr(tlesr0) 1144 OSFcrd_TLEPstore_tlsb_clr(tlesr1) 1145 OSFcrd_TLEPstore_tlsb_clr(tlesr2) 1146 OSFcrd_TLEPstore_tlsb_clr(tlesr3) 1147 1148sys_crd_ack: 1149 mfpr r0, pt0 // restore r0 1150 mfpr r1, pt1 // restore r1 1151 1152 srl r12, ei_stat_v_ei_es, r12 1153 blbc r12, 5f 1154 srl r13, mces_v_dsc, r10 // logging enabled? 1155 br r31, 6f 11565: srl r13, mces_v_dpc, r10 // logging enabled? 11576: blbc r10, sys_crd_post_interrupt // logging enabled -- report it 1158 1159 // logging not enabled 1160 // Get base of the logout area. 1161 GET_IMPURE(r13) // addr of per-cpu impure area 1162 GET_ADDR(r13,(pal_logout_area+mchk_crd_base),r13) 1163 ldl_p r10, mchk_crd_rsvd(r13) // bump counter 1164 addl r10, 1, r10 1165 stl_p r10, mchk_crd_rsvd(r13) 1166 mb 1167 br r31, sys_crd_dismiss_interrupt // just return 1168 1169 // 1170 // The stack is pushed. Load up a0,a1,a2 and vector via entInt 1171 // 1172 // 1173 1174 ALIGN_BRANCH 1175sys_crd_post_interrupt: 1176 lda r16, osfint_c_mchk(r31) // flag as mchk/crd in a0 1177 lda r17, scb_v_proc_corr_err(r31) // a1 <- interrupt vector 1178 1179 blbc r12, 1f 1180 lda r17, scb_v_sys_corr_err(r31) // a1 <- interrupt vector 1181 11821: subq r31, 1, r18 // get a -1 1183 mfpr r25, pt_entInt 1184 1185 srl r18, 42, r18 // shift off low bits of kseg addr 1186 mtpr r25, exc_addr // load interrupt vector 1187 1188 sll r18, 42, r18 // shift back into position 1189 or r14, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address 1190 1191 hw_rei_spe // done 1192 1193 1194 // 1195 // The stack is pushed. Need to back out of it all. 1196 // 1197 1198sys_crd_dismiss_interrupt: 1199 br r31, Call_Pal_Rti 1200 1201 1202// sys_crd_scrub_mem 1203// 1204// r0 = addr of cache block 1205// 1206 ALIGN_BLOCK // align for branch target 1207sys_crd_scrub_mem: 1208 // now find error in memory, and attempt to scrub that cache block 1209 // This routine just scrubs the failing octaword 1210 // Only need to "touch" one quadword per octaword to accomplish the scrub 1211 srl r0, 39, r8 // get high bit of bad pa 1212 blbs r8, 1f // don't attempt fixup on IO space addrs 1213 nop // needed to align the ldq_pl to octaword boundary 1214 nop // " 1215 1216 ldq_p r8, 0(r0) // attempt to read the bad memory 1217 // location 1218 // (Note bits 63:40,3:0 of ei_addr 1219 // are set to 1, but as long as 1220 // we are doing a phys ref, should 1221 // be ok) 1222 nop // Needed to keep the Ibox from swapping the ldq_p into E1 1223 1224 stq_p r8, 0(r0) // Store it back if it is still there. 1225 // If store fails, location already 1226 // scrubbed by someone else 1227 1228 nop // needed to align the ldq_p to octaword boundary 1229 1230 lda r8, 0x20(r31) // flip bit 5 to touch next hexaword 1231 xor r8, r0, r0 1232 nop // needed to align the ldq_p to octaword boundary 1233 nop // " 1234 1235 ldq_p r8, 0(r0) // attempt to read the bad memory 1236 // location 1237 // (Note bits 63:40,3:0 of ei_addr 1238 // are set to 1, but as long as 1239 // we are doing a phys ref, should 1240 // be ok) 1241 nop // Needed to keep the Ibox from swapping the ldq_p into E1 1242 1243 stq_p r8, 0(r0) // Store it back if it is still there. 1244 // If store fails, location already 1245 // scrubbed by someone else 1246 1247 lda r8, 0x20(r31) // restore r0 to original address 1248 xor r8, r0, r0 1249 1250 //at this point, ei_stat could be locked due to a new corr error on the ld, 1251 //so read ei_stat to unlock AFTER this routine. 1252 1253// XXX bugnion pvc$jsr crd_scrub_mem, bsr=1, dest=1 12541: ret r31, (r13) // and back we go 1255 1256 1257// 1258// sys_int_mchk - MCHK Interrupt code 1259// 1260// Machine check interrupt from the system. Setup and join the 1261// regular machine check flow. 1262// On exit: 1263// pt0 - saved r0 1264// pt1 - saved r1 1265// pt4 - saved r4 1266// pt5 - saved r5 1267// pt6 - saved r6 1268// pt10 - saved exc_addr 1269// pt_misc<47:32> - mchk code 1270// pt_misc<31:16> - scb vector 1271// r14 - base of Cbox IPRs in IO space 1272// MCES<mchk> is set 1273// 1274 ALIGN_BLOCK 1275sys_int_mchk: 1276 lda r14, mchk_c_sys_hrd_error(r31) 1277 mfpr r12, exc_addr 1278 1279 addq r14, 1, r14 // Flag as interrupt 1280 nop 1281 1282 sll r14, 32, r14 // Move mchk code to position 1283 mtpr r12, pt10 // Stash exc_addr 1284 1285 mfpr r12, pt_misc // Get MCES and scratch 1286 mtpr r0, pt0 // Stash for scratch 1287 1288 zap r12, 0x3c, r12 // Clear scratch 1289 blbs r12, sys_double_machine_check // MCHK halt if double machine check 1290 1291 or r12, r14, r12 // Combine mchk code 1292 lda r14, scb_v_sysmchk(r31) // Get SCB vector 1293 1294 sll r14, 16, r14 // Move SCBv to position 1295 or r12, r14, r14 // Combine SCBv 1296 1297 bis r14, BIT(mces_v_mchk), r14 // Set MCES<MCHK> bit 1298 mtpr r14, pt_misc // Save mchk code!scbv!whami!mces 1299 1300 ldah r14, 0xfff0(r31) 1301 mtpr r1, pt1 // Stash for scratch 1302 1303 zap r14, 0xE0, r14 // Get Cbox IPR base 1304 mtpr r4, pt4 1305 1306 mtpr r5, pt5 1307 1308 mtpr r6, pt6 1309 br r31, sys_mchk_collect_iprs // Join common machine check flow 1310 1311 1312// 1313// sys_int_perf_cnt - Performance counter interrupt code 1314// 1315// A performance counter interrupt has been detected. The stack 1316// has been pushed. IPL and PS are updated as well. 1317// 1318// on exit to interrupt entry point ENTINT:: 1319// a0 = osfint$c_perf 1320// a1 = scb$v_perfmon (650) 1321// a2 = 0 if performance counter 0 fired 1322// a2 = 1 if performance counter 1 fired 1323// a2 = 2 if performance counter 2 fired 1324// (if more than one counter overflowed, an interrupt will be 1325// generated for each counter that overflows) 1326// 1327// 1328// 1329 ALIGN_BLOCK 1330sys_int_perf_cnt: // Performance counter interrupt 1331 lda r17, scb_v_perfmon(r31) // a1 to interrupt vector 1332 mfpr r25, pt_entint 1333 1334 lda r16, osfint_c_perf(r31) // a0 to perf counter code 1335 mtpr r25, exc_addr 1336 1337 //isolate which perf ctr fired, load code in a2, and ack 1338 mfpr r25, isr 1339 or r31, r31, r18 // assume interrupt was pc0 1340 1341 srl r25, isr_v_pc1, r25 // isolate 1342 cmovlbs r25, 1, r18 // if pc1 set, load 1 into r14 1343 1344 srl r25, 1, r25 // get pc2 1345 cmovlbs r25, 2, r18 // if pc2 set, load 2 into r14 1346 1347 lda r25, 1(r31) // get a one 1348 sll r25, r18, r25 1349 1350 sll r25, hwint_clr_v_pc0c, r25 // ack only the perf counter that generated the interrupt 1351 mtpr r25, hwint_clr 1352 1353 hw_rei_spe 1354 1355 1356 1357// 1358// sys_reset - System specific RESET code 1359// On entry: 1360// r1 = pal_base +8 1361// 1362// Entry state on trap: 1363// r0 = whami 1364// r2 = base of scratch area 1365// r3 = halt code 1366// and the following 3 if init_cbox is enabled: 1367// r5 = sc_ctl 1368// r6 = bc_ctl 1369// r7 = bc_cnfg 1370// 1371// Entry state on switch: 1372// r17 - new PC 1373// r18 - new PCBB 1374// r19 - new VPTB 1375// 1376 1377 ALIGN_BLOCK 1378 .globl sys_reset 1379sys_reset: 1380// mtpr r31, ic_flush_ctl // do not flush the icache - done by hardware before SROM load 1381 mtpr r31, itb_ia // clear the ITB 1382 mtpr r31, dtb_ia // clear the DTB 1383 1384 lda r1, -8(r1) // point to start of code 1385 mtpr r1, pal_base // initialize PAL_BASE 1386 1387 // Interrupts 1388 mtpr r31, astrr // stop ASTs 1389 mtpr r31, aster // stop ASTs 1390 mtpr r31, sirr // clear software interrupts 1391 1392 mtpr r0, pt1 // r0 is whami (unless we entered via swp) 1393 1394 ldah r1,(BIT(icsr_v_sde-16)|BIT(icsr_v_fpe-16)|BIT(icsr_v_spe-16+1))(zero) 1395 1396 bis r31, 1, r0 1397 sll r0, icsr_v_crde, r0 // A 1 in iscr<corr_read_enable> 1398 or r0, r1, r1 // Set the bit 1399 1400 mtpr r1, icsr // ICSR - Shadows enabled, Floating point enable, 1401 // super page enabled, correct read per assembly option 1402 1403 // Mbox/Dcache init 1404 lda r1,BIT(mcsr_v_sp1)(zero) 1405 1406 mtpr r1, mcsr // MCSR - Super page enabled 1407 lda r1, BIT(dc_mode_v_dc_ena)(r31) 1408 ALIGN_BRANCH 1409// mtpr r1, dc_mode // turn Dcache on 1410 nop 1411 1412 mfpr r31, pt0 // No Mbox instr in 1,2,3,4 1413 mfpr r31, pt0 1414 mfpr r31, pt0 1415 mfpr r31, pt0 1416 mtpr r31, dc_flush // flush Dcache 1417 1418 // build PS (IPL=7,CM=K,VMM=0,SW=0) 1419 lda r11, 0x7(r31) // Set shadow copy of PS - kern mode, IPL=7 1420 lda r1, 0x1F(r31) 1421 mtpr r1, ipl // set internal <ipl>=1F 1422 mtpr r31, ev5__ps // set new ps<cm>=0, Ibox copy 1423 mtpr r31, dtb_cm // set new ps<cm>=0, Mbox copy 1424 1425 // Create the PALtemp pt_intmask 1426 // MAP: 1427 // OSF IPL EV5 internal IPL(hex) note 1428 // 0 0 1429 // 1 1 1430 // 2 2 1431 // 3 14 device 1432 // 4 15 device 1433 // 5 16 device 1434 // 6 1E device,performance counter, powerfail 1435 // 7 1F 1436 // 1437 1438 ldah r1, 0x1f1E(r31) // Create upper lw of int_mask 1439 lda r1, 0x1615(r1) 1440 1441 sll r1, 32, r1 1442 ldah r1, 0x1402(r1) // Create lower lw of int_mask 1443 1444 lda r1, 0x0100(r1) 1445 mtpr r1, pt_intmask // Stash in PALtemp 1446 1447 // Unlock a bunch of chip internal IPRs 1448 mtpr r31, exc_sum // clear out exeception summary and exc_mask 1449 mfpr r31, va // unlock va, mmstat 1450 lda r8,(BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(zero) 1451 1452 mtpr r8, icperr_stat // Clear Icache parity error & timeout status 1453 lda r8,(BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31) 1454 1455 mtpr r8, dcperr_stat // Clear Dcache parity error status 1456 1457 rc r0 // clear intr_flag 1458 mtpr r31, pt_trap 1459 1460 mfpr r0, pt_misc 1461 srl r0, pt_misc_v_switch, r1 1462 blbs r1, sys_reset_switch // see if we got here from swppal 1463 1464 // Rest of the "real" reset flow 1465 // ASN 1466 mtpr r31, dtb_asn 1467 mtpr r31, itb_asn 1468 1469 lda r1, 0x67(r31) 1470 sll r1, hwint_clr_v_pc0c, r1 1471 mtpr r1, hwint_clr // Clear hardware interrupt requests 1472 1473 lda r1, BIT(mces_v_dpc)(r31) // 1 in disable processor correctable error 1474 mfpr r0, pt1 // get whami 1475 insbl r0, 1, r0 // isolate whami in correct pt_misc position 1476 or r0, r1, r1 // combine whami and mces 1477 mtpr r1, pt_misc // store whami and mces, swap bit clear 1478 1479 zapnot r3, 1, r0 // isolate halt code 1480 mtpr r0, pt0 // save entry type 1481 1482 // Cycle counter 1483 or r31, 1, r9 // get a one 1484 sll r9, 32, r9 // shift to <32> 1485 mtpr r31, cc // clear Cycle Counter 1486 mtpr r9, cc_ctl // clear and enable the Cycle Counter 1487 mtpr r31, pt_scc // clear System Cycle Counter 1488 1489 1490 // Misc PALtemps 1491 mtpr r31, maf_mode // no mbox instructions for 3 cycles 1492 or r31, 1, r1 // get bogus scbb value 1493 mtpr r1, pt_scbb // load scbb 1494 mtpr r31, pt_prbr // clear out prbr 1495#if defined(TSUNAMI) || defined(BIG_TSUNAMI) 1496 // yes, this is ugly, but you figure out a better 1497 // way to get the address of the kludge_initial_pcbb 1498 // in r1 with an uncooperative assembler --ali 1499 br r1, kludge_getpcb_addr 1500 br r31, kludge_initial_pcbb 1501kludge_getpcb_addr: 1502 ldq_p r19, 0(r1) 1503 sll r19, 44, r19 1504 srl r19, 44, r19 1505 mulq r19,4,r19 1506 addq r19, r1, r1 1507 addq r1,4,r1 1508#elif defined(TLASER) 1509 // or zero,kludge_initial_pcbb,r1 1510 GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1) 1511#endif 1512 mtpr r1, pt_pcbb // load pcbb 1513 lda r1, 2(r31) // get a two 1514 sll r1, 32, r1 // gen up upper bits 1515 mtpr r1, mvptbr 1516 mtpr r1, ivptbr 1517 mtpr r31, pt_ptbr 1518 // Performance counters 1519 mtpr r31, pmctr 1520 1521 // Clear pmctr_ctl in impure area 1522 1523 1524 ldah r14, 0xfff0(r31) 1525 zap r14, 0xE0, r14 // Get Cbox IPR base 1526 GET_IMPURE(r13) 1527 stq_p r31, 0(r13) // Clear lock_flag 1528 1529 mfpr r0, pt0 // get entry type 1530 br r31, sys_enter_console // enter the cosole 1531 1532 1533 // swppal entry 1534 // r0 - pt_misc 1535 // r17 - new PC 1536 // r18 - new PCBB 1537 // r19 - new VPTB 1538sys_reset_switch: 1539 or r31, 1, r9 1540 sll r9, pt_misc_v_switch, r9 1541 bic r0, r9, r0 // clear switch bit 1542 mtpr r0, pt_misc 1543 1544 rpcc r1 // get cyccounter 1545 1546 ldq_p r22, osfpcb_q_fen(r18) // get new fen/pme 1547 ldl_p r23, osfpcb_l_cc(r18) // get cycle counter 1548 ldl_p r24, osfpcb_l_asn(r18) // get new asn 1549 1550 1551 ldq_p r25, osfpcb_q_Mmptr(r18)// get new mmptr 1552 sll r25, page_offset_size_bits, r25 // convert pfn to pa 1553 mtpr r25, pt_ptbr // load the new mmptr 1554 mtpr r18, pt_pcbb // set new pcbb 1555 1556 bic r17, 3, r17 // clean use pc 1557 mtpr r17, exc_addr // set new pc 1558 mtpr r19, mvptbr 1559 mtpr r19, ivptbr 1560 1561 ldq_p r30, osfpcb_q_Usp(r18) // get new usp 1562 mtpr r30, pt_usp // save usp 1563 1564 sll r24, dtb_asn_v_asn, r8 1565 mtpr r8, dtb_asn 1566 sll r24, itb_asn_v_asn, r24 1567 mtpr r24, itb_asn 1568 1569 mfpr r25, icsr // get current icsr 1570 lda r24, 1(r31) 1571 sll r24, icsr_v_fpe, r24 // 1 in icsr<fpe> position 1572 bic r25, r24, r25 // clean out old fpe 1573 and r22, 1, r22 // isolate new fen bit 1574 sll r22, icsr_v_fpe, r22 1575 or r22, r25, r25 // or in new fpe 1576 mtpr r25, icsr // update ibox ipr 1577 1578 subl r23, r1, r1 // gen new cc offset 1579 insll r1, 4, r1 // << 32 1580 mtpr r1, cc // set new offset 1581 1582 or r31, r31, r0 // set success 1583 ldq_p r30, osfpcb_q_Ksp(r18) // get new ksp 1584 mfpr r31, pt0 // stall 1585 hw_rei_stall 1586 1587// 1588//sys_machine_check - Machine check PAL 1589// A machine_check trap has occurred. The Icache has been flushed. 1590// 1591// 1592 1593 ALIGN_BLOCK 1594EXPORT(sys_machine_check) 1595 // Need to fill up the refill buffer (32 instructions) and 1596 // then flush the Icache again. 1597 // Also, due to possible 2nd Cbox register file write for 1598 // uncorrectable errors, no register file read or write for 7 cycles. 1599 1600 //nop 1601 .long 0x4000054 // call M5 Panic 1602 mtpr r0, pt0 // Stash for scratch -- OK if Cbox overwrites 1603 // r0 later 1604 nop 1605 nop 1606 1607 nop 1608 nop 1609 1610 nop 1611 nop 1612 1613 nop 1614 nop 1615 // 10 instructions// 5 cycles 1616 1617 nop 1618 nop 1619 1620 nop 1621 nop 1622 1623 // Register file can now be written 1624 lda r0, scb_v_procmchk(r31) // SCB vector 1625 mfpr r13, pt_mces // Get MCES 1626 sll r0, 16, r0 // Move SCBv to correct position 1627 bis r13, BIT(mces_v_mchk), r14 // Set MCES<MCHK> bit 1628 1629 1630 zap r14, 0x3C, r14 // Clear mchk_code word and SCBv word 1631 mtpr r14, pt_mces 1632 // 20 instructions 1633 1634 nop 1635 or r14, r0, r14 // Insert new SCB vector 1636 lda r0, mchk_c_proc_hrd_error(r31) // MCHK code 1637 mfpr r12, exc_addr 1638 1639 sll r0, 32, r0 // Move MCHK code to correct position 1640 mtpr r4, pt4 1641 or r14, r0, r14 // Insert new MCHK code 1642 mtpr r14, pt_misc // Store updated MCES, MCHK code, and SCBv 1643 1644 ldah r14, 0xfff0(r31) 1645 mtpr r1, pt1 // Stash for scratch - 30 instructions 1646 1647 zap r14, 0xE0, r14 // Get Cbox IPR base 1648 mtpr r12, pt10 // Stash exc_addr 1649 1650 1651 1652 mtpr r31, ic_flush_ctl // Second Icache flush, now it is really flushed. 1653 blbs r13, sys_double_machine_check // MCHK halt if double machine check 1654 1655 mtpr r6, pt6 1656 mtpr r5, pt5 1657 1658 // Look for the powerfail cases here.... 1659 mfpr r4, isr 1660 srl r4, isr_v_pfl, r4 1661 blbc r4, sys_mchk_collect_iprs // skip if no powerfail interrupt pending 1662 lda r4, 0xffc4(r31) // get GBUS$MISCR address bits 1663 sll r4, 24, r4 // shift to proper position 1664 ldq_p r4, 0(r4) // read GBUS$MISCR 1665 srl r4, 5, r4 // isolate bit <5> 1666 blbc r4, sys_mchk_collect_iprs // skip if already cleared 1667 // No missed CFAIL mchk 1668 lda r5, 0xffc7(r31) // get GBUS$SERNUM address bits 1669 sll r5, 24, r5 // shift to proper position 1670 lda r6, 0x40(r31) // get bit <6> mask 1671 ldq_p r4, 0(r5) // read GBUS$SERNUM 1672 or r4, r6, r6 // set bit <6> 1673 stq_p r6, 0(r5) // clear GBUS$SERNUM<6> 1674 mb 1675 mb 1676 1677 1678 // 1679 // Start to collect the IPRs. Common entry point for mchk flows. 1680 // 1681 // Current state: 1682 // pt0 - saved r0 1683 // pt1 - saved r1 1684 // pt4 - saved r4 1685 // pt5 - saved r5 1686 // pt6 - saved r6 1687 // pt10 - saved exc_addr 1688 // pt_misc<47:32> - mchk code 1689 // pt_misc<31:16> - scb vector 1690 // r14 - base of Cbox IPRs in IO space 1691 // r0, r1, r4, r5, r6, r12, r13, r25 - available 1692 // r8, r9, r10 - available as all loads are physical 1693 // MCES<mchk> is set 1694 // 1695 // 1696 1697EXPORT(sys_mchk_collect_iprs) 1698 .long 0x4000054 // call M5 Panic 1699 //mb // MB before reading Scache IPRs 1700 mfpr r1, icperr_stat 1701 1702 mfpr r8, dcperr_stat 1703 mtpr r31, dc_flush // Flush the Dcache 1704 1705 mfpr r31, pt0 // Pad Mbox instructions from dc_flush 1706 mfpr r31, pt0 1707 nop 1708 nop 1709 1710 ldq_p r9, sc_addr(r14) // SC_ADDR IPR 1711 bis r9, r31, r31 // Touch ld to make sure it completes before 1712 // read of SC_STAT 1713 ldq_p r10, sc_stat(r14) // SC_STAT, also unlocks SC_ADDR 1714 1715 ldq_p r12, ei_addr(r14) // EI_ADDR IPR 1716 ldq_p r13, bc_tag_addr(r14) // BC_TAG_ADDR IPR 1717 ldq_p r0, fill_syn(r14) // FILL_SYN IPR 1718 bis r12, r13, r31 // Touch lds to make sure they complete before reading EI_STAT 1719 bis r0, r0, r31 // Touch lds to make sure they complete before reading EI_STAT 1720 ldq_p r25, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN 1721 ldq_p r31, ei_stat(r14) // Read again to insure it is unlocked 1722 1723 1724 1725 1726 // 1727 // Look for nonretryable cases 1728 // In this segment: 1729 // r5<0> = 1 means retryable 1730 // r4, r6, and r14 are available for scratch 1731 // 1732 // 1733 1734 1735 bis r31, r31, r5 // Clear local retryable flag 1736 srl r25, ei_stat_v_bc_tperr, r25 // Move EI_STAT status bits to low bits 1737 1738 lda r4, 1(r31) 1739 sll r4, icperr_stat_v_tmr, r4 1740 and r1, r4, r4 // Timeout reset 1741 bne r4, sys_cpu_mchk_not_retryable 1742 1743 and r8, BIT(dcperr_stat_v_lock), r4 // DCache parity error locked 1744 bne r4, sys_cpu_mchk_not_retryable 1745 1746 lda r4, 1(r31) 1747 sll r4, sc_stat_v_sc_scnd_err, r4 1748 and r10, r4, r4 // 2nd Scache error occurred 1749 bne r4, sys_cpu_mchk_not_retryable 1750 1751 1752 bis r31, 0xa3, r4 // EI_STAT Bcache Tag Parity Error, Bcache Tag Control 1753 // Parity Error, Interface Parity Error, 2nd Error 1754 1755 and r25, r4, r4 1756 bne r4, sys_cpu_mchk_not_retryable 1757 1758// bis r31, #<1@<ei_stat$v_unc_ecc_err-ei_stat$v_bc_tperr>>, r4 1759 bis r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4 1760 and r25, r4, r4 // Isolate the Uncorrectable Error Bit 1761// bis r31, #<1@<ei_stat$v_fil_ird-ei_stat$v_bc_tperr>>, r6 1762 bis r31, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r6 // Isolate the Iread bit 1763 cmovne r6, 0, r4 // r4 = 0 if IRD or if No Uncorrectable Error 1764 bne r4, sys_cpu_mchk_not_retryable 1765 1766 lda r4, 7(r31) 1767 and r10, r4, r4 // Isolate the Scache Tag Parity Error bits 1768 bne r4, sys_cpu_mchk_not_retryable // All Scache Tag PEs are not retryable 1769 1770 1771 lda r4, 0x7f8(r31) 1772 and r10, r4, r4 // Isolate the Scache Data Parity Error bits 1773 srl r10, sc_stat_v_cbox_cmd, r6 1774 and r6, 0x1f, r6 // Isolate Scache Command field 1775 subq r6, 1, r6 // Scache Iread command = 1 1776 cmoveq r6, 0, r4 // r4 = 0 if IRD or if No Parity Error 1777 bne r4, sys_cpu_mchk_not_retryable 1778 1779 // Look for the system unretryable cases here.... 1780 1781 mfpr r4, isr // mchk_interrupt pin asserted 1782 srl r4, isr_v_mck, r4 1783 blbs r4, sys_cpu_mchk_not_retryable 1784 1785 1786 1787 // 1788 // Look for retryable cases 1789 // In this segment: 1790 // r5<0> = 1 means retryable 1791 // r6 - holds the mchk code 1792 // r4 and r14 are available for scratch 1793 // 1794 // 1795 1796 1797 // Within the chip, the retryable cases are Istream errors 1798 lda r4, 3(r31) 1799 sll r4, icperr_stat_v_dpe, r4 1800 and r1, r4, r4 1801 cmovne r4, 1, r5 // Retryable if just Icache parity error 1802 1803 1804 lda r4, 0x7f8(r31) 1805 and r10, r4, r4 // Isolate the Scache Data Parity Error bits 1806 srl r10, sc_stat_v_cbox_cmd, r14 1807 and r14, 0x1f, r14 // Isolate Scache Command field 1808 subq r14, 1, r14 // Scache Iread command = 1 1809 cmovne r4, 1, r4 // r4 = 1 if Scache data parity error bit set 1810 cmovne r14, 0, r4 // r4 = 1 if Scache PE and Iread 1811 bis r4, r5, r5 // Accumulate 1812 1813 1814 bis r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4 1815 and r25, r4, r4 // Isolate the Uncorrectable Error Bit 1816 and r25, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r14 // Isolate the Iread bit 1817 cmovne r4, 1, r4 // r4 = 1 if uncorr error 1818 cmoveq r14, 0, r4 // r4 = 1 if uncorr and Iread 1819 bis r4, r5, r5 // Accumulate 1820 1821 mfpr r6, pt_misc 1822 extwl r6, 4, r6 // Fetch mchk code 1823 bic r6, 1, r6 // Clear flag from interrupt flow 1824 cmovne r5, mchk_c_retryable_ird, r6 // Set mchk code 1825 1826 1827 // 1828 // Write the logout frame 1829 // 1830 // Current state: 1831 // r0 - fill_syn 1832 // r1 - icperr_stat 1833 // r4 - available 1834 // r5<0> - retry flag 1835 // r6 - mchk code 1836 // r8 - dcperr_stat 1837 // r9 - sc_addr 1838 // r10 - sc_stat 1839 // r12 - ei_addr 1840 // r13 - bc_tag_addr 1841 // r14 - available 1842 // r25 - ei_stat (shifted) 1843 // pt0 - saved r0 1844 // pt1 - saved r1 1845 // pt4 - saved r4 1846 // pt5 - saved r5 1847 // pt6 - saved r6 1848 // pt10 - saved exc_addr 1849 // 1850 // 1851 1852sys_mchk_write_logout_frame: 1853 // Get base of the logout area. 1854 GET_IMPURE(r14) // addr of per-cpu impure area 1855 GET_ADDR(r14,pal_logout_area+mchk_mchk_base,r14) 1856 1857 // Write the first 2 quadwords of the logout area: 1858 1859 sll r5, 63, r5 // Move retry flag to bit 63 1860 lda r4, mchk_size(r5) // Combine retry flag and frame size 1861 stq_p r4, mchk_flag(r14) // store flag/frame size 1862 lda r4, mchk_sys_base(r31) // sys offset 1863 sll r4, 32, r4 1864 lda r4, mchk_cpu_base(r4) // cpu offset 1865 stq_p r4, mchk_offsets(r14) // store sys offset/cpu offset into logout frame 1866 1867 // 1868 // Write the mchk code to the logout area 1869 // Write error IPRs already fetched to the logout area 1870 // Restore some GPRs from PALtemps 1871 // 1872 1873 mfpr r5, pt5 1874 stq_p r6, mchk_mchk_code(r14) 1875 mfpr r4, pt4 1876 stq_p r1, mchk_ic_perr_stat(r14) 1877 mfpr r6, pt6 1878 stq_p r8, mchk_dc_perr_stat(r14) 1879 mfpr r1, pt1 1880 stq_p r9, mchk_sc_addr(r14) 1881 stq_p r10, mchk_sc_stat(r14) 1882 stq_p r12, mchk_ei_addr(r14) 1883 stq_p r13, mchk_bc_tag_addr(r14) 1884 stq_p r0, mchk_fill_syn(r14) 1885 mfpr r0, pt0 1886 sll r25, ei_stat_v_bc_tperr, r25 // Move EI_STAT status bits back to expected position 1887 // retrieve lower 28 bits again from ei_stat and restore before storing to logout frame 1888 ldah r13, 0xfff0(r31) 1889 zapnot r13, 0x1f, r13 1890 ldq_p r13, ei_stat(r13) 1891 sll r13, 64-ei_stat_v_bc_tperr, r13 1892 srl r13, 64-ei_stat_v_bc_tperr, r13 1893 or r25, r13, r25 1894 stq_p r25, mchk_ei_stat(r14) 1895 1896 1897 1898 1899 // 1900 // complete the CPU-specific part of the logout frame 1901 // 1902 1903 ldah r13, 0xfff0(r31) 1904 zap r13, 0xE0, r13 // Get Cbox IPR base 1905 ldq_p r13, ld_lock(r13) // Get ld_lock IPR 1906 stq_p r13, mchk_ld_lock(r14) // and stash it in the frame 1907 1908 // Unlock IPRs 1909 lda r8, (BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31) 1910 mtpr r8, dcperr_stat // Clear Dcache parity error status 1911 1912 lda r8, (BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(r31) 1913 mtpr r8, icperr_stat // Clear Icache parity error & timeout status 1914 19151: ldq_p r8, mchk_ic_perr_stat(r14) // get ICPERR_STAT value 1916 GET_ADDR(r0,0x1800,r31) // get ICPERR_STAT value 1917 and r0, r8, r0 // compare 1918 beq r0, 2f // check next case if nothing set 1919 lda r0, mchk_c_retryable_ird(r31) // set new MCHK code 1920 br r31, do_670 // setup new vector 1921 19222: ldq_p r8, mchk_dc_perr_stat(r14) // get DCPERR_STAT value 1923 GET_ADDR(r0,0x3f,r31) // get DCPERR_STAT value 1924 and r0, r8, r0 // compare 1925 beq r0, 3f // check next case if nothing set 1926 lda r0, mchk_c_dcperr(r31) // set new MCHK code 1927 br r31, do_670 // setup new vector 1928 19293: ldq_p r8, mchk_sc_stat(r14) // get SC_STAT value 1930 GET_ADDR(r0,0x107ff,r31) // get SC_STAT value 1931 and r0, r8, r0 // compare 1932 beq r0, 4f // check next case if nothing set 1933 lda r0, mchk_c_scperr(r31) // set new MCHK code 1934 br r31, do_670 // setup new vector 1935 19364: ldq_p r8, mchk_ei_stat(r14) // get EI_STAT value 1937 GET_ADDR(r0,0x30000000,r31) // get EI_STAT value 1938 and r0, r8, r0 // compare 1939 beq r0, 5f // check next case if nothing set 1940 lda r0, mchk_c_bcperr(r31) // set new MCHK code 1941 br r31, do_670 // setup new vector 1942 19435: ldl_p r8, mchk_tlber(r14) // get TLBER value 1944 GET_ADDR(r0,0xfe01,r31) // get high TLBER mask value 1945 sll r0, 16, r0 // shift into proper position 1946 GET_ADDR(r1,0x03ff,r31) // get low TLBER mask value 1947 or r0, r1, r0 // merge mask values 1948 and r0, r8, r0 // compare 1949 beq r0, 6f // check next case if nothing set 1950 GET_ADDR(r0, 0xfff0, r31) // set new MCHK code 1951 br r31, do_660 // setup new vector 1952 19536: ldl_p r8, mchk_tlepaerr(r14) // get TLEPAERR value 1954 GET_ADDR(r0,0xff7f,r31) // get TLEPAERR mask value 1955 and r0, r8, r0 // compare 1956 beq r0, 7f // check next case if nothing set 1957 GET_ADDR(r0, 0xfffa, r31) // set new MCHK code 1958 br r31, do_660 // setup new vector 1959 19607: ldl_p r8, mchk_tlepderr(r14) // get TLEPDERR value 1961 GET_ADDR(r0,0x7,r31) // get TLEPDERR mask value 1962 and r0, r8, r0 // compare 1963 beq r0, 8f // check next case if nothing set 1964 GET_ADDR(r0, 0xfffb, r31) // set new MCHK code 1965 br r31, do_660 // setup new vector 1966 19678: ldl_p r8, mchk_tlepmerr(r14) // get TLEPMERR value 1968 GET_ADDR(r0,0x3f,r31) // get TLEPMERR mask value 1969 and r0, r8, r0 // compare 1970 beq r0, 9f // check next case if nothing set 1971 GET_ADDR(r0, 0xfffc, r31) // set new MCHK code 1972 br r31, do_660 // setup new vector 1973 19749: ldq_p r8, mchk_ei_stat(r14) // get EI_STAT value 1975 GET_ADDR(r0,0xb,r31) // get EI_STAT mask value 1976 sll r0, 32, r0 // shift to upper lw 1977 and r0, r8, r0 // compare 1978 beq r0, 1f // check next case if nothing set 1979 GET_ADDR(r0,0xfffd,r31) // set new MCHK code 1980 br r31, do_660 // setup new vector 1981 19821: ldl_p r8, mchk_tlepaerr(r14) // get TLEPAERR value 1983 GET_ADDR(r0,0x80,r31) // get TLEPAERR mask value 1984 and r0, r8, r0 // compare 1985 beq r0, cont_logout_frame // check next case if nothing set 1986 GET_ADDR(r0, 0xfffe, r31) // set new MCHK code 1987 br r31, do_660 // setup new vector 1988 1989do_670: lda r8, scb_v_procmchk(r31) // SCB vector 1990 br r31, do_6x0_cont 1991do_660: lda r8, scb_v_sysmchk(r31) // SCB vector 1992do_6x0_cont: 1993 sll r8, 16, r8 // shift to proper position 1994 mfpr r1, pt_misc // fetch current pt_misc 1995 GET_ADDR(r4,0xffff, r31) // mask for vector field 1996 sll r4, 16, r4 // shift to proper position 1997 bic r1, r4, r1 // clear out old vector field 1998 or r1, r8, r1 // merge in new vector 1999 mtpr r1, pt_misc // save new vector field 2000 stl_p r0, mchk_mchk_code(r14) // save new mchk code 2001 2002cont_logout_frame: 2003 // Restore some GPRs from PALtemps 2004 mfpr r0, pt0 2005 mfpr r1, pt1 2006 mfpr r4, pt4 2007 2008 mfpr r12, pt10 // fetch original PC 2009 blbs r12, sys_machine_check_while_in_pal // MCHK halt if machine check in pal 2010 2011//XXXbugnion pvc_jsr armc, bsr=1 2012 bsr r12, sys_arith_and_mchk // go check for and deal with arith trap 2013 2014 mtpr r31, exc_sum // Clear Exception Summary 2015 2016 mfpr r25, pt10 // write exc_addr after arith_and_mchk to pickup new pc 2017 stq_p r25, mchk_exc_addr(r14) 2018 2019 // 2020 // Set up the km trap 2021 // 2022 2023 2024sys_post_mchk_trap: 2025 mfpr r25, pt_misc // Check for flag from mchk interrupt 2026 extwl r25, 4, r25 2027 blbs r25, sys_mchk_stack_done // Stack from already pushed if from interrupt flow 2028 2029 bis r14, r31, r12 // stash pointer to logout area 2030 mfpr r14, pt10 // get exc_addr 2031 2032 sll r11, 63-3, r25 // get mode to msb 2033 bge r25, 3f 2034 2035 mtpr r31, dtb_cm 2036 mtpr r31, ev5__ps 2037 2038 mtpr r30, pt_usp // save user stack 2039 mfpr r30, pt_ksp 2040 20413: 2042 lda sp, 0-osfsf_c_size(sp) // allocate stack space 2043 nop 2044 2045 stq r18, osfsf_a2(sp) // a2 2046 stq r11, osfsf_ps(sp) // save ps 2047 2048 stq r14, osfsf_pc(sp) // save pc 2049 mfpr r25, pt_entint // get the VA of the interrupt routine 2050 2051 stq r16, osfsf_a0(sp) // a0 2052 lda r16, osfint_c_mchk(r31) // flag as mchk in a0 2053 2054 stq r17, osfsf_a1(sp) // a1 2055 mfpr r17, pt_misc // get vector 2056 2057 stq r29, osfsf_gp(sp) // old gp 2058 mtpr r25, exc_addr // 2059 2060 or r31, 7, r11 // get new ps (km, high ipl) 2061 subq r31, 1, r18 // get a -1 2062 2063 extwl r17, 2, r17 // a1 <- interrupt vector 2064 bis r31, ipl_machine_check, r25 2065 2066 mtpr r25, ipl // Set internal ipl 2067 srl r18, 42, r18 // shift off low bits of kseg addr 2068 2069 sll r18, 42, r18 // shift back into position 2070 mfpr r29, pt_kgp // get the kern r29 2071 2072 or r12, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address 2073 hw_rei_spe // out to interrupt dispatch routine 2074 2075 2076 // 2077 // The stack is pushed. Load up a0,a1,a2 and vector via entInt 2078 // 2079 // 2080 ALIGN_BRANCH 2081sys_mchk_stack_done: 2082 lda r16, osfint_c_mchk(r31) // flag as mchk/crd in a0 2083 lda r17, scb_v_sysmchk(r31) // a1 <- interrupt vector 2084 2085 subq r31, 1, r18 // get a -1 2086 mfpr r25, pt_entInt 2087 2088 srl r18, 42, r18 // shift off low bits of kseg addr 2089 mtpr r25, exc_addr // load interrupt vector 2090 2091 sll r18, 42, r18 // shift back into position 2092 or r14, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address 2093 2094 hw_rei_spe // done 2095 2096 2097 ALIGN_BRANCH 2098sys_cpu_mchk_not_retryable: 2099 mfpr r6, pt_misc 2100 extwl r6, 4, r6 // Fetch mchk code 2101 br r31, sys_mchk_write_logout_frame // 2102 2103 2104 2105// 2106//sys_double_machine_check - a machine check was started, but MCES<MCHK> was 2107// already set. We will now double machine check halt. 2108// 2109// pt0 - old R0 2110// 2111// 2112 2113EXPORT(sys_double_machine_check) 2114 lda r0, hlt_c_dbl_mchk(r31) 2115 br r31, sys_enter_console 2116 2117// 2118// sys_machine_check_while_in_pal - a machine check was started, 2119// exc_addr points to a PAL PC. We will now machine check halt. 2120// 2121// pt0 - old R0 2122// 2123// 2124sys_machine_check_while_in_pal: 2125 stq_p r12, mchk_exc_addr(r14) // exc_addr has not yet been written 2126 lda r0, hlt_c_mchk_from_pal(r31) 2127 br r31, sys_enter_console 2128 2129 2130//ARITH and MCHK 2131// Check for arithmetic errors and build trap frame, 2132// but don't post the trap. 2133// on entry: 2134// pt10 - exc_addr 2135// r12 - return address 2136// r14 - logout frame pointer 2137// r13 - available 2138// r8,r9,r10 - available except across stq's 2139// pt0,1,6 - available 2140// 2141// on exit: 2142// pt10 - new exc_addr 2143// r17 = exc_mask 2144// r16 = exc_sum 2145// r14 - logout frame pointer 2146// 2147 ALIGN_BRANCH 2148sys_arith_and_mchk: 2149 mfpr r13, ev5__exc_sum 2150 srl r13, exc_sum_v_swc, r13 2151 bne r13, handle_arith_and_mchk 2152 2153// XXX bugnion pvc$jsr armc, bsr=1, dest=1 2154 ret r31, (r12) // return if no outstanding arithmetic error 2155 2156handle_arith_and_mchk: 2157 mtpr r31, ev5__dtb_cm // Set Mbox current mode to kernel 2158 // no virt ref for next 2 cycles 2159 mtpr r14, pt0 2160 2161 mtpr r1, pt1 // get a scratch reg 2162 and r11, osfps_m_mode, r1 // get mode bit 2163 2164 bis r11, r31, r25 // save ps 2165 beq r1, 1f // if zero we are in kern now 2166 2167 bis r31, r31, r25 // set the new ps 2168 mtpr r30, pt_usp // save user stack 2169 2170 mfpr r30, pt_ksp // get kern stack 21711: 2172 mfpr r14, exc_addr // get pc into r14 in case stack writes fault 2173 2174 lda sp, 0-osfsf_c_size(sp) // allocate stack space 2175 mtpr r31, ev5__ps // Set Ibox current mode to kernel 2176 2177 mfpr r1, pt_entArith 2178 stq r14, osfsf_pc(sp) // save pc 2179 2180 stq r17, osfsf_a1(sp) 2181 mfpr r17, ev5__exc_mask // Get exception register mask IPR - no mtpr exc_sum in next cycle 2182 2183 stq r29, osfsf_gp(sp) 2184 stq r16, osfsf_a0(sp) // save regs 2185 2186 bis r13, r31, r16 // move exc_sum to r16 2187 stq r18, osfsf_a2(sp) 2188 2189 stq r11, osfsf_ps(sp) // save ps 2190 mfpr r29, pt_kgp // get the kern gp 2191 2192 mfpr r14, pt0 // restore logout frame pointer from pt0 2193 bis r25, r31, r11 // set new ps 2194 2195 mtpr r1, pt10 // Set new PC 2196 mfpr r1, pt1 2197 2198// XXX bugnion pvc$jsr armc, bsr=1, dest=1 2199 ret r31, (r12) // return if no outstanding arithmetic error 2200 2201 2202 2203// sys_enter_console - Common PALcode for ENTERING console 2204// 2205// Entry: 2206// Entered when PAL wants to enter the console. 2207// usually as the result of a HALT instruction or button, 2208// or catastrophic error. 2209// 2210// Regs on entry... 2211// 2212// R0 = halt code 2213// pt0 <- r0 2214// 2215// Function: 2216// 2217// Save all readable machine state, and "call" the console 2218// 2219// Returns: 2220// 2221// 2222// Notes: 2223// 2224// In these routines, once the save state routine has been executed, 2225// the remainder of the registers become scratchable, as the only 2226// "valid" copy of them is the "saved" copy. 2227// 2228// Any registers or PTs that are modified before calling the save 2229// routine will have there data lost. The code below will save all 2230// state, but will loose pt 0,4,5. 2231// 2232// 2233 2234 ALIGN_BLOCK 2235EXPORT(sys_enter_console) 2236 mtpr r1, pt4 2237 mtpr r3, pt5 2238 subq r31, 1, r1 2239 sll r1, 42, r1 2240 ldah r1, 1(r1) 2241 2242 /* taken from scrmax, seems like the obvious thing to do */ 2243 mtpr r1, exc_addr 2244 mfpr r1, pt4 2245 mfpr r3, pt5 2246 STALL 2247 STALL 2248 hw_rei_stall 2249 2250 2251// 2252// sys_exit_console - Common PALcode for ENTERING console 2253// 2254// Entry: 2255// Entered when console wants to reenter PAL. 2256// usually as the result of a CONTINUE. 2257// 2258// 2259// Regs' on entry... 2260// 2261// 2262// Function: 2263// 2264// Restore all readable machine state, and return to user code. 2265// 2266// 2267// 2268// 2269 ALIGN_BLOCK 2270sys_exit_console: 2271 2272 GET_IMPURE(r1) 2273 2274 // clear lock and intr_flags prior to leaving console 2275 rc r31 // clear intr_flag 2276 // lock flag cleared by restore_state 2277 // TB's have been flushed 2278 2279 ldq_p r3, (cns_gpr+(8*3))(r1) // restore r3 2280 ldq_p r1, (cns_gpr+8)(r1) // restore r1 2281 hw_rei_stall // back to user 2282 2283 2284// kludge_initial_pcbb - PCB for Boot use only 2285 2286 ALIGN_128 2287.globl kludge_initial_pcbb 2288kludge_initial_pcbb: // PCB is 128 bytes long 2289 nop 2290 nop 2291 nop 2292 nop 2293 2294 nop 2295 nop 2296 nop 2297 nop 2298 2299 nop 2300 nop 2301 nop 2302 nop 2303 2304 nop 2305 nop 2306 nop 2307 nop 2308 2309 2310// SET_SC_BC_CTL subroutine 2311// 2312// Subroutine to set the SC_CTL, BC_CONFIG, and BC_CTL registers and 2313// flush the Scache 2314// There must be no outstanding memory references -- istream or 2315// dstream -- when these registers are written. EV5 prefetcher is 2316// difficult to turn off. So, this routine needs to be exactly 32 2317// instructions long// the final jmp must be in the last octaword of a 2318// page (prefetcher doesn't go across page) 2319// 2320// 2321// Register expecations: 2322// r0 base address of CBOX iprs 2323// r5 value to set sc_ctl to (flush bit is added in) 2324// r6 value to set bc_ctl to 2325// r7 value to set bc_config to 2326// r10 return address 2327// r19 old sc_ctl value 2328// r20 old value of bc_ctl 2329// r21 old value of bc_config 2330// r23 flush scache flag 2331// Register usage: 2332// r17 sc_ctl with flush bit cleared 2333// r22 loop address 2334// 2335// 2336set_sc_bc_ctl: 2337 ret r31, (r10) // return to where we came from 2338