1/* QEMU Emulation PALcode. 2 3 Copyright (C) 2011 Richard Henderson 4 5 This file is part of QEMU PALcode. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 of the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 .set noat 22 .set nomacro 23 .text 24 25#include "pal.h" 26#include "osf.h" 27#include SYSTEM_H 28 29/* 30 * Create a standard kernel entry stack frame. 31 */ 32 33.macro STACK_FRAME save_ps, save_pc, temp, do_ps 34 // Test if we're currently in user mode 35 and \save_ps, PS_M_CM, \temp 36 beq \temp, 0f 37 // Switch to kernel mode 38.ifne \do_ps 39 mtpr $31, qemu_ps 40.endif 41 mtpr $sp, qemu_usp 42 mfpr $sp, ptKsp 43 // Allocate the stack frame 440: lda $sp, -FRM_K_SIZE($sp) 45 stq \save_ps, FRM_Q_PS($sp) 46 stq \save_pc, FRM_Q_PC($sp) 47 stq $gp, FRM_Q_GP($sp) 48 stq a0, FRM_Q_A0($sp) 49 stq a1, FRM_Q_A1($sp) 50 stq a2, FRM_Q_A2($sp) 51.endm 52 53/* 54 * Allocate a 1 page stack for use by the console. 55 */ 56#define STACK_SIZE 8192 57 58/* 59 * QEMU emulator "hardware" entry points. 60 */ 61 62/* 63 * Reset 64 * 65 * INPUT PARAMETERS: 66 * 67 * trap_arg0 = Memory size 68 * trap_arg1 = Kernel entry (if loaded) 69 */ 70 .org 0x0000 71 .globl __start 72__start: 73 // Initialize GP. 74 br $gp, .+4 75 ldah $gp, 0($gp) !gpdisp!1 76 lda $gp, 0($gp) !gpdisp!1 77 mtpr $gp, ptPgp 78 79 // Disable interrupts; kernel mode 80 lda t0, IPL_K_HIGH 81 mtpr t0, qemu_ps 82 83 // Initialize Stack. 84 SYS_WHAMI a0 85 lda t0, STACK_SIZE 86 addq a0, 1, t1 87 mull t0, t1, t0 88 ldah t1, stack($gp) !gprelhigh 89 lda t1, stack(t1) !gprellow 90 addq t0, t1, $sp 91 92 // Do any necessary system setup required for PALmode, 93 // e.g. setting up ptSys[01]. 94 bsr $26, Sys_Setup 95 96 // Non-boot CPUs can go wait now. 97 bne a0, 1f 98 99 // Load boot arguments 100 mfpr a0, qemu_trap_arg0 // memsize 101 mfpr a1, qemu_trap_arg1 // kernel entry 102 mfpr a2, qemu_trap_arg2 // ncpus 103 104 // Continue in do_start, outside PALmode. 105 ldah $27, do_start($gp) !gprelhigh 106 lda $27, do_start($27) !gprellow 107 hw_ret ($27) 108 1091: ldah $27, do_start_wait($gp) !gprelhigh 110 lda $27, do_start_wait($27) !gprellow 111 hw_ret ($27) 112ENDFN __start 113 114/* 115 * Machine Check 116 * 117 * INPUT PARAMETERS: 118 * 119 * trap_arg0 = 120 * trap_arg1 = 121 * trap_arg2 = 122 */ 123 .org 0x0080 124Pal_Mchk: 125 mfpr p6, qemu_exc_addr // Check for palcode mchk 126 blbs p6, MchkFromPal 127 mfpr p0, ptMces // Check for double mchk 128 blbs p0, MchkDouble 129 130 // Since this is QEMU, the only MCHK we raise spontaneously 131 // is for access to non-existent memory. 132 // 133 // ??? With MemTxResult we could perhaps distinguish 134 // between MEMTX_DECODE_ERROR (no memory) and 135 // MEMTX_ERROR (device error), but it's not clear whether 136 // "device error" corresponds to "PCI target abort" or whatnot. 137 // However the main reason to handle mchk at all is to allow 138 // the guest OS to probe for devices, which is just "no memory". 139 140 lda t0, MCHK_K_SYS_NOMEM 141 br MchkLogOut 142ENDFN Pal_Mchk 143 144/* 145 * Interprocessor Interrupt 146 * 147 * INPUT PARAMETERS: 148 * 149 * trap_arg0 = 150 * trap_arg1 = 151 * trap_arg2 = 152 * 153 * The interprocessor interrupt is special, in that PALcode is supposed 154 * to clear the interupt and not wait for the OS to do it. 155 */ 156 .org 0x0100 157Pal_Smp_Interrupt: 158 mfpr p6, qemu_exc_addr 159 160 SYS_ACK_SMP p0, p1, p2 161 162 mfpr p0, qemu_ps 163 164 STACK_FRAME p0, p6, p2, 0 165 166 mov IPL_K_IP, p0 // Raise IPL 167 mtpr p0, qemu_ps 168 169 mfpr p6, ptEntInt 170 mfpr $gp, ptKgp 171 lda a0, INT_K_IP 172 lda a1, 0 173 lda a2, 0 174 175 hw_ret (p6) 176ENDFN Pal_Smp_Interrupt 177 178/* 179 * Clock Interrupt 180 * 181 * INPUT PARAMETERS: 182 * 183 * trap_arg0 = 184 * trap_arg1 = 185 * trap_arg2 = 186 * 187 * The clock interrupt is special, in that PALcode is supposed 188 * to clear the interupt and not wait for the OS to do it. 189 */ 190 .org 0x0180 191Pal_Clk_Interrupt: 192 mfpr p6, qemu_exc_addr 193 194 SYS_ACK_CLK p0, p1, p2 195 196 mfpr p0, qemu_ps 197 198 STACK_FRAME p0, p6, p2, 0 199 200 mov IPL_K_CLK, p0 // Raise IPL 201 mtpr p0, qemu_ps 202 203 mfpr p6, ptEntInt 204 mfpr $gp, ptKgp 205 lda a0, INT_K_CLK 206 lda a1, 0 207 lda a2, 0 208 2099: hw_ret (p6) 210ENDFN Pal_Clk_Interrupt 211 212/* 213 * Device Interrupt 214 * 215 * INPUT PARAMETERS: 216 * 217 * trap_arg0 = 218 * trap_arg1 = 219 * trap_arg2 = 220 */ 221 .org 0x0200 222Pal_Dev_Interrupt: 223 mfpr p6, qemu_exc_addr 224 mfpr p0, qemu_ps 225 226 STACK_FRAME p0, p6, p2, 0 227 228 mov IPL_K_DEV1, p0 // Raise IPL 229 mtpr p0, qemu_ps 230 231 bsr p7, Sys_Dev_Vector 232 233 mfpr p7, ptEntInt 234 mfpr $gp, ptKgp 235 lda a0, INT_K_DEV 236 lda a2, 0 237 hw_ret (p7) 238ENDFN Pal_Dev_Interrupt 239 240/* 241 * Memory Fault 242 * 243 * INPUT PARAMETERS: 244 * 245 * trap_arg0 = faulting address 246 * trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE) 247 * trap_arg2 = access type (exec=-1, read=0, write=1) 248 */ 249 .org 0x0280 250Pal_MMFault: 251 mfpr p0, qemu_ps 252 mfpr p6, qemu_exc_addr 253 blbs p6, MchkBugCheck 254 255 STACK_FRAME p0, p6, p2, 1 256 257 mfpr p0, ptEntMM 258 mfpr $gp, ptKgp 259 mfpr a0, qemu_trap_arg0 260 mfpr a1, qemu_trap_arg1 261 mfpr a2, qemu_trap_arg2 262 hw_ret (p0) 263ENDFN Pal_MMFault 264 265/* 266 * Unaligned Data 267 * 268 * INPUT PARAMETERS: 269 * 270 * trap_arg0 = faulting address 271 * trap_arg1 = opcode of faulting insn 272 * trap_arg2 = src/dst register number 273 */ 274 .org 0x0300 275Pal_Unalign: 276 mfpr p0, qemu_ps 277 mfpr p6, qemu_exc_addr 278 blbs p6, MchkBugCheck 279 addq p6, 4, p6 // increment past the faulting insn 280 281 STACK_FRAME p0, p1, p2, 1 282 283 mfpr p0, ptEntUna 284 mfpr $gp, ptKgp 285 mfpr a0, qemu_trap_arg0 286 mfpr a1, qemu_trap_arg1 287 mfpr a2, qemu_trap_arg2 288 hw_ret (p0) 289ENDFN Pal_Unalign 290 291/* 292 * Illegal Opcode 293 * 294 * INPUT PARAMETERS: 295 * 296 * trap_arg0 = UNDEFINED 297 * trap_arg1 = UNDEFINED 298 * trap_arg2 = UNDEFINED 299 * 300 * OUTPUT PARAMETERS: 301 * 302 * r16 (a0) = Instruction fault code 303 * r17 (a1) = UNPREDICTABLE 304 * r18 (a2) = UNPREDICTABLE 305 */ 306 .org 0x0380 307Pal_OpcDec: 308 mfpr p0, qemu_ps 309 mfpr p6, qemu_exc_addr 310 blbs p6, MchkBugCheck 311 312 STACK_FRAME p0, p6, p2, 1 313 314 mfpr p0, ptEntIF 315 mfpr $gp, ptKgp 316 mov IF_K_OPCDEC, a0 317 hw_ret (p0) 318ENDFN Pal_OpcDec 319 320/* 321 * Arithmetic Trap 322 * 323 * INPUT PARAMETERS: 324 * 325 * trap_arg0 = exception type 326 * trap_arg1 = register modification mask 327 * trap_arg2 = UNDEFINED 328 */ 329 .org 0x0400 330Pal_Arith: 331 mfpr p0, qemu_ps 332 mfpr p6, qemu_exc_addr 333 blbs p6, MchkBugCheck 334 335 STACK_FRAME p0, p6, p2, 1 336 337 mfpr p0, ptEntArith 338 mfpr $gp, ptKgp 339 mfpr a0, qemu_trap_arg0 340 mfpr a1, qemu_trap_arg1 341 hw_ret (p0) 342ENDFN Pal_Arith 343 344/* 345 * Floating Point Disabled 346 * 347 * INPUT PARAMETERS: 348 * 349 * trap_arg0 = UNDEFINED 350 * trap_arg1 = UNDEFINED 351 * trap_arg2 = UNDEFINED 352 * 353 * OUTPUT PARAMETERS: 354 * 355 * r16 (a0) = Instruction fault code 356 * r17 (a1) = UNPREDICTABLE 357 * r18 (a2) = UNPREDICTABLE 358 */ 359 .org 0x0480 360Pal_Fen: 361 mfpr p0, qemu_ps 362 mfpr p6, qemu_exc_addr 363 blbs p6, MchkBugCheck 364 365 STACK_FRAME p0, p6, p2, 1 366 367 mfpr p0, ptEntIF 368 mfpr $gp, ptKgp 369 mov IF_K_FEN, a0 370 hw_ret (p0) 371ENDFN Pal_Fen 372 373/* 374 * OSF/1 Privileged CALL_PAL Entry Points 375 */ 376 377#define ORG_CALL_PAL_PRIV(X) .org 0x1000+64*X 378 379/* 380 * Halt 381 * 382 * SIDE EFFECTS: 383 * 384 * We either power down the system or re-enter the console. 385 * But given that we're not returning to the kernel, there's 386 * no reason to continue processing in assembler. Go to C. 387 */ 388 ORG_CALL_PAL_PRIV(0x00) 389CallPal_Halt: 390 bsr p7, UpdatePCB // Save kernel data 391 lda v0, HLT_K_SW_HALT // FIXME store this somewhere. 392 393 mtpr $31, qemu_halt 394 395 br Sys_EnterConsole 396ENDFN CallPal_Halt 397 398/* 399 * Cache Flush 400 * 401 * For QEMU, this is of course a no-op. 402 */ 403 ORG_CALL_PAL_PRIV(0x01) 404CallPal_Cflush: 405 hw_rei 406ENDFN CallPal_Cflush 407 408/* 409 * Drain Aborts 410 * 411 * For QEMU, this is of course a no-op. 412 */ 413 ORG_CALL_PAL_PRIV(0x02) 414CallPal_Draina: 415 hw_rei 416ENDFN CallPal_Draina 417 418/* 419 * Delay for N nanoseconds. 420 * 421 * This is unique to QEMU, used only within PALcode itself. 422 */ 423 ORG_CALL_PAL_PRIV(0x03) 424CallPal_Ndelay: 425 mfpr p0, qemu_vmtime 426 addq p0, a0, p0 427 mtpr p0, qemu_alarm 428 429 mtpr $31, qemu_wait 430 431 SYS_ACK_CLK p2, p3, p4 432 433 mfpr v0, qemu_vmtime 434 subq p0, v0, v0 435 hw_rei 436ENDFN CallPal_Ndelay 437 438 ORG_CALL_PAL_PRIV(0x04) 439CallPal_OpcDec04: 440 br CallPal_OpcDec 441ENDFN CallPal_OpcDec04 442 443 ORG_CALL_PAL_PRIV(0x05) 444CallPal_OpcDec05: 445 br CallPal_OpcDec 446ENDFN CallPal_OpcDec05 447 448 ORG_CALL_PAL_PRIV(0x06) 449CallPal_OpcDec06: 450 br CallPal_OpcDec 451ENDFN CallPal_OpcDec06 452 453 ORG_CALL_PAL_PRIV(0x07) 454CallPal_OpcDec07: 455 br CallPal_OpcDec 456ENDFN CallPal_OpcDec07 457 458 ORG_CALL_PAL_PRIV(0x08) 459CallPal_OpcDec08: 460 br CallPal_OpcDec 461ENDFN CallPal_OpcDec08 462 463/* 464 * Console Service 465 * 466 * INPUT PARAMETERS: 467 * 468 * r16 (a0) = Option selector 469 * r17..r21 (a1..a5) = Implementation specific entry parameters 470 * 471 * SIDE EFFECTS: 472 * 473 * Registers a0..a5, and v0 are UNPREDICTABLE upon return. 474 */ 475 ORG_CALL_PAL_PRIV(0x09) 476CallPal_Cserve: 477 // Most of the entries are densely clustered around 0. 478 mov 0, v0 479 cmpule a0, 7, p0 480 cmovne p0, a0, v0 481 br p0, 1f 4821: lda p0, Cserve_Table-1b(p0) 483 s8addq v0, p0, p0 484 jmp $31, (p0), 0 485ENDFN CallPal_Cserve 486 487 .text 1 488 .align 3 489/* Note that the entries in the following table are all 2 insns. 490 The first entry is unused, and is also where all out-of-range 491 commands are vectored. */ 492Cserve_Table: 493 br CallPal_Cserve_Cont 494 nop 495Cserve_Ldqp: 496 ldq_p v0, 0(a1) 497 hw_rei 498ENDFN Cserve_Ldqp 499Cserve_Stqp: 500 stq_p a2, 0(a1) 501 hw_rei 502ENDFN Cserve_Stqp 503Cserve_Get_Wall_Time: 504 mfpr v0, qemu_walltime 505 hw_rei 506ENDFN Cserve_Get_Wall_Time 507Cserve_Get_Alarm: 508 mfpr v0, qemu_alarm 509 hw_rei 510ENDFN Cserve_Get_Alarm 511Cserve_Set_Alarm_Rel: 512 // Cheating here: create the absolute time and fall thru. 513 mfpr p0, qemu_vmtime 514 addq p0, a1, a1 515ENDFN Cserve_Set_Alarm_Rel 516Cserve_Set_Alarm_Abs: 517 mtpr a1, qemu_alarm 518 hw_rei 519ENDFN Cserve_Set_Alarm_Abs 520Cserve_Get_VM_Time: 521 mfpr v0, qemu_vmtime 522 hw_rei 523ENDFN Cserve_Get_VM_Time 524 525 526CallPal_Cserve_Cont: 527 // ??? For SRM compatibility and their use within Linux, use 52/53 528 // for these. Anyone know what other "standard" SRM Cserve entry 529 // points are? Certainly we don't want to be compatible with MILO, 530 // which puts the selector at A2. 531 cmpeq a0, 52, v0 532 bne v0, Cserve_Ena 533 cmpeq a0, 53, v0 534 bne v0, Cserve_Dis 535 hw_rei 536ENDFN CallPal_Cserve_Cont 537 .previous 538 539/* 540 * Swap PALcode 541 * 542 * FUNCTIONAL DESCRIPTION: 543 * 544 * The swap PALcode (swppal) function replaces the current 545 * (active) PALcode by the specified new PALcode image. 546 * This function is intended for use by operating systems 547 * only during bootstraps and restarts, or during transitions 548 * to console I/O mode. 549 * 550 * The PALcode descriptor passed in a0 is interpreted as 551 * either a PALcode variant or the base physical address 552 * of the new PALcode image. If a variant, the PALcode 553 * image must have been previously loaded. No PALcode 554 * loading occurs as a result of this function. 555 * 556 * NOTE: 557 * This implementation of SWPPAL does not support PALcode 558 * variants. If a variant is specified in a0, a check is 559 * performed to determine whether the variant is OSF/1 or 560 * not and the returned status is either unknown variant 561 * (if not OSF/1) or variant not loaded. 562 * 563 * INPUT PARAMETERS: 564 * 565 * r16 (a0) = New PALcode variant or base physical address 566 * r17 (a1) = New PC 567 * r18 (a2) = New PCB 568 * r19 (a3) = New VptPtr 569 * 570 * OUTPUT PARAMETERS: 571 * 572 * r0 (v0) = Returned status indicating: 573 * 0 - Success (PALcode was switched) 574 * 1 - Unknown PALcode variant 575 * 2 - Known PALcode variant, but PALcode not loaded 576 * 577 * r26 (ra) = r27 (pv) = New PC 578 * Note that this is non-architected, but is relied on by 579 * the usage of SwpPal within our own console code in order 580 * to simplify its use within C code. 581 * 582 */ 583 ORG_CALL_PAL_PRIV(0x0A) 584CallPal_SwpPal: 585 // Save a copy of the return address in case of machine check. 586 mfpr p6, qemu_exc_addr 587 588 // Accept swapping to OSF PALcode. The side effect here is to 589 // load the other parameters for the kernel. 590 cmpeq a0, 2, v0 591 bne v0, CallPal_SwpPal_Cont 592 593 // Return as an unknown PALcode variant 594 mov 1, v0 595 hw_rei 596ENDFN CallPal_SwpPal 597 598 .text 1 599CallPal_SwpPal_Cont: 600 rpcc p0 601 mtpr a2, ptPcbb 602 mtpr a3, qemu_vptptr 603 604 ldq_p $sp, PCB_Q_KSP(a2) 605 ldq_p t0, PCB_Q_USP(a2) 606 ldq_p t1, PCB_Q_PTBR(a2) 607 ldl_p t2, PCB_L_PCC(a2) 608 ldq_p t3, PCB_Q_UNIQUE(a2) 609 ldq_p t4, PCB_Q_FEN(a2) 610 611 mtpr t0, qemu_usp 612 613 sll t1, VA_S_OFF, t1 614 mtpr t1, qemu_ptbr 615 616 subl t2, p0, t2 617 mtpr t2, qemu_pcc_ofs 618 619 mtpr t3, qemu_unique 620 621 and t4, 1, t4 622 mtpr t4, qemu_fen 623 624 mtpr $31, qemu_tbia // Flush TLB for new PTBR 625 626 mov a1, $26 627 mov a1, $27 628 hw_ret (a1) 629ENDFN CallPal_SwpPal_Cont 630 .previous 631 632 ORG_CALL_PAL_PRIV(0x0B) 633CallPal_OpcDec0B: 634 br CallPal_OpcDec 635ENDFN CallPal_OpcDec0B 636 637 ORG_CALL_PAL_PRIV(0x0C) 638CallPal_OpcDec0C: 639 br CallPal_OpcDec 640ENDFN CallPal_OpcDec0C 641 642/* 643 * Write Interprocessor Interrupt Request 644 * 645 * INPUT PARAMETERS: 646 * 647 * r16 (a0) = target processor number 648 * 649 * OUTPUT PARAMETERS: 650 * 651 * SIDE EFFECTS: 652 * 653 */ 654 ORG_CALL_PAL_PRIV(0x0D) 655CallPal_WrIpir: 656 // Save a copy of the return address in case of machine check. 657 mfpr p6, qemu_exc_addr 658 659 SYS_WRIPIR a0, p0, p1, p2 660 661 hw_rei 662ENDFN CallPal_WrIpir 663 664 ORG_CALL_PAL_PRIV(0x0E) 665CallPal_OpcDec0E: 666 br CallPal_OpcDec 667ENDFN CallPal_OpcDec0E 668 669 ORG_CALL_PAL_PRIV(0x0F) 670CallPal_OpcDec0F: 671 br CallPal_OpcDec 672ENDFN CallPal_OpcDec0F 673 674/* 675 * Read Machine Check Error Summary 676 * 677 * INPUT PARAMETERS: 678 * 679 * OUTPUT PARAMETERS: 680 * 681 * r0 (v0) = returned MCES value 682 * 683 * SIDE EFFECTS: 684 * 685 */ 686 ORG_CALL_PAL_PRIV(0x10) 687CallPal_RdMces: 688 mfpr v0, ptMces // Get current MCES value 689 and v0, MCES_M_ALL, v0 // Clear all other bits 690 hw_rei 691ENDFN CallPal_RdMces 692 693/* 694 * Write Machine Check Error Summary 695 * 696 * INPUT PARAMETERS: 697 * 698 * r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4> 699 * 700 * OUTPUT PARAMETERS: 701 * 702 * SIDE EFFECTS: 703 * 704 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 705 */ 706 ORG_CALL_PAL_PRIV(0x11) 707CallPal_WrMces: 708 // Clear MIP, SCE, PCE 709 and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0 710 mfpr p1, ptMces 711 bic p1, p0, p1 712 713 // Copy DPC and DSC 714 and a0, (MCES_M_DPC | MCES_M_DSC), p0 715 bic p1, (MCES_M_DPC | MCES_M_DSC), p1 716 or p1, p0, p1 717 718 mtpr p1, ptMces 719 hw_rei 720ENDFN CallPal_WrMces 721 722 ORG_CALL_PAL_PRIV(0x12) 723CallPal_OpcDec12: 724 br CallPal_OpcDec 725ENDFN CallPal_OpcDec12 726 727 ORG_CALL_PAL_PRIV(0x13) 728CallPal_OpcDec13: 729 br CallPal_OpcDec 730ENDFN CallPal_OpcDec13 731 732 ORG_CALL_PAL_PRIV(0x14) 733CallPal_OpcDec14: 734 br CallPal_OpcDec 735ENDFN CallPal_OpcDec14 736 737 ORG_CALL_PAL_PRIV(0x15) 738CallPal_OpcDec15: 739 br CallPal_OpcDec 740ENDFN CallPal_OpcDec15 741 742 ORG_CALL_PAL_PRIV(0x16) 743CallPal_OpcDec16: 744 br CallPal_OpcDec 745ENDFN CallPal_OpcDec16 746 747 ORG_CALL_PAL_PRIV(0x17) 748CallPal_OpcDec17: 749 br CallPal_OpcDec 750ENDFN CallPal_OpcDec17 751 752 ORG_CALL_PAL_PRIV(0x18) 753CallPal_OpcDec18: 754 br CallPal_OpcDec 755ENDFN CallPal_OpcDec18 756 757 ORG_CALL_PAL_PRIV(0x19) 758CallPal_OpcDec19: 759 br CallPal_OpcDec 760ENDFN CallPal_OpcDec19 761 762 ORG_CALL_PAL_PRIV(0x1A) 763CallPal_OpcDec1A: 764 br CallPal_OpcDec 765ENDFN CallPal_OpcDec1A 766 767 ORG_CALL_PAL_PRIV(0x1B) 768CallPal_OpcDec1B: 769 br CallPal_OpcDec 770ENDFN CallPal_OpcDec1B 771 772 ORG_CALL_PAL_PRIV(0x1C) 773CallPal_OpcDec1C: 774 br CallPal_OpcDec 775ENDFN CallPal_OpcDec1C 776 777 ORG_CALL_PAL_PRIV(0x1D) 778CallPal_OpcDec1D: 779 br CallPal_OpcDec 780ENDFN CallPal_OpcDec1D 781 782 ORG_CALL_PAL_PRIV(0x1E) 783CallPal_OpcDec1E: 784 br CallPal_OpcDec 785ENDFN CallPal_OpcDec1E 786 787 ORG_CALL_PAL_PRIV(0x1F) 788CallPal_OpcDec1F: 789 br CallPal_OpcDec 790ENDFN CallPal_OpcDec1F 791 792 ORG_CALL_PAL_PRIV(0x20) 793CallPal_OpcDec20: 794 br CallPal_OpcDec 795ENDFN CallPal_OpcDec20 796 797 ORG_CALL_PAL_PRIV(0x21) 798CallPal_OpcDec21: 799 br CallPal_OpcDec 800ENDFN CallPal_OpcDec21 801 802 ORG_CALL_PAL_PRIV(0x22) 803CallPal_OpcDec22: 804 br CallPal_OpcDec 805ENDFN CallPal_OpcDec22 806 807 ORG_CALL_PAL_PRIV(0x23) 808CallPal_OpcDec23: 809 br CallPal_OpcDec 810ENDFN CallPal_OpcDec23 811 812 ORG_CALL_PAL_PRIV(0x24) 813CallPal_OpcDec24: 814 br CallPal_OpcDec 815ENDFN CallPal_OpcDec24 816 817 ORG_CALL_PAL_PRIV(0x25) 818CallPal_OpcDec25: 819 br CallPal_OpcDec 820ENDFN CallPal_OpcDec25 821 822 ORG_CALL_PAL_PRIV(0x26) 823CallPal_OpcDec26: 824 br CallPal_OpcDec 825ENDFN CallPal_OpcDec26 826 827 ORG_CALL_PAL_PRIV(0x27) 828CallPal_OpcDec27: 829 br CallPal_OpcDec 830ENDFN CallPal_OpcDec27 831 832 ORG_CALL_PAL_PRIV(0x28) 833CallPal_OpcDec28: 834 br CallPal_OpcDec 835ENDFN CallPal_OpcDec28 836 837 ORG_CALL_PAL_PRIV(0x29) 838CallPal_OpcDec29: 839 br CallPal_OpcDec 840ENDFN CallPal_OpcDec29 841 842 ORG_CALL_PAL_PRIV(0x2A) 843CallPal_OpcDec2A: 844 br CallPal_OpcDec 845ENDFN CallPal_OpcDec2A 846 847/* 848 * Write Floating Point Enable 849 * 850 * INPUT PARAMETERS: 851 * 852 * r16 (a0) = ICSR<FPE> <- a0<0> 853 * 854 * SIDE EFFECTS: 855 * 856 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 857 */ 858 ORG_CALL_PAL_PRIV(0x2B) 859CallPal_WrFen: 860 mfpr p0, ptPcbb // Get PCBB 861 and a0, 1, a0 // Clean new FEN value to single bit 862 mtpr a0, qemu_fen 863 stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN> 864 hw_rei 865ENDFN CallPal_WrFen 866 867 ORG_CALL_PAL_PRIV(0x2C) 868CallPal_OpcDec2C: 869 br CallPal_OpcDec 870ENDFN CallPal_OpcDec2C 871 872/* 873 * Write Virtual Page Table Pointer 874 * 875 * INPUT PARAMETERS: 876 * 877 * r16 (a0) = New virtual page table pointer 878 * 879 * SIDE EFFECTS: 880 * 881 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 882 */ 883 ORG_CALL_PAL_PRIV(0x2D) 884CallPal_WrVptPtr: 885 mtpr a0, qemu_vptptr 886 hw_rei 887ENDFN CallPal_WrVptPtr 888 889 ORG_CALL_PAL_PRIV(0x2E) 890CallPal_OpcDec2E: 891 br CallPal_OpcDec 892ENDFN CallPal_OpcDec2E 893 894 ORG_CALL_PAL_PRIV(0x2F) 895CallPal_OpcDec2F: 896 br CallPal_OpcDec 897ENDFN CallPal_OpcDec2F 898 899/* 900 * Swap Process Context 901 * 902 * FUNCTIONAL DESCRIPTION: 903 * 904 * The swap process context (swpctx) function saves 905 * the current process data in the current PCB, then 906 * switches to the PCB passed in a0 and loads the 907 * new process context. The old PCB is returned in v0. 908 * 909 * INPUT PARAMETERS: 910 * 911 * r16 (a0) = New PCBB 912 * 913 * OUTPUT PARAMETERS: 914 * 915 * r0 (v0) = Old PCBB 916 * 917 * SIDE EFFECTS: 918 * 919 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 920 */ 921 ORG_CALL_PAL_PRIV(0x30) 922CallPal_SwpCtx: 923 rpcc p5 // Get cycle counter 924 mfpr p6, qemu_exc_addr // Save exc_addr for machine check 925 926 mfpr v0, ptPcbb // Get current PCBB 927 mtpr a0, ptPcbb // Save new PCBB 928 srl p5, 32, p7 // Move CC<OFFSET> to low longword 929 930 addl p5, p7, p7 // Accumulate time for old pcb 931 stl_p p7, PCB_L_PCC(v0) 932 933 ldl_p t9, PCB_L_PCC(a0) // Get new PCC 934 subl t9, p5, p5 // Generate and ... 935 mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits 936 937 stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer 938 mfpr t10, qemu_usp // Save old user stack pointer 939 stq_p t10, PCB_Q_USP(v0) 940 941 br CallPal_SwpCtx_Cont 942ENDFN CallPal_SwpCtx 943 944 .text 1 945CallPal_SwpCtx_Cont: 946 ldq_p $sp, PCB_Q_KSP(a0) // Install new stack pointers 947 ldq_p t10, PCB_Q_USP(a0) 948 mtpr t10, qemu_usp 949 950 mfpr t10, qemu_unique // Save old unique value 951 stq_p t10, PCB_Q_UNIQUE(v0) 952 ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value 953 mtpr t10, qemu_unique 954 955 ldq_p t8, PCB_Q_FEN(a0) // Install new FEN 956 and t8, 1, t8 957 mtpr t8, qemu_fen 958 959 // QEMU does not implement an ASN; skip that. 960 961 ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables 962 sll t10, VA_S_OFF, t10 963 mtpr t10, qemu_ptbr 964 mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs 965 966 hw_rei 967ENDFN CallPal_SwpCtx_Cont 968 .previous 969 970/* 971 * Write System Value 972 * 973 * INPUT PARAMETERS: 974 * 975 * r16 (a0) = New system value 976 * 977 * SIDE EFFECTS: 978 * 979 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 980 */ 981 ORG_CALL_PAL_PRIV(0x31) 982CallPal_WrVal: 983 mtpr a0, qemu_sysval 984 hw_rei 985ENDFN CallPal_WrVal 986 987/* 988 * Read System Value 989 * 990 * OUTPUT PARAMETERS: 991 * 992 * r0 (v0) = Returned system value 993 * 994 * SIDE EFFECTS: 995 * 996 * Registers t0 and t8..t11 are UNPREDICTABLE upon return. 997 */ 998 ORG_CALL_PAL_PRIV(0x32) 999CallPal_RdVal: 1000 mfpr v0, qemu_sysval 1001 hw_rei 1002ENDFN CallPal_RdVal 1003 1004/* 1005 * Translation Buffer Invalidate 1006 * 1007 * INPUT PARAMETERS: 1008 * 1009 * r16 (a0) = tbi selector type: 1010 * 1011 * -2 - Flush all TB entries (tbia) 1012 * -1 - Invalidate all TB entries with ASM=0 (tbiap) 1013 * 1 - Invalidate ITB entry for va=a1 (tbisi) 1014 * 2 - Invalidate DTB entry for va=a1 (tbisd) 1015 * 3 - Invalidate both ITB and DTB entry for va=a1 (tbis) 1016 * 1017 * r17 (a1) = VA for TBISx types 1018 * 1019 * Qemu does not implement ASNs or split I/D tlbs. Therefore these 1020 * collapse to tbia and tbis. 1021 * 1022 * SIDE EFFECTS: 1023 * 1024 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 1025 */ 1026 ORG_CALL_PAL_PRIV(0x33) 1027CallPal_Tbi: 1028 bge a0, 1f 1029 1030 mtpr $31, qemu_tbia 1031 hw_rei 1032 10331: mtpr a1, qemu_tbis 1034 hw_rei 1035ENDFN CallPal_Tbi 1036 1037/* 1038 * Write System Entry Address 1039 * 1040 * INPUT PARAMETERS: 1041 * 1042 * r16 (a0) = VA of system entry point 1043 * r17 (a1) = System entry point selector 1044 * 1045 * SIDE EFFECTS: 1046 * 1047 * Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE 1048 * upon return. 1049 */ 1050 ORG_CALL_PAL_PRIV(0x34) 1051CallPal_WrEnt: 1052 andnot a0, 3, a0 // Clean PC<1:0> 1053 1054 cmpult a1, 6, t8 // Bound the input 1055 cmoveq t8, 6, a1 1056 1057 br t0, 1f 10581: lda t0, WrEnt_Table-1b(t0) 1059 s8addq a1, t0, t0 1060 jmp $31, (t0), 0 1061ENDFN CallPal_WrEnt 1062 1063 .text 1 1064WrEnt_Table: 10650: mtpr a0, ptEntInt 1066 hw_rei 10671: mtpr a0, ptEntArith 1068 hw_rei 10692: mtpr a0, ptEntMM 1070 hw_rei 10713: mtpr a0, ptEntIF 1072 hw_rei 10734: mtpr a0, ptEntUna 1074 hw_rei 10755: mtpr a0, ptEntSys 1076 hw_rei 10776: nop 1078 hw_rei 1079ENDFN WrEnt_Table 1080 .previous 1081 1082/* 1083 * Swap Interrupt Priority Level 1084 * 1085 * INPUT PARAMETERS: 1086 * 1087 * r16 (a0) = New IPL 1088 * 1089 * OUTPUT PARAMETERS: 1090 * 1091 * r0 (v0) = Old IPL 1092 * 1093 * SIDE EFFECTS: 1094 * 1095 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 1096 */ 1097 ORG_CALL_PAL_PRIV(0x35) 1098CallPal_SwpIpl: 1099 mfpr v0, qemu_ps 1100 and a0, PS_M_IPL, a0 1101 and v0, PS_M_IPL, v0 1102 mtpr a0, qemu_ps 1103 hw_rei 1104ENDFN CallPal_SwpIpl 1105 1106/* 1107 * Read Processor Status 1108 * 1109 * OUTPUT PARAMETERS: 1110 * 1111 * r0 (v0) = Current PS 1112 * 1113 * SIDE EFFECTS: 1114 * 1115 * Registers t0, t8..t11 are UNPREDICTABLE upon return. 1116 */ 1117 ORG_CALL_PAL_PRIV(0x36) 1118CallPal_RdPs: 1119 mfpr v0, qemu_ps 1120 hw_rei 1121ENDFN CallPal_RdPs 1122 1123/* 1124 * Write Kernel Global Pointer 1125 * 1126 * INPUT PARAMETERS: 1127 * 1128 * r16 (a0) = New KGP value 1129 * 1130 * SIDE EFFECTS: 1131 * 1132 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 1133 */ 1134 ORG_CALL_PAL_PRIV(0x37) 1135CallPal_WrKgp: 1136 mtpr a0, ptKgp 1137 hw_rei 1138ENDFN CallPal_WrKgp 1139 1140/* 1141 * Write User Stack Pointer 1142 * 1143 * INPUT PARAMETERS: 1144 * 1145 * r16 (a0) = New user stack pointer value 1146 * 1147 * SIDE EFFECTS: 1148 * 1149 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 1150 */ 1151 ORG_CALL_PAL_PRIV(0x38) 1152CallPal_WrUsp: 1153 mtpr a0, qemu_usp 1154 hw_rei 1155ENDFN CallPal_WrUsp 1156 1157/* 1158 * Write Performance Monitor 1159 * 1160 * INPUT PARAMETERS: 1161 * 1162 * r16 (a0) = New user stack pointer value 1163 * 1164 * SIDE EFFECTS: 1165 * 1166 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return. 1167 */ 1168 ORG_CALL_PAL_PRIV(0x39) 1169CallPal_WrPerfMon: 1170 // Not implemented 1171 hw_rei 1172ENDFN CallPal_WrPerfMon 1173 1174/* 1175 * Read User Stack Pointer 1176 * 1177 * OUTPUT PARAMETERS: 1178 * 1179 * r0 (v0) = User stack pointer value 1180 * 1181 * SIDE EFFECTS: 1182 * 1183 * Registers t0, and t8..t11 are UNPREDICTABLE upon return. 1184 */ 1185 ORG_CALL_PAL_PRIV(0x3A) 1186CallPal_RdUsp: 1187 mfpr v0, qemu_usp 1188 hw_rei 1189ENDFN CallPal_RdUsp 1190 1191 ORG_CALL_PAL_PRIV(0x3B) 1192CallPal_OpcDec3B: 1193 br CallPal_OpcDec 1194ENDFN CallPal_OpcDec3B 1195 1196/* 1197 * Who Am I 1198 * 1199 * OUTPUT PARAMETERS: 1200 * 1201 * r0 (v0) = Current processor number 1202 * 1203 * SIDE EFFECTS: 1204 * 1205 * Registers t0 and t8..t11 are UNPREDICTABLE upon return. 1206 */ 1207 ORG_CALL_PAL_PRIV(0x3C) 1208CallPal_Whami: 1209 SYS_WHAMI v0 1210 hw_rei 1211ENDFN CallPal_Whami 1212 1213/* 1214 * Return From System Call 1215 * 1216 * INPUT PARAMETERS: 1217 * 1218 * r30 (sp) = Pointer to the top of the kernel stack 1219 * 1220 * OUTPUT PARAMETERS: 1221 * 1222 * r29 (gp) = Restored user mode global pointer 1223 * r30 (sp) = User stack pointer 1224 * 1225 * SIDE EFFECTS: 1226 * 1227 * Registers t0 and t8..t11 are UNPREDICTABLE upon return. 1228 */ 1229 ORG_CALL_PAL_PRIV(0x3D) 1230CallPal_RetSys: 1231 ldq t9, FRM_Q_PC($sp) // Pop the return address 1232 ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer 1233 lda t8, FRM_K_SIZE($sp) 1234 mtpr t8, ptKsp 1235 1236 mov PS_K_USER, t8 // Set new mode to user 1237 mtpr t8, qemu_ps 1238 1239 mfpr $sp, qemu_usp // Get the user stack pointer 1240 1241 andnot t9, 3, t9 // Clean return PC<1:0> 1242 hw_ret (t9) 1243ENDFN CallPal_RetSys 1244 1245/* 1246 * Wait For Interrupt 1247 * 1248 * FUNCTIONAL DESCRIPTION: 1249 * 1250 * If possible, wait for the first of either of the following 1251 * conditions before returning: any interrupt other than a clock 1252 * tick; or the first clock tick after a specified number of clock 1253 * ticks have bbeen skipped. 1254 * 1255 * INPUT PARAMETERS: 1256 * 1257 * r16 (a0) = Maximum number of clock ticks to skip 1258 * 1259 * OUTPUT PARAMETERS: 1260 * 1261 * r0 (v0) = Number of clock ticks actually skipped. 1262 */ 1263 ORG_CALL_PAL_PRIV(0x3E) 1264CallPal_WtInt: 1265 mtpr $31, qemu_wait 1266 mov 0, v0 1267 hw_rei 1268ENDFN CallPal_WtInt 1269 1270/* 1271 * Return From Trap, Fault, or Interrupt 1272 * 1273 * INPUT PARAMETERS: 1274 * 1275 * r30 (sp) = Pointer to the top of the kernel stack 1276 * 1277 * OUTPUT PARAMETERS: 1278 * 1279 * ps <- (sp+00) 1280 * pc <- (sp+08) 1281 * r29 (gp) <- (sp+16) 1282 * r16 (a0) <- (sp+24) 1283 * r17 (a1) <- (sp+32) 1284 * r18 (a2) <- (sp+40) 1285 */ 1286 ORG_CALL_PAL_PRIV(0x3F) 1287 .globl CallPal_Rti 1288CallPal_Rti: 1289 mfpr p6, qemu_exc_addr // Save exc_addr for machine check 1290 1291 ldq p4, FRM_Q_PS($sp) // Get the PS 1292 ldq p5, FRM_Q_PC($sp) // Get the return PC 1293 ldq $gp, FRM_Q_GP($sp) // Get gp 1294 ldq a0, FRM_Q_A0($sp) // Get a0 1295 ldq a1, FRM_Q_A1($sp) // Get a1 1296 ldq a2, FRM_Q_A2($sp) // Get a2 1297 lda $sp, FRM_K_SIZE($sp) // Pop the stack 1298 1299 andnot p5, 3, p5 // Clean return PC<1:0> 1300 1301 and p4, PS_M_CM, p3 1302 bne p3, CallPal_Rti_ToUser 1303 1304 and p4, PS_M_IPL, p4 1305 mtpr p4, qemu_ps 1306 hw_ret (p5) 1307ENDFN CallPal_Rti 1308 1309 .text 1 1310CallPal_Rti_ToUser: 1311 mtpr p3, qemu_ps 1312 mtpr $sp, ptKsp 1313 mfpr $sp, qemu_usp 1314 hw_ret (p5) 1315ENDFN CallPal_Rti_ToUser 1316 .previous 1317 1318/* 1319 * OSF/1 Unprivileged CALL_PAL Entry Points 1320 */ 1321 1322#define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80) 1323 1324/* 1325 * A helper routine for the unprivaledged kernel entry points, since the 1326 * actual stack frame setup code is just a tad too large to fit inline. 1327 * 1328 * INPUT PARAMETERS: 1329 * 1330 * p5 = ps 1331 * p6 = exc_addr 1332 * p7 = return address 1333 * 1334 * SIDE EFFECTS: 1335 * 1336 * p0 is clobbered 1337 * 1338 */ 1339 .text 1 1340CallPal_Stack_Frame: 1341 // Test if we're currently in user mode 1342 and p5, PS_M_CM, p0 1343 beq p0, 0f 1344CallPal_Stack_Frame_FromUser: 1345 // Switch to kernel mode 1346 mtpr $31, qemu_ps 1347 mtpr $sp, qemu_usp 1348 mfpr $sp, ptKsp 13490: 1350 // Allocate the stack frame 1351 lda $sp, -FRM_K_SIZE($sp) 1352 stq p5, FRM_Q_PS($sp) 1353 stq p6, FRM_Q_PC($sp) 1354 stq $gp, FRM_Q_GP($sp) 1355 stq a0, FRM_Q_A0($sp) 1356 stq a1, FRM_Q_A1($sp) 1357 stq a2, FRM_Q_A2($sp) 1358 ret $31, (p7), 0 1359ENDFN CallPal_Stack_Frame 1360 .previous 1361 1362/* 1363 * Breakpoint Trap 1364 * 1365 * OUTPUT PARAMETERS: 1366 * 1367 * r16 (a0) = Code for bpt (0) 1368 * r17 (a1) = UNPREDICTABLE 1369 * r18 (a2) = UNPREDICTABLE 1370 */ 1371 ORG_CALL_PAL_UNPRIV(0x80) 1372CallPal_Bpt: 1373 mfpr p5, qemu_ps 1374 mfpr p6, qemu_exc_addr 1375 bsr p7, CallPal_Stack_Frame 1376 1377 mfpr p0, ptEntIF 1378 mfpr $gp, ptKgp 1379 mov IF_K_BPT, a0 1380 hw_ret (p0) 1381ENDFN CallPal_Bpt 1382 1383/* 1384 * Bugcheck Trap 1385 * 1386 * OUTPUT PARAMETERS: 1387 * 1388 * r16 (a0) = Code for bugchk (1) 1389 * r17 (a1) = UNPREDICTABLE 1390 * r18 (a2) = UNPREDICTABLE 1391 */ 1392 ORG_CALL_PAL_UNPRIV(0x81) 1393CallPal_BugChk: 1394 mfpr p5, qemu_ps 1395 mfpr p6, qemu_exc_addr 1396 bsr p7, CallPal_Stack_Frame 1397 1398 mfpr p0, ptEntIF 1399 mfpr $gp, ptKgp 1400 mov IF_K_BUGCHK, a0 1401 hw_ret (p0) 1402ENDFN CallPal_BugChk 1403 1404 1405 ORG_CALL_PAL_UNPRIV(0x82) 1406CallPal_OpcDec82: 1407 br CallPal_OpcDec 1408ENDFN CallPal_OpcDec82 1409 1410/* 1411 * System Call 1412 */ 1413 ORG_CALL_PAL_UNPRIV(0x83) 1414CallPal_CallSys: 1415 mfpr p5, qemu_ps 1416 mfpr p6, qemu_exc_addr 1417 1418 and p5, PS_M_CM, p0 1419 beq p0, 0f 1420 1421 bsr p7, CallPal_Stack_Frame_FromUser 1422 1423 mfpr p0, ptEntSys 1424 mfpr $gp, ptKgp 1425 hw_ret (p0) 1426 14270: subq p6, 4, p6 // Get PC of CALL_PAL insn 1428 lda p0, MCHK_K_OS_BUGCHECK 1429 br MchkLogOut 1430ENDFN CallPal_CallSys 1431 1432 ORG_CALL_PAL_UNPRIV(0x84) 1433CallPal_OpcDec84: 1434 br CallPal_OpcDec 1435ENDFN CallPal_OpcDec84 1436 1437 ORG_CALL_PAL_UNPRIV(0x85) 1438CallPal_OpcDec85: 1439 br CallPal_OpcDec 1440ENDFN CallPal_OpcDec85 1441 1442 1443/* 1444 * I-Stream Memory Barrier 1445 * 1446 * For QEMU, this is of course a no-op. 1447 */ 1448 ORG_CALL_PAL_UNPRIV(0x86) 1449CallPal_Imb: 1450 mb 1451 hw_rei 1452ENDFN CallPal_Imb 1453 1454 1455 ORG_CALL_PAL_UNPRIV(0x87) 1456CallPal_OpcDec87: 1457 br CallPal_OpcDec 1458ENDFN CallPal_OpcDec87 1459 1460 ORG_CALL_PAL_UNPRIV(0x88) 1461CallPal_OpcDec88: 1462 br CallPal_OpcDec 1463ENDFN CallPal_OpcDec88 1464 1465 ORG_CALL_PAL_UNPRIV(0x89) 1466CallPal_OpcDec89: 1467 br CallPal_OpcDec 1468ENDFN CallPal_OpcDec89 1469 1470 ORG_CALL_PAL_UNPRIV(0x8A) 1471CallPal_OpcDec8A: 1472 br CallPal_OpcDec 1473ENDFN CallPal_OpcDec8A 1474 1475 ORG_CALL_PAL_UNPRIV(0x8B) 1476CallPal_OpcDec8B: 1477 br CallPal_OpcDec 1478ENDFN CallPal_OpcDec8B 1479 1480 ORG_CALL_PAL_UNPRIV(0x8C) 1481CallPal_OpcDec8C: 1482 br CallPal_OpcDec 1483ENDFN CallPal_OpcDec8C 1484 1485 ORG_CALL_PAL_UNPRIV(0x8D) 1486CallPal_OpcDec8D: 1487 br CallPal_OpcDec 1488ENDFN CallPal_OpcDec8D 1489 1490 ORG_CALL_PAL_UNPRIV(0x8E) 1491CallPal_OpcDec8E: 1492 br CallPal_OpcDec 1493ENDFN CallPal_OpcDec8E 1494 1495 ORG_CALL_PAL_UNPRIV(0x8F) 1496CallPal_OpcDec8F: 1497 br CallPal_OpcDec 1498ENDFN CallPal_OpcDec8F 1499 1500 ORG_CALL_PAL_UNPRIV(0x90) 1501CallPal_OpcDec90: 1502 br CallPal_OpcDec 1503ENDFN CallPal_OpcDec90 1504 1505 ORG_CALL_PAL_UNPRIV(0x91) 1506CallPal_OpcDec91: 1507 br CallPal_OpcDec 1508ENDFN CallPal_OpcDec91 1509 1510 ORG_CALL_PAL_UNPRIV(0x92) 1511CallPal_OpcDec92: 1512 br CallPal_OpcDec 1513ENDFN CallPal_OpcDec92 1514 1515 ORG_CALL_PAL_UNPRIV(0x93) 1516CallPal_OpcDec93: 1517 br CallPal_OpcDec 1518ENDFN CallPal_OpcDec93 1519 1520 ORG_CALL_PAL_UNPRIV(0x94) 1521CallPal_OpcDec94: 1522 br CallPal_OpcDec 1523ENDFN CallPal_OpcDec94 1524 1525 ORG_CALL_PAL_UNPRIV(0x95) 1526CallPal_OpcDec95: 1527 br CallPal_OpcDec 1528ENDFN CallPal_OpcDec95 1529 1530 ORG_CALL_PAL_UNPRIV(0x96) 1531CallPal_OpcDec96: 1532 br CallPal_OpcDec 1533ENDFN CallPal_OpcDec96 1534 1535 ORG_CALL_PAL_UNPRIV(0x97) 1536CallPal_OpcDec97: 1537 br CallPal_OpcDec 1538ENDFN CallPal_OpcDec97 1539 1540 ORG_CALL_PAL_UNPRIV(0x98) 1541CallPal_OpcDec98: 1542 br CallPal_OpcDec 1543ENDFN CallPal_OpcDec98 1544 1545 ORG_CALL_PAL_UNPRIV(0x99) 1546CallPal_OpcDec99: 1547 br CallPal_OpcDec 1548ENDFN CallPal_OpcDec99 1549 1550 ORG_CALL_PAL_UNPRIV(0x9A) 1551CallPal_OpcDec9A: 1552 br CallPal_OpcDec 1553ENDFN CallPal_OpcDec9A 1554 1555 ORG_CALL_PAL_UNPRIV(0x9B) 1556CallPal_OpcDec9B: 1557 br CallPal_OpcDec 1558ENDFN CallPal_OpcDec9B 1559 1560 ORG_CALL_PAL_UNPRIV(0x9C) 1561CallPal_OpcDec9C: 1562 br CallPal_OpcDec 1563ENDFN CallPal_OpcDec9C 1564 1565 ORG_CALL_PAL_UNPRIV(0x9D) 1566CallPal_OpcDec9D: 1567 br CallPal_OpcDec 1568ENDFN CallPal_OpcDec9D 1569 1570/* 1571 * Read Unique Value 1572 * 1573 * OUTPUT PARAMETERS: 1574 * 1575 * r0 (v0) = Returned process unique value 1576*/ 1577 ORG_CALL_PAL_UNPRIV(0x9E) 1578CallPal_RdUnique: 1579 mfpr v0, qemu_unique 1580 hw_rei 1581ENDFN CallPal_RdUnique 1582 1583/* 1584 * Write Unique Value 1585 * 1586 * INPUT PARAMETERS: 1587 * 1588 * r16 (a0) = New process unique value 1589 */ 1590 ORG_CALL_PAL_UNPRIV(0x9F) 1591CallPal_WrUnique: 1592 mtpr a0, qemu_unique 1593 hw_rei 1594ENDFN CallPal_WrUnique 1595 1596 ORG_CALL_PAL_UNPRIV(0xA0) 1597CallPal_OpcDecA0: 1598 br CallPal_OpcDec 1599ENDFN CallPal_OpcDecA0 1600 1601 ORG_CALL_PAL_UNPRIV(0xA1) 1602CallPal_OpcDecA1: 1603 br CallPal_OpcDec 1604ENDFN CallPal_OpcDecA1 1605 1606 ORG_CALL_PAL_UNPRIV(0xA2) 1607CallPal_OpcDecA2: 1608 br CallPal_OpcDec 1609ENDFN CallPal_OpcDecA2 1610 1611 ORG_CALL_PAL_UNPRIV(0xA3) 1612CallPal_OpcDecA3: 1613 br CallPal_OpcDec 1614ENDFN CallPal_OpcDecA3 1615 1616 ORG_CALL_PAL_UNPRIV(0xA4) 1617CallPal_OpcDecA4: 1618 br CallPal_OpcDec 1619ENDFN CallPal_OpcDecA4 1620 1621 ORG_CALL_PAL_UNPRIV(0xA5) 1622CallPal_OpcDecA5: 1623 br CallPal_OpcDec 1624ENDFN CallPal_OpcDecA5 1625 1626 ORG_CALL_PAL_UNPRIV(0xA6) 1627CallPal_OpcDecA6: 1628 br CallPal_OpcDec 1629ENDFN CallPal_OpcDecA6 1630 1631 ORG_CALL_PAL_UNPRIV(0xA7) 1632CallPal_OpcDecA7: 1633 br CallPal_OpcDec 1634ENDFN CallPal_OpcDecA7 1635 1636 ORG_CALL_PAL_UNPRIV(0xA8) 1637CallPal_OpcDecA8: 1638 br CallPal_OpcDec 1639ENDFN CallPal_OpcDecA8 1640 1641 ORG_CALL_PAL_UNPRIV(0xA9) 1642CallPal_OpcDecA9: 1643 br CallPal_OpcDec 1644ENDFN CallPal_OpcDecA9 1645 1646/* 1647 * Generate Trap 1648 * 1649 * OUTPUT PARAMETERS: 1650 * 1651 * r16 (a0) = Code for gentrap (2) 1652 * r17 (a1) = UNPREDICTABLE 1653 * r18 (a2) = UNPREDICTABLE 1654 */ 1655 ORG_CALL_PAL_UNPRIV(0xAA) 1656CallPal_GenTrap: 1657 mfpr p5, qemu_ps 1658 mfpr p6, qemu_exc_addr 1659 bsr p7, CallPal_Stack_Frame 1660 1661 mfpr p0, ptEntIF 1662 mfpr $gp, ptKgp 1663 mov IF_K_GENTRAP, a0 1664 hw_ret (p0) 1665ENDFN CallPal_GenTrap 1666 1667 ORG_CALL_PAL_UNPRIV(0xAB) 1668CallPal_OpcDecAB: 1669 br CallPal_OpcDec 1670ENDFN CallPal_OpcDecAB 1671 1672 ORG_CALL_PAL_UNPRIV(0xAC) 1673CallPal_OpcDecAC: 1674 br CallPal_OpcDec 1675ENDFN CallPal_OpcDecAC 1676 1677 ORG_CALL_PAL_UNPRIV(0xAD) 1678CallPal_OpcDecAD: 1679 br CallPal_OpcDec 1680ENDFN CallPal_OpcDecAD 1681 1682 ORG_CALL_PAL_UNPRIV(0xAE) 1683CallPal_OpcDecAE: 1684 br CallPal_OpcDec 1685ENDFN CallPal_OpcDecAE 1686 1687 ORG_CALL_PAL_UNPRIV(0xAF) 1688CallPal_OpcDecAF: 1689 br CallPal_OpcDec 1690ENDFN CallPal_OpcDecAF 1691 1692 ORG_CALL_PAL_UNPRIV(0xB0) 1693CallPal_OpcDecB0: 1694 br CallPal_OpcDec 1695ENDFN CallPal_OpcDecB0 1696 1697 ORG_CALL_PAL_UNPRIV(0xB1) 1698CallPal_OpcDecB1: 1699 br CallPal_OpcDec 1700ENDFN CallPal_OpcDecB1 1701 1702 ORG_CALL_PAL_UNPRIV(0xB2) 1703CallPal_OpcDecB2: 1704 br CallPal_OpcDec 1705ENDFN CallPal_OpcDecB2 1706 1707 ORG_CALL_PAL_UNPRIV(0xB3) 1708CallPal_OpcDecB3: 1709 br CallPal_OpcDec 1710ENDFN CallPal_OpcDecB3 1711 1712 ORG_CALL_PAL_UNPRIV(0xB4) 1713CallPal_OpcDecB4: 1714 br CallPal_OpcDec 1715ENDFN CallPal_OpcDecB4 1716 1717 ORG_CALL_PAL_UNPRIV(0xB5) 1718CallPal_OpcDecB5: 1719 br CallPal_OpcDec 1720ENDFN CallPal_OpcDecB5 1721 1722 ORG_CALL_PAL_UNPRIV(0xB6) 1723CallPal_OpcDecB6: 1724 br CallPal_OpcDec 1725ENDFN CallPal_OpcDecB6 1726 1727 ORG_CALL_PAL_UNPRIV(0xB7) 1728CallPal_OpcDecB7: 1729 br CallPal_OpcDec 1730ENDFN CallPal_OpcDecB7 1731 1732 ORG_CALL_PAL_UNPRIV(0xB8) 1733CallPal_OpcDecB8: 1734 br CallPal_OpcDec 1735ENDFN CallPal_OpcDecB8 1736 1737 ORG_CALL_PAL_UNPRIV(0xB9) 1738CallPal_OpcDecB9: 1739 br CallPal_OpcDec 1740ENDFN CallPal_OpcDecB9 1741 1742 ORG_CALL_PAL_UNPRIV(0xBA) 1743CallPal_OpcDecBA: 1744 br CallPal_OpcDec 1745ENDFN CallPal_OpcDecBA 1746 1747 ORG_CALL_PAL_UNPRIV(0xBB) 1748CallPal_OpcDecBB: 1749 br CallPal_OpcDec 1750ENDFN CallPal_OpcDecBB 1751 1752 ORG_CALL_PAL_UNPRIV(0xBC) 1753CallPal_OpcDecBC: 1754 br CallPal_OpcDec 1755ENDFN CallPal_OpcDecBC 1756 1757 ORG_CALL_PAL_UNPRIV(0xBD) 1758CallPal_OpcDecBD: 1759 br CallPal_OpcDec 1760ENDFN CallPal_OpcDecBD 1761 1762 ORG_CALL_PAL_UNPRIV(0xBE) 1763CallPal_OpcDecBE: 1764 br CallPal_OpcDec 1765ENDFN CallPal_OpcDecBE 1766 1767 ORG_CALL_PAL_UNPRIV(0xBF) 1768CallPal_OpcDec: 1769 mfpr p5, qemu_ps 1770 mfpr p6, qemu_exc_addr 1771 bsr p7, CallPal_Stack_Frame 1772 1773 mfpr p0, ptEntIF 1774 mfpr $gp, ptKgp 1775 mov IF_K_OPCDEC, a0 1776 hw_ret (p0) 1777ENDFN CallPal_OpcDec 1778 1779 .org 0x3000 1780 .text 1 1781/* 1782 * Build Machine Check Logout Frame 1783 * 1784 * This portion of the machine check handler builds a logout frame 1785 * in the PAL impure scratch area, builds a stack frame on the kernel 1786 * stack (already built if there was an interrupt machine check), 1787 * loads the GP with the KGP, loads the machine check entry 1788 * code in a0, loads a platform-specific interrupt vector 1789 * (typically the same value as the SCB offset) in a1, loads 1790 * the kseg address of the logout area in a2, and dispatches 1791 * to the kernel interrupt handler pointed to by the entInt 1792 * operating system entry point. 1793 * 1794 * INPUT PARAMETERS: 1795 * 1796 * r8 (p0) = Machine check reason 1797 * r14 (p6) = Exception address 1798 * 1799 * OUTPUT PARAMETERS: 1800 * 1801 * a0 (r16) = Machine check entry type 1802 * a1 (r17) = Platform-specific interrupt vector 1803 * a2 (r18) = Pointer to logout area 1804 */ 1805 1806#define MCHK_COMMON_SIZE 24 1807#define MCHK_LOGOUT_SIZE 144 1808 1809MchkLogOut: 1810 mfpr p1, qemu_ps 1811 1812 // ??? Apparently we skip the insn that caused the mchk. 1813 // ??? This is used by the kernel for mcheck_expected. 1814 addq p6, 4, p6 1815 1816 STACK_FRAME p1, p6, p2, 0 1817 1818 // Restore the real EXC_ADDR for the logout frame. 1819 subq p6, 4, p6 1820 1821 // Locate logout frame 1822 br $gp, .+4 1823 ldah $gp, 0($gp) !gpdisp!2 1824 lda $gp, 0($gp) !gpdisp!2 1825 ldah p1, mchk_logout($gp) !gprelhigh 1826 lda p1, mchk_logout(p1) !gprellow 1827 1828 SYS_WHAMI p2 1829 mull p2, MCHK_LOGOUT_SIZE, p2 1830 addq p2, p1, a2 1831 1832 // Populate the minimal logout frame 1833 lda p2, MCHK_LOGOUT_SIZE 1834 stl p2, 0(a2) // size 1835 stl $31, 4(a2) // flags 1836 lda p1, MCHK_COMMON_SIZE 1837 stl p1, 8(a2) // proc_offset 1838 stl p2, 12(a2) // sys_offset 1839 stl p0, 16(a2) // mchk_code 1840 stl $31, 20(a2) // frame_rev 1841 1842 // EV6 portion, format copied from Linux kernel 1843 // although there's not much we can fill in. 1844 stq $31, 24(a2) // I_STAT 1845 stq $31, 32(a2) // DC_STAT 1846 stq $31, 40(a2) // C_ADDR 1847 stq $31, 48(a2) // DC1_SYNDROME 1848 stq $31, 56(a2) // DC0_SYNDROME 1849 stq $31, 64(a2) // C_STAT 1850 stq $31, 72(a2) // C_STS 1851 stq $31, 80(a2) // MM_STAT 1852 stq p6, 88(a2) // EXC_ADDR 1853 stq $31, 96(a2) // IER_CM 1854 stq $31, 104(a2) // ISUM 1855 stq $31, 112(a2) // RESERVED0 1856 mfpr p2, qemu_palbr 1857 stq p2, 120(a2) // PAL_BASE 1858 stq $31, 128(a2) // I_CTL 1859 stq $31, 136(a2) // PCTX 1860 1861 mov IPL_K_MCHK, p1 // Raise IPL 1862 mtpr p1, qemu_ps 1863 1864 mfpr p6, ptEntInt 1865 mfpr $gp, ptKgp 1866 lda a0, INT_K_MCHK 1867 lda a1, 0 // "vector" 1868 1869 hw_ret (p6) 1870ENDFN MchkLogOut 1871 1872MchkDouble: 1873 bsr p7, UpdatePCB 1874 lda v0, HLT_K_DBL_MCHK 1875 br Sys_EnterConsole 1876ENDFN MchkDouble 1877 1878MchkBugCheck: 1879MchkFromPal: 1880 bsr p7, UpdatePCB 1881 lda v0, HLT_K_MCHK_FROM_PAL 1882 br Sys_EnterConsole 1883ENDFN MchkFromPal 1884 1885MchkKspInvalid: 1886 bsr p7, UpdatePCB 1887 lda v0, HLT_K_KSP_INVAL 1888 br Sys_EnterConsole 1889ENDFN MchkKspInvalid 1890 1891/* 1892 * Update the current PCB with new SP and CC info. 1893 * 1894 * INPUT PARAMETERS: 1895 * 1896 * p7 = return linkage 1897 */ 1898 1899UpdatePCB: 1900 rpcc p5 1901 mfpr p4, ptPcbb 1902 1903 mfpr p3, qemu_ps // Check current mode 1904 and p3, PS_M_CM, p3 1905 beq p3, 1f 1906 1907 mtpr $sp, qemu_usp // Save user stack pointer 1908 stq_p $sp, PCB_Q_USP(p4) 1909 br 2f 1910 19111: mtpr $sp, ptKsp // Save kernel stack pointer 1912 stq_p $sp, PCB_Q_KSP(p4) 1913 19142: srl p5, 32, p3 // Merge for new time 1915 addl p5, p3, p3 1916 stl_p p3, PCB_L_PCC(p4) // Store new time 1917 1918 mfpr p5, qemu_unique // Save unique 1919 stq_p p5, PCB_Q_UNIQUE(p4) 1920 1921 ret $31, (p7), 0 1922ENDFN UpdatePCB 1923 1924/* 1925 * FIXME 1926 */ 1927Sys_EnterConsole: 1928 halt 1929 1930/* 1931 * Allocate the initial bootup stack. 1932 */ 1933 1934 .section .bss.stack 1935 .align 3 1936 .globl stack 1937 .type stack,@object 1938 .size stack,STACK_SIZE * 4 1939stack: .skip STACK_SIZE * 4 1940 1941 .globl mchk_logout 1942 .type mchk_logout,@object 1943 .size mchk_logout,MCHK_LOGOUT_SIZE * 4 1944mchk_logout: 1945 .skip MCHK_LOGOUT_SIZE * 4 1946