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