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