1 /* QEMU Emulation PALcode.
3 Copyright (C) 2011 Richard Henderson
5 This file is part of QEMU PALcode.
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.
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.
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/>. */
30 * Create a standard kernel entry stack frame.
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
37 // Switch to kernel mode
43 // Allocate the stack frame
44 0: 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)
54 * Allocate a 1 page stack for use by the console.
56 #define STACK_SIZE 8192
59 * QEMU emulator "hardware" entry points.
67 * trap_arg0 = Memory size
68 * trap_arg1 = Kernel entry (if loaded)
75 ldah $gp, 0($gp) !gpdisp!1
76 lda $gp, 0($gp) !gpdisp!1
79 // Disable interrupts; kernel mode
88 ldah t1, stack($gp) !gprelhigh
89 lda t1, stack(t1) !gprellow
92 // Do any necessary system setup required for PALmode,
93 // e.g. setting up ptSys[01].
96 // Non-boot CPUs can go wait now.
99 // Load boot arguments
100 mfpr a0, qemu_trap_arg0
101 mfpr a1, qemu_trap_arg1
102 mfpr a2, qemu_trap_arg2
104 // Continue in do_start, outside PALmode.
105 ldah $27, do_start($gp) !gprelhigh
106 lda $27, do_start($27) !gprellow
109 1: ldah $27, do_start_wait($gp) !gprelhigh
110 lda $27, do_start_wait($27) !gprellow
129 * Interprocessor Interrupt
137 * The interprocessor interrupt is special, in that PALcode is supposed
138 * to clear the interupt and not wait for the OS to do it.
142 mfpr p6, qemu_exc_addr
144 SYS_ACK_SMP p0, p1, p2
148 STACK_FRAME p0, p6, p2, 0
150 mov IPL_K_IP, p0 // Raise IPL
160 ENDFN Pal_Smp_Interrupt
171 * The clock interrupt is special, in that PALcode is supposed
172 * to clear the interupt and not wait for the OS to do it.
176 mfpr p6, qemu_exc_addr
178 SYS_ACK_CLK p0, p1, p2
182 STACK_FRAME p0, p6, p2, 0
184 mov IPL_K_CLK, p0 // Raise IPL
194 ENDFN Pal_Clk_Interrupt
207 mfpr p6, qemu_exc_addr
210 STACK_FRAME p0, p6, p2, 0
212 mov IPL_K_DEV1, p0 // Raise IPL
215 bsr p7, Sys_Dev_Vector
222 ENDFN Pal_Dev_Interrupt
229 * trap_arg0 = faulting address
230 * trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
231 * trap_arg2 = access type (exec=-1, read=0, write=1)
236 mfpr p6, qemu_exc_addr
237 blbs p6, MchkBugCheck
239 STACK_FRAME p0, p6, p2, 1
243 mfpr a0, qemu_trap_arg0
244 mfpr a1, qemu_trap_arg1
245 mfpr a2, qemu_trap_arg2
254 * trap_arg0 = faulting address
255 * trap_arg1 = opcode of faulting insn
256 * trap_arg2 = src/dst register number
261 mfpr p6, qemu_exc_addr
262 addq p6, 4, p1 // increment past the faulting insn
263 blbs p6, MchkBugCheck
265 STACK_FRAME p0, p1, p2, 1
269 mfpr a0, qemu_trap_arg0
270 mfpr a1, qemu_trap_arg1
271 mfpr a2, qemu_trap_arg2
280 * trap_arg0 = UNDEFINED
281 * trap_arg1 = UNDEFINED
282 * trap_arg2 = UNDEFINED
286 * r16 (a0) = Instruction fault code
287 * r17 (a1) = UNPREDICTABLE
288 * r18 (a2) = UNPREDICTABLE
293 mfpr p6, qemu_exc_addr
294 addq p6, 4, p1 // increment past the faulting insn
295 blbs p6, MchkBugCheck
297 STACK_FRAME p0, p1, p2, 1
310 * trap_arg0 = exception type
311 * trap_arg1 = register modification mask
312 * trap_arg2 = UNDEFINED
317 mfpr p6, qemu_exc_addr
318 blbs p6, MchkBugCheck
320 STACK_FRAME p0, p6, p2, 1
324 mfpr a0, qemu_trap_arg0
325 mfpr a1, qemu_trap_arg1
330 * Floating Point Disabled
334 * trap_arg0 = UNDEFINED
335 * trap_arg1 = UNDEFINED
336 * trap_arg2 = UNDEFINED
340 * r16 (a0) = Instruction fault code
341 * r17 (a1) = UNPREDICTABLE
342 * r18 (a2) = UNPREDICTABLE
347 mfpr p6, qemu_exc_addr
348 blbs p6, MchkBugCheck
350 STACK_FRAME p0, p6, p2, 1
359 * OSF/1 Privileged CALL_PAL Entry Points
362 #define ORG_CALL_PAL_PRIV(X) .org 0x1000+64*X
369 * We either power down the system or re-enter the console.
370 * But given that we're not returning to the kernel, there's
371 * no reason to continue processing in assembler. Go to C.
373 ORG_CALL_PAL_PRIV(0x00)
375 bsr p7, UpdatePCB // Save kernel data
376 lda v0, HLT_K_SW_HALT // FIXME store this somewhere.
386 * For QEMU, this is of course a no-op.
388 ORG_CALL_PAL_PRIV(0x01)
396 * For QEMU, this is of course a no-op.
398 ORG_CALL_PAL_PRIV(0x02)
403 ORG_CALL_PAL_PRIV(0x03)
406 ENDFN CallPal_OpcDec03
408 ORG_CALL_PAL_PRIV(0x04)
411 ENDFN CallPal_OpcDec04
413 ORG_CALL_PAL_PRIV(0x05)
416 ENDFN CallPal_OpcDec05
418 ORG_CALL_PAL_PRIV(0x06)
421 ENDFN CallPal_OpcDec06
423 ORG_CALL_PAL_PRIV(0x07)
426 ENDFN CallPal_OpcDec07
428 ORG_CALL_PAL_PRIV(0x08)
431 ENDFN CallPal_OpcDec08
438 * r16 (a0) = Option selector
439 * r17..r21 (a1..a5) = Implementation specific entry parameters
443 * Registers a0..a5, and v0 are UNPREDICTABLE upon return.
445 ORG_CALL_PAL_PRIV(0x09)
447 // Most of the entries are densely clustered around 0.
452 1: lda p0, Cserve_Table-1b(p0)
459 /* Note that the entries in the following table are all 2 insns.
460 The first entry is unused, and is also where all out-of-range
461 commands are vectored. */
463 br CallPal_Cserve_Cont
473 Cserve_Get_Wall_Time:
474 mfpr v0, qemu_walltime
476 ENDFN Cserve_Get_Wall_Time
480 ENDFN Cserve_Get_Alarm
481 Cserve_Set_Alarm_Rel:
482 // Cheating here: create the absolute time and fall thru.
483 mfpr p0, qemu_walltime
485 ENDFN Cserve_Set_Alarm_Rel
486 Cserve_Set_Alarm_Abs:
489 ENDFN Cserve_Set_Alarm_Abs
492 // ??? For SRM compatibility and their use within Linux, use 52/53
493 // for these. Anyone know what other "standard" SRM Cserve entry
494 // points are? Certainly we don't want to be compatible with MILO,
495 // which puts the selector at A2.
501 ENDFN CallPal_Cserve_Cont
507 * FUNCTIONAL DESCRIPTION:
509 * The swap PALcode (swppal) function replaces the current
510 * (active) PALcode by the specified new PALcode image.
511 * This function is intended for use by operating systems
512 * only during bootstraps and restarts, or during transitions
513 * to console I/O mode.
515 * The PALcode descriptor passed in a0 is interpreted as
516 * either a PALcode variant or the base physical address
517 * of the new PALcode image. If a variant, the PALcode
518 * image must have been previously loaded. No PALcode
519 * loading occurs as a result of this function.
522 * This implementation of SWPPAL does not support PALcode
523 * variants. If a variant is specified in a0, a check is
524 * performed to determine whether the variant is OSF/1 or
525 * not and the returned status is either unknown variant
526 * (if not OSF/1) or variant not loaded.
530 * r16 (a0) = New PALcode variant or base physical address
533 * r19 (a3) = New VptPtr
537 * r0 (v0) = Returned status indicating:
538 * 0 - Success (PALcode was switched)
539 * 1 - Unknown PALcode variant
540 * 2 - Known PALcode variant, but PALcode not loaded
542 * r26 (ra) = r27 (pv) = New PC
543 * Note that this is non-architected, but is relied on by
544 * the usage of SwpPal within our own console code in order
545 * to simplify its use within C code.
548 ORG_CALL_PAL_PRIV(0x0A)
550 // Save a copy of the return address in case of machine check.
551 mfpr p6, qemu_exc_addr
553 // Accept swapping to OSF PALcode. The side effect here is to
554 // load the other parameters for the kernel.
556 bne v0, CallPal_SwpPal_Cont
558 // Return as an unknown PALcode variant
569 ldq_p $sp, PCB_Q_KSP(a2)
570 ldq_p t0, PCB_Q_USP(a2)
571 ldq_p t1, PCB_Q_PTBR(a2)
572 ldl_p t2, PCB_L_PCC(a2)
573 ldq_p t3, PCB_Q_UNIQUE(a2)
574 ldq_p t4, PCB_Q_FEN(a2)
582 mtpr t2, qemu_pcc_ofs
589 mtpr $31, qemu_tbia // Flush TLB for new PTBR
594 ENDFN CallPal_SwpPal_Cont
597 ORG_CALL_PAL_PRIV(0x0B)
600 ENDFN CallPal_OpcDec0B
602 ORG_CALL_PAL_PRIV(0x0C)
605 ENDFN CallPal_OpcDec0C
608 * Write Interprocessor Interrupt Request
612 * r16 (a0) = target processor number
619 ORG_CALL_PAL_PRIV(0x0D)
621 // Save a copy of the return address in case of machine check.
622 mfpr p6, qemu_exc_addr
624 SYS_WRIPIR a0, p0, p1, p2
629 ORG_CALL_PAL_PRIV(0x0E)
632 ENDFN CallPal_OpcDec0E
634 ORG_CALL_PAL_PRIV(0x0F)
637 ENDFN CallPal_OpcDec0F
640 * Read Machine Check Error Summary
646 * r0 (v0) = returned MCES value
651 ORG_CALL_PAL_PRIV(0x10)
653 mfpr v0, ptMces // Get current MCES value
654 and v0, MCES_M_ALL, v0 // Clear all other bits
659 * Write Machine Check Error Summary
663 * r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4>
669 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
671 ORG_CALL_PAL_PRIV(0x11)
673 // Clear MIP, SCE, PCE
674 and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
679 and a0, (MCES_M_DPC | MCES_M_DSC), p0
680 bic p1, (MCES_M_DPC | MCES_M_DSC), p1
687 ORG_CALL_PAL_PRIV(0x12)
690 ENDFN CallPal_OpcDec12
692 ORG_CALL_PAL_PRIV(0x13)
695 ENDFN CallPal_OpcDec13
697 ORG_CALL_PAL_PRIV(0x14)
700 ENDFN CallPal_OpcDec14
702 ORG_CALL_PAL_PRIV(0x15)
705 ENDFN CallPal_OpcDec15
707 ORG_CALL_PAL_PRIV(0x16)
710 ENDFN CallPal_OpcDec16
712 ORG_CALL_PAL_PRIV(0x17)
715 ENDFN CallPal_OpcDec17
717 ORG_CALL_PAL_PRIV(0x18)
720 ENDFN CallPal_OpcDec18
722 ORG_CALL_PAL_PRIV(0x19)
725 ENDFN CallPal_OpcDec19
727 ORG_CALL_PAL_PRIV(0x1A)
730 ENDFN CallPal_OpcDec1A
732 ORG_CALL_PAL_PRIV(0x1B)
735 ENDFN CallPal_OpcDec1B
737 ORG_CALL_PAL_PRIV(0x1C)
740 ENDFN CallPal_OpcDec1C
742 ORG_CALL_PAL_PRIV(0x1D)
745 ENDFN CallPal_OpcDec1D
747 ORG_CALL_PAL_PRIV(0x1E)
750 ENDFN CallPal_OpcDec1E
752 ORG_CALL_PAL_PRIV(0x1F)
755 ENDFN CallPal_OpcDec1F
757 ORG_CALL_PAL_PRIV(0x20)
760 ENDFN CallPal_OpcDec20
762 ORG_CALL_PAL_PRIV(0x21)
765 ENDFN CallPal_OpcDec21
767 ORG_CALL_PAL_PRIV(0x22)
770 ENDFN CallPal_OpcDec22
772 ORG_CALL_PAL_PRIV(0x23)
775 ENDFN CallPal_OpcDec23
777 ORG_CALL_PAL_PRIV(0x24)
780 ENDFN CallPal_OpcDec24
782 ORG_CALL_PAL_PRIV(0x25)
785 ENDFN CallPal_OpcDec25
787 ORG_CALL_PAL_PRIV(0x26)
790 ENDFN CallPal_OpcDec26
792 ORG_CALL_PAL_PRIV(0x27)
795 ENDFN CallPal_OpcDec27
797 ORG_CALL_PAL_PRIV(0x28)
800 ENDFN CallPal_OpcDec28
802 ORG_CALL_PAL_PRIV(0x29)
805 ENDFN CallPal_OpcDec29
807 ORG_CALL_PAL_PRIV(0x2A)
810 ENDFN CallPal_OpcDec2A
813 * Write Floating Point Enable
817 * r16 (a0) = ICSR<FPE> <- a0<0>
821 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
823 ORG_CALL_PAL_PRIV(0x2B)
825 mfpr p0, ptPcbb // Get PCBB
826 and a0, 1, a0 // Clean new FEN value to single bit
828 stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN>
832 ORG_CALL_PAL_PRIV(0x2C)
835 ENDFN CallPal_OpcDec2C
838 * Write Virtual Page Table Pointer
842 * r16 (a0) = New virtual page table pointer
846 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
848 ORG_CALL_PAL_PRIV(0x2D)
852 ENDFN CallPal_WrVptPtr
854 ORG_CALL_PAL_PRIV(0x2E)
857 ENDFN CallPal_OpcDec2E
859 ORG_CALL_PAL_PRIV(0x2F)
862 ENDFN CallPal_OpcDec2F
865 * Swap Process Context
867 * FUNCTIONAL DESCRIPTION:
869 * The swap process context (swpctx) function saves
870 * the current process data in the current PCB, then
871 * switches to the PCB passed in a0 and loads the
872 * new process context. The old PCB is returned in v0.
876 * r16 (a0) = New PCBB
884 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
886 ORG_CALL_PAL_PRIV(0x30)
888 rpcc p5 // Get cycle counter
889 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
891 mfpr v0, ptPcbb // Get current PCBB
892 mtpr a0, ptPcbb // Save new PCBB
893 srl p5, 32, p7 // Move CC<OFFSET> to low longword
895 addl p5, p7, p7 // Accumulate time for old pcb
896 stl_p p7, PCB_L_PCC(v0)
898 ldl_p t9, PCB_L_PCC(a0) // Get new PCC
899 subl t9, p5, p5 // Generate and ...
900 mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits
902 stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer
903 mfpr t10, qemu_usp // Save old user stack pointer
904 stq_p t10, PCB_Q_USP(v0)
906 br CallPal_SwpCtx_Cont
911 ldq_p $sp, PCB_Q_KSP(a0) // Install new stack pointers
912 ldq_p t10, PCB_Q_USP(a0)
915 mfpr t10, qemu_unique // Save old unique value
916 stq_p t10, PCB_Q_UNIQUE(v0)
917 ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
918 mtpr t10, qemu_unique
920 ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
924 // QEMU does not implement an ASN; skip that.
926 ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
927 sll t10, VA_S_OFF, t10
929 mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
932 ENDFN CallPal_SwpCtx_Cont
940 * r16 (a0) = New system value
944 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
946 ORG_CALL_PAL_PRIV(0x31)
957 * r0 (v0) = Returned system value
961 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
963 ORG_CALL_PAL_PRIV(0x32)
970 * Translation Buffer Invalidate
974 * r16 (a0) = tbi selector type:
976 * -2 - Flush all TB entries (tbia)
977 * -1 - Invalidate all TB entries with ASM=0 (tbiap)
978 * 1 - Invalidate ITB entry for va=a1 (tbisi)
979 * 2 - Invalidate DTB entry for va=a1 (tbisd)
980 * 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
982 * r17 (a1) = VA for TBISx types
984 * Qemu does not implement ASNs or split I/D tlbs. Therefore these
985 * collapse to tbia and tbis.
989 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
991 ORG_CALL_PAL_PRIV(0x33)
998 1: mtpr a1, qemu_tbis
1003 * Write System Entry Address
1007 * r16 (a0) = VA of system entry point
1008 * r17 (a1) = System entry point selector
1012 * Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
1015 ORG_CALL_PAL_PRIV(0x34)
1017 andnot a0, 3, a0 // Clean PC<1:0>
1019 cmpult a1, 6, t8 // Bound the input
1023 1: lda t0, WrEnt_Table-1b(t0)
1030 0: mtpr a0, ptEntInt
1032 1: mtpr a0, ptEntArith
1038 4: mtpr a0, ptEntUna
1040 5: mtpr a0, ptEntSys
1048 * Swap Interrupt Priority Level
1052 * r16 (a0) = New IPL
1054 * OUTPUT PARAMETERS:
1060 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1062 ORG_CALL_PAL_PRIV(0x35)
1065 and a0, PS_M_IPL, a0
1066 and v0, PS_M_IPL, v0
1069 ENDFN CallPal_SwpIpl
1072 * Read Processor Status
1074 * OUTPUT PARAMETERS:
1076 * r0 (v0) = Current PS
1080 * Registers t0, t8..t11 are UNPREDICTABLE upon return.
1082 ORG_CALL_PAL_PRIV(0x36)
1089 * Write Kernel Global Pointer
1093 * r16 (a0) = New KGP value
1097 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1099 ORG_CALL_PAL_PRIV(0x37)
1106 * Write User Stack Pointer
1110 * r16 (a0) = New user stack pointer value
1114 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1116 ORG_CALL_PAL_PRIV(0x38)
1123 * Write Performance Monitor
1127 * r16 (a0) = New user stack pointer value
1131 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1133 ORG_CALL_PAL_PRIV(0x39)
1137 ENDFN CallPal_WrPerfMon
1140 * Read User Stack Pointer
1142 * OUTPUT PARAMETERS:
1144 * r0 (v0) = User stack pointer value
1148 * Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1150 ORG_CALL_PAL_PRIV(0x3A)
1156 ORG_CALL_PAL_PRIV(0x3B)
1159 ENDFN CallPal_OpcDec3B
1164 * OUTPUT PARAMETERS:
1166 * r0 (v0) = Current processor number
1170 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1172 ORG_CALL_PAL_PRIV(0x3C)
1179 * Return From System Call
1183 * r30 (sp) = Pointer to the top of the kernel stack
1185 * OUTPUT PARAMETERS:
1187 * r29 (gp) = Restored user mode global pointer
1188 * r30 (sp) = User stack pointer
1192 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1194 ORG_CALL_PAL_PRIV(0x3D)
1196 ldq t9, FRM_Q_PC($sp) // Pop the return address
1197 ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer
1198 lda t8, FRM_K_SIZE($sp)
1201 mov PS_K_USER, t8 // Set new mode to user
1204 mfpr $sp, qemu_usp // Get the user stack pointer
1206 andnot t9, 3, t9 // Clean return PC<1:0>
1208 ENDFN CallPal_RetSys
1211 * Wait For Interrupt
1213 * FUNCTIONAL DESCRIPTION:
1215 * If possible, wait for the first of either of the following
1216 * conditions before returning: any interrupt other than a clock
1217 * tick; or the first clock tick after a specified number of clock
1218 * ticks have bbeen skipped.
1222 * r16 (a0) = Maximum number of clock ticks to skip
1224 * OUTPUT PARAMETERS:
1226 * r0 (v0) = Number of clock ticks actually skipped.
1228 ORG_CALL_PAL_PRIV(0x3E)
1236 * Return From Trap, Fault, or Interrupt
1240 * r30 (sp) = Pointer to the top of the kernel stack
1242 * OUTPUT PARAMETERS:
1246 * r29 (gp) <- (sp+16)
1247 * r16 (a0) <- (sp+24)
1248 * r17 (a1) <- (sp+32)
1249 * r18 (a2) <- (sp+40)
1251 ORG_CALL_PAL_PRIV(0x3F)
1254 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
1256 ldq p4, FRM_Q_PS($sp) // Get the PS
1257 ldq p5, FRM_Q_PC($sp) // Get the return PC
1258 ldq $gp, FRM_Q_GP($sp) // Get gp
1259 ldq a0, FRM_Q_A0($sp) // Get a0
1260 ldq a1, FRM_Q_A1($sp) // Get a1
1261 ldq a2, FRM_Q_A2($sp) // Get a2
1262 lda $sp, FRM_K_SIZE($sp) // Pop the stack
1264 andnot p5, 3, p5 // Clean return PC<1:0>
1267 bne p3, CallPal_Rti_ToUser
1269 and p4, PS_M_IPL, p4
1280 ENDFN CallPal_Rti_ToUser
1284 * OSF/1 Unprivileged CALL_PAL Entry Points
1287 #define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80)
1290 * A helper routine for the unprivaledged kernel entry points, since the
1291 * actual stack frame setup code is just a tad too large to fit inline.
1297 * p7 = return address
1305 CallPal_Stack_Frame:
1306 // Test if we're currently in user mode
1309 CallPal_Stack_Frame_FromUser:
1310 // Switch to kernel mode
1315 // Allocate the stack frame
1316 lda $sp, -FRM_K_SIZE($sp)
1317 stq p5, FRM_Q_PS($sp)
1318 stq p6, FRM_Q_PC($sp)
1319 stq $gp, FRM_Q_GP($sp)
1320 stq a0, FRM_Q_A0($sp)
1321 stq a1, FRM_Q_A1($sp)
1322 stq a2, FRM_Q_A2($sp)
1324 ENDFN CallPal_Stack_Frame
1330 * OUTPUT PARAMETERS:
1332 * r16 (a0) = Code for bpt (0)
1333 * r17 (a1) = UNPREDICTABLE
1334 * r18 (a2) = UNPREDICTABLE
1336 ORG_CALL_PAL_UNPRIV(0x80)
1339 mfpr p6, qemu_exc_addr
1340 bsr p7, CallPal_Stack_Frame
1351 * OUTPUT PARAMETERS:
1353 * r16 (a0) = Code for bugchk (1)
1354 * r17 (a1) = UNPREDICTABLE
1355 * r18 (a2) = UNPREDICTABLE
1357 ORG_CALL_PAL_UNPRIV(0x81)
1360 mfpr p6, qemu_exc_addr
1361 bsr p7, CallPal_Stack_Frame
1367 ENDFN CallPal_BugChk
1370 ORG_CALL_PAL_UNPRIV(0x82)
1373 ENDFN CallPal_OpcDec82
1378 ORG_CALL_PAL_UNPRIV(0x83)
1381 mfpr p6, qemu_exc_addr
1386 bsr p7, CallPal_Stack_Frame_FromUser
1392 0: subq p6, 4, p6 // Get PC of CALL_PAL insn
1394 ENDFN CallPal_CallSys
1396 ORG_CALL_PAL_UNPRIV(0x84)
1399 ENDFN CallPal_OpcDec84
1401 ORG_CALL_PAL_UNPRIV(0x85)
1404 ENDFN CallPal_OpcDec85
1408 * I-Stream Memory Barrier
1410 * For QEMU, this is of course a no-op.
1412 ORG_CALL_PAL_UNPRIV(0x86)
1418 ORG_CALL_PAL_UNPRIV(0x87)
1421 ENDFN CallPal_OpcDec87
1423 ORG_CALL_PAL_UNPRIV(0x88)
1426 ENDFN CallPal_OpcDec88
1428 ORG_CALL_PAL_UNPRIV(0x89)
1431 ENDFN CallPal_OpcDec89
1433 ORG_CALL_PAL_UNPRIV(0x8A)
1436 ENDFN CallPal_OpcDec8A
1438 ORG_CALL_PAL_UNPRIV(0x8B)
1441 ENDFN CallPal_OpcDec8B
1443 ORG_CALL_PAL_UNPRIV(0x8C)
1446 ENDFN CallPal_OpcDec8C
1448 ORG_CALL_PAL_UNPRIV(0x8D)
1451 ENDFN CallPal_OpcDec8D
1453 ORG_CALL_PAL_UNPRIV(0x8E)
1456 ENDFN CallPal_OpcDec8E
1458 ORG_CALL_PAL_UNPRIV(0x8F)
1461 ENDFN CallPal_OpcDec8F
1463 ORG_CALL_PAL_UNPRIV(0x90)
1466 ENDFN CallPal_OpcDec90
1468 ORG_CALL_PAL_UNPRIV(0x91)
1471 ENDFN CallPal_OpcDec91
1473 ORG_CALL_PAL_UNPRIV(0x92)
1476 ENDFN CallPal_OpcDec92
1478 ORG_CALL_PAL_UNPRIV(0x93)
1481 ENDFN CallPal_OpcDec93
1483 ORG_CALL_PAL_UNPRIV(0x94)
1486 ENDFN CallPal_OpcDec94
1488 ORG_CALL_PAL_UNPRIV(0x95)
1491 ENDFN CallPal_OpcDec95
1493 ORG_CALL_PAL_UNPRIV(0x96)
1496 ENDFN CallPal_OpcDec96
1498 ORG_CALL_PAL_UNPRIV(0x97)
1501 ENDFN CallPal_OpcDec97
1503 ORG_CALL_PAL_UNPRIV(0x98)
1506 ENDFN CallPal_OpcDec98
1508 ORG_CALL_PAL_UNPRIV(0x99)
1511 ENDFN CallPal_OpcDec99
1513 ORG_CALL_PAL_UNPRIV(0x9A)
1516 ENDFN CallPal_OpcDec9A
1518 ORG_CALL_PAL_UNPRIV(0x9B)
1521 ENDFN CallPal_OpcDec9B
1523 ORG_CALL_PAL_UNPRIV(0x9C)
1526 ENDFN CallPal_OpcDec9C
1528 ORG_CALL_PAL_UNPRIV(0x9D)
1531 ENDFN CallPal_OpcDec9D
1536 * OUTPUT PARAMETERS:
1538 * r0 (v0) = Returned process unique value
1540 ORG_CALL_PAL_UNPRIV(0x9E)
1542 mfpr v0, qemu_unique
1544 ENDFN CallPal_RdUnique
1547 * Write Unique Value
1551 * r16 (a0) = New process unique value
1553 ORG_CALL_PAL_UNPRIV(0x9F)
1555 mtpr a0, qemu_unique
1557 ENDFN CallPal_WrUnique
1559 ORG_CALL_PAL_UNPRIV(0xA0)
1562 ENDFN CallPal_OpcDecA0
1564 ORG_CALL_PAL_UNPRIV(0xA1)
1567 ENDFN CallPal_OpcDecA1
1569 ORG_CALL_PAL_UNPRIV(0xA2)
1572 ENDFN CallPal_OpcDecA2
1574 ORG_CALL_PAL_UNPRIV(0xA3)
1577 ENDFN CallPal_OpcDecA3
1579 ORG_CALL_PAL_UNPRIV(0xA4)
1582 ENDFN CallPal_OpcDecA4
1584 ORG_CALL_PAL_UNPRIV(0xA5)
1587 ENDFN CallPal_OpcDecA5
1589 ORG_CALL_PAL_UNPRIV(0xA6)
1592 ENDFN CallPal_OpcDecA6
1594 ORG_CALL_PAL_UNPRIV(0xA7)
1597 ENDFN CallPal_OpcDecA7
1599 ORG_CALL_PAL_UNPRIV(0xA8)
1602 ENDFN CallPal_OpcDecA8
1604 ORG_CALL_PAL_UNPRIV(0xA9)
1607 ENDFN CallPal_OpcDecA9
1612 * OUTPUT PARAMETERS:
1614 * r16 (a0) = Code for gentrap (2)
1615 * r17 (a1) = UNPREDICTABLE
1616 * r18 (a2) = UNPREDICTABLE
1618 ORG_CALL_PAL_UNPRIV(0xAA)
1621 mfpr p6, qemu_exc_addr
1622 bsr p7, CallPal_Stack_Frame
1626 mov IF_K_GENTRAP, a0
1628 ENDFN CallPal_GenTrap
1630 ORG_CALL_PAL_UNPRIV(0xAB)
1633 ENDFN CallPal_OpcDecAB
1635 ORG_CALL_PAL_UNPRIV(0xAC)
1638 ENDFN CallPal_OpcDecAC
1640 ORG_CALL_PAL_UNPRIV(0xAD)
1643 ENDFN CallPal_OpcDecAD
1645 ORG_CALL_PAL_UNPRIV(0xAE)
1648 ENDFN CallPal_OpcDecAE
1650 ORG_CALL_PAL_UNPRIV(0xAF)
1653 ENDFN CallPal_OpcDecAF
1655 ORG_CALL_PAL_UNPRIV(0xB0)
1658 ENDFN CallPal_OpcDecB0
1660 ORG_CALL_PAL_UNPRIV(0xB1)
1663 ENDFN CallPal_OpcDecB1
1665 ORG_CALL_PAL_UNPRIV(0xB2)
1668 ENDFN CallPal_OpcDecB2
1670 ORG_CALL_PAL_UNPRIV(0xB3)
1673 ENDFN CallPal_OpcDecB3
1675 ORG_CALL_PAL_UNPRIV(0xB4)
1678 ENDFN CallPal_OpcDecB4
1680 ORG_CALL_PAL_UNPRIV(0xB5)
1683 ENDFN CallPal_OpcDecB5
1685 ORG_CALL_PAL_UNPRIV(0xB6)
1688 ENDFN CallPal_OpcDecB6
1690 ORG_CALL_PAL_UNPRIV(0xB7)
1693 ENDFN CallPal_OpcDecB7
1695 ORG_CALL_PAL_UNPRIV(0xB8)
1698 ENDFN CallPal_OpcDecB8
1700 ORG_CALL_PAL_UNPRIV(0xB9)
1703 ENDFN CallPal_OpcDecB9
1705 ORG_CALL_PAL_UNPRIV(0xBA)
1708 ENDFN CallPal_OpcDecBA
1710 ORG_CALL_PAL_UNPRIV(0xBB)
1713 ENDFN CallPal_OpcDecBB
1715 ORG_CALL_PAL_UNPRIV(0xBC)
1718 ENDFN CallPal_OpcDecBC
1720 ORG_CALL_PAL_UNPRIV(0xBD)
1723 ENDFN CallPal_OpcDecBD
1725 ORG_CALL_PAL_UNPRIV(0xBE)
1728 ENDFN CallPal_OpcDecBE
1730 ORG_CALL_PAL_UNPRIV(0xBF)
1733 mfpr p6, qemu_exc_addr
1734 bsr p7, CallPal_Stack_Frame
1740 ENDFN CallPal_OpcDec
1745 * PALcode detected processor machine check handler.
1747 * The PALcode-detected machine check handler loads a code
1748 * indicating the type of machine check error, loads
1749 * the System Control Block (SCB) vector for the
1750 * processor machine check service routine, sets the
1751 * Machine-Check-In-Progress (MIP) flag in the Machine
1752 * Check Error Summary register (MCES), and merges
1753 * with the common machine check flow.
1755 * If a second processor machine check error condition
1756 * is detected while the MIP flag is set, the processor
1757 * is forced into console I/O mode indicating "double
1758 * error abort encountered" as the reason for the halt.
1762 * Called when an internal processor error is detected
1763 * that cannot be successfully corrected by hardware or
1768 * r14 (p6) = Exception address
1770 * OUTPUT PARAMETERS:
1772 * ptMchk0 = saved v0
1773 * ptMchk1 = saved t0
1774 * ptMchk2 = saved t3
1775 * ptMchk3 = saved t4
1776 * ptMchk4 = saved t5
1777 * ptMchk5 = saved exc_addr
1778 * ptMisc<47:32> = MCHK code
1779 * ptMisc<31:16> = SCB vector
1784 * r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
1785 * PAL temporaries and are available for use as scratch
1786 * registers by the system specific machine check
1796 * Common Machine Check Handler
1805 * ptMchk5 Saved exc_addr
1806 * ptMisc<47:32> MCHK code
1807 * ptMisc<31:16> SCB vector
1810 * Registers v0, t0, and t3 .. t5 are available for use, in
1811 * addition to the shadow registers.
1819 * Build Machine Check Logout Frame
1821 * This portion of the machine check handler builds a logout frame
1822 * in the PAL impure scratch area, builds a stack frame on the kernel
1823 * stack (already built if there was an interrupt machine check),
1824 * loads the GP with the KGP, loads the machine check entry
1825 * code in a0, loads a platform-specific interrupt vector
1826 * (typically the same value as the SCB offset) in a1, loads
1827 * the kseg address of the logout area in a2, and dispatches
1828 * to the kernel interrupt handler pointed to by the entInt
1829 * operating system entry point.
1831 * OUTPUT PARAMETERS:
1833 * a0 (r16) = Machine check entry type
1834 * a1 (r17) = Platform-specific interrupt vector
1835 * a2 (r18) = Pointer to logout area
1838 .macro STORE_IPR which, offset, base
1840 stq_p v0, \offset(\base)
1849 lda v0, HLT_K_DBL_MCHK
1855 lda v0, HLT_K_MCHK_FROM_PAL
1861 lda v0, HLT_K_KSP_INVAL
1863 ENDFN MchkKspInvalid
1866 * Update the current PCB with new SP and CC info.
1870 * p7 = return linkage
1877 mfpr p3, qemu_ps // Check current mode
1881 mtpr $sp, qemu_usp // Save user stack pointer
1882 stq_p $sp, PCB_Q_USP(p4)
1885 1: mtpr $sp, ptKsp // Save kernel stack pointer
1886 stq_p $sp, PCB_Q_KSP(p4)
1888 2: srl p5, 32, p3 // Merge for new time
1890 stl_p p3, PCB_L_PCC(p4) // Store new time
1892 mfpr p5, qemu_unique // Save unique
1893 stq_p p5, PCB_Q_UNIQUE(p4)
1905 * Allocate the initial bootup stack.
1912 .size stack,STACK_SIZE
1913 stack: .skip STACK_SIZE