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.
485 ENDFN Cserve_Set_Alarm_Rel
486 Cserve_Set_Alarm_Abs:
489 ENDFN Cserve_Set_Alarm_Abs
493 ENDFN Cserve_Get_VM_Time
497 // ??? For SRM compatibility and their use within Linux, use 52/53
498 // for these. Anyone know what other "standard" SRM Cserve entry
499 // points are? Certainly we don't want to be compatible with MILO,
500 // which puts the selector at A2.
506 ENDFN CallPal_Cserve_Cont
512 * FUNCTIONAL DESCRIPTION:
514 * The swap PALcode (swppal) function replaces the current
515 * (active) PALcode by the specified new PALcode image.
516 * This function is intended for use by operating systems
517 * only during bootstraps and restarts, or during transitions
518 * to console I/O mode.
520 * The PALcode descriptor passed in a0 is interpreted as
521 * either a PALcode variant or the base physical address
522 * of the new PALcode image. If a variant, the PALcode
523 * image must have been previously loaded. No PALcode
524 * loading occurs as a result of this function.
527 * This implementation of SWPPAL does not support PALcode
528 * variants. If a variant is specified in a0, a check is
529 * performed to determine whether the variant is OSF/1 or
530 * not and the returned status is either unknown variant
531 * (if not OSF/1) or variant not loaded.
535 * r16 (a0) = New PALcode variant or base physical address
538 * r19 (a3) = New VptPtr
542 * r0 (v0) = Returned status indicating:
543 * 0 - Success (PALcode was switched)
544 * 1 - Unknown PALcode variant
545 * 2 - Known PALcode variant, but PALcode not loaded
547 * r26 (ra) = r27 (pv) = New PC
548 * Note that this is non-architected, but is relied on by
549 * the usage of SwpPal within our own console code in order
550 * to simplify its use within C code.
553 ORG_CALL_PAL_PRIV(0x0A)
555 // Save a copy of the return address in case of machine check.
556 mfpr p6, qemu_exc_addr
558 // Accept swapping to OSF PALcode. The side effect here is to
559 // load the other parameters for the kernel.
561 bne v0, CallPal_SwpPal_Cont
563 // Return as an unknown PALcode variant
574 ldq_p $sp, PCB_Q_KSP(a2)
575 ldq_p t0, PCB_Q_USP(a2)
576 ldq_p t1, PCB_Q_PTBR(a2)
577 ldl_p t2, PCB_L_PCC(a2)
578 ldq_p t3, PCB_Q_UNIQUE(a2)
579 ldq_p t4, PCB_Q_FEN(a2)
587 mtpr t2, qemu_pcc_ofs
594 mtpr $31, qemu_tbia // Flush TLB for new PTBR
599 ENDFN CallPal_SwpPal_Cont
602 ORG_CALL_PAL_PRIV(0x0B)
605 ENDFN CallPal_OpcDec0B
607 ORG_CALL_PAL_PRIV(0x0C)
610 ENDFN CallPal_OpcDec0C
613 * Write Interprocessor Interrupt Request
617 * r16 (a0) = target processor number
624 ORG_CALL_PAL_PRIV(0x0D)
626 // Save a copy of the return address in case of machine check.
627 mfpr p6, qemu_exc_addr
629 SYS_WRIPIR a0, p0, p1, p2
634 ORG_CALL_PAL_PRIV(0x0E)
637 ENDFN CallPal_OpcDec0E
639 ORG_CALL_PAL_PRIV(0x0F)
642 ENDFN CallPal_OpcDec0F
645 * Read Machine Check Error Summary
651 * r0 (v0) = returned MCES value
656 ORG_CALL_PAL_PRIV(0x10)
658 mfpr v0, ptMces // Get current MCES value
659 and v0, MCES_M_ALL, v0 // Clear all other bits
664 * Write Machine Check Error Summary
668 * r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4>
674 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
676 ORG_CALL_PAL_PRIV(0x11)
678 // Clear MIP, SCE, PCE
679 and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
684 and a0, (MCES_M_DPC | MCES_M_DSC), p0
685 bic p1, (MCES_M_DPC | MCES_M_DSC), p1
692 ORG_CALL_PAL_PRIV(0x12)
695 ENDFN CallPal_OpcDec12
697 ORG_CALL_PAL_PRIV(0x13)
700 ENDFN CallPal_OpcDec13
702 ORG_CALL_PAL_PRIV(0x14)
705 ENDFN CallPal_OpcDec14
707 ORG_CALL_PAL_PRIV(0x15)
710 ENDFN CallPal_OpcDec15
712 ORG_CALL_PAL_PRIV(0x16)
715 ENDFN CallPal_OpcDec16
717 ORG_CALL_PAL_PRIV(0x17)
720 ENDFN CallPal_OpcDec17
722 ORG_CALL_PAL_PRIV(0x18)
725 ENDFN CallPal_OpcDec18
727 ORG_CALL_PAL_PRIV(0x19)
730 ENDFN CallPal_OpcDec19
732 ORG_CALL_PAL_PRIV(0x1A)
735 ENDFN CallPal_OpcDec1A
737 ORG_CALL_PAL_PRIV(0x1B)
740 ENDFN CallPal_OpcDec1B
742 ORG_CALL_PAL_PRIV(0x1C)
745 ENDFN CallPal_OpcDec1C
747 ORG_CALL_PAL_PRIV(0x1D)
750 ENDFN CallPal_OpcDec1D
752 ORG_CALL_PAL_PRIV(0x1E)
755 ENDFN CallPal_OpcDec1E
757 ORG_CALL_PAL_PRIV(0x1F)
760 ENDFN CallPal_OpcDec1F
762 ORG_CALL_PAL_PRIV(0x20)
765 ENDFN CallPal_OpcDec20
767 ORG_CALL_PAL_PRIV(0x21)
770 ENDFN CallPal_OpcDec21
772 ORG_CALL_PAL_PRIV(0x22)
775 ENDFN CallPal_OpcDec22
777 ORG_CALL_PAL_PRIV(0x23)
780 ENDFN CallPal_OpcDec23
782 ORG_CALL_PAL_PRIV(0x24)
785 ENDFN CallPal_OpcDec24
787 ORG_CALL_PAL_PRIV(0x25)
790 ENDFN CallPal_OpcDec25
792 ORG_CALL_PAL_PRIV(0x26)
795 ENDFN CallPal_OpcDec26
797 ORG_CALL_PAL_PRIV(0x27)
800 ENDFN CallPal_OpcDec27
802 ORG_CALL_PAL_PRIV(0x28)
805 ENDFN CallPal_OpcDec28
807 ORG_CALL_PAL_PRIV(0x29)
810 ENDFN CallPal_OpcDec29
812 ORG_CALL_PAL_PRIV(0x2A)
815 ENDFN CallPal_OpcDec2A
818 * Write Floating Point Enable
822 * r16 (a0) = ICSR<FPE> <- a0<0>
826 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
828 ORG_CALL_PAL_PRIV(0x2B)
830 mfpr p0, ptPcbb // Get PCBB
831 and a0, 1, a0 // Clean new FEN value to single bit
833 stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN>
837 ORG_CALL_PAL_PRIV(0x2C)
840 ENDFN CallPal_OpcDec2C
843 * Write Virtual Page Table Pointer
847 * r16 (a0) = New virtual page table pointer
851 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
853 ORG_CALL_PAL_PRIV(0x2D)
857 ENDFN CallPal_WrVptPtr
859 ORG_CALL_PAL_PRIV(0x2E)
862 ENDFN CallPal_OpcDec2E
864 ORG_CALL_PAL_PRIV(0x2F)
867 ENDFN CallPal_OpcDec2F
870 * Swap Process Context
872 * FUNCTIONAL DESCRIPTION:
874 * The swap process context (swpctx) function saves
875 * the current process data in the current PCB, then
876 * switches to the PCB passed in a0 and loads the
877 * new process context. The old PCB is returned in v0.
881 * r16 (a0) = New PCBB
889 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
891 ORG_CALL_PAL_PRIV(0x30)
893 rpcc p5 // Get cycle counter
894 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
896 mfpr v0, ptPcbb // Get current PCBB
897 mtpr a0, ptPcbb // Save new PCBB
898 srl p5, 32, p7 // Move CC<OFFSET> to low longword
900 addl p5, p7, p7 // Accumulate time for old pcb
901 stl_p p7, PCB_L_PCC(v0)
903 ldl_p t9, PCB_L_PCC(a0) // Get new PCC
904 subl t9, p5, p5 // Generate and ...
905 mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits
907 stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer
908 mfpr t10, qemu_usp // Save old user stack pointer
909 stq_p t10, PCB_Q_USP(v0)
911 br CallPal_SwpCtx_Cont
916 ldq_p $sp, PCB_Q_KSP(a0) // Install new stack pointers
917 ldq_p t10, PCB_Q_USP(a0)
920 mfpr t10, qemu_unique // Save old unique value
921 stq_p t10, PCB_Q_UNIQUE(v0)
922 ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
923 mtpr t10, qemu_unique
925 ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
929 // QEMU does not implement an ASN; skip that.
931 ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
932 sll t10, VA_S_OFF, t10
934 mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
937 ENDFN CallPal_SwpCtx_Cont
945 * r16 (a0) = New system value
949 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
951 ORG_CALL_PAL_PRIV(0x31)
962 * r0 (v0) = Returned system value
966 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
968 ORG_CALL_PAL_PRIV(0x32)
975 * Translation Buffer Invalidate
979 * r16 (a0) = tbi selector type:
981 * -2 - Flush all TB entries (tbia)
982 * -1 - Invalidate all TB entries with ASM=0 (tbiap)
983 * 1 - Invalidate ITB entry for va=a1 (tbisi)
984 * 2 - Invalidate DTB entry for va=a1 (tbisd)
985 * 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
987 * r17 (a1) = VA for TBISx types
989 * Qemu does not implement ASNs or split I/D tlbs. Therefore these
990 * collapse to tbia and tbis.
994 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
996 ORG_CALL_PAL_PRIV(0x33)
1003 1: mtpr a1, qemu_tbis
1008 * Write System Entry Address
1012 * r16 (a0) = VA of system entry point
1013 * r17 (a1) = System entry point selector
1017 * Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
1020 ORG_CALL_PAL_PRIV(0x34)
1022 andnot a0, 3, a0 // Clean PC<1:0>
1024 cmpult a1, 6, t8 // Bound the input
1028 1: lda t0, WrEnt_Table-1b(t0)
1035 0: mtpr a0, ptEntInt
1037 1: mtpr a0, ptEntArith
1043 4: mtpr a0, ptEntUna
1045 5: mtpr a0, ptEntSys
1053 * Swap Interrupt Priority Level
1057 * r16 (a0) = New IPL
1059 * OUTPUT PARAMETERS:
1065 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1067 ORG_CALL_PAL_PRIV(0x35)
1070 and a0, PS_M_IPL, a0
1071 and v0, PS_M_IPL, v0
1074 ENDFN CallPal_SwpIpl
1077 * Read Processor Status
1079 * OUTPUT PARAMETERS:
1081 * r0 (v0) = Current PS
1085 * Registers t0, t8..t11 are UNPREDICTABLE upon return.
1087 ORG_CALL_PAL_PRIV(0x36)
1094 * Write Kernel Global Pointer
1098 * r16 (a0) = New KGP value
1102 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1104 ORG_CALL_PAL_PRIV(0x37)
1111 * Write User Stack Pointer
1115 * r16 (a0) = New user stack pointer value
1119 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1121 ORG_CALL_PAL_PRIV(0x38)
1128 * Write Performance Monitor
1132 * r16 (a0) = New user stack pointer value
1136 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1138 ORG_CALL_PAL_PRIV(0x39)
1142 ENDFN CallPal_WrPerfMon
1145 * Read User Stack Pointer
1147 * OUTPUT PARAMETERS:
1149 * r0 (v0) = User stack pointer value
1153 * Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1155 ORG_CALL_PAL_PRIV(0x3A)
1161 ORG_CALL_PAL_PRIV(0x3B)
1164 ENDFN CallPal_OpcDec3B
1169 * OUTPUT PARAMETERS:
1171 * r0 (v0) = Current processor number
1175 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1177 ORG_CALL_PAL_PRIV(0x3C)
1184 * Return From System Call
1188 * r30 (sp) = Pointer to the top of the kernel stack
1190 * OUTPUT PARAMETERS:
1192 * r29 (gp) = Restored user mode global pointer
1193 * r30 (sp) = User stack pointer
1197 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1199 ORG_CALL_PAL_PRIV(0x3D)
1201 ldq t9, FRM_Q_PC($sp) // Pop the return address
1202 ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer
1203 lda t8, FRM_K_SIZE($sp)
1206 mov PS_K_USER, t8 // Set new mode to user
1209 mfpr $sp, qemu_usp // Get the user stack pointer
1211 andnot t9, 3, t9 // Clean return PC<1:0>
1213 ENDFN CallPal_RetSys
1216 * Wait For Interrupt
1218 * FUNCTIONAL DESCRIPTION:
1220 * If possible, wait for the first of either of the following
1221 * conditions before returning: any interrupt other than a clock
1222 * tick; or the first clock tick after a specified number of clock
1223 * ticks have bbeen skipped.
1227 * r16 (a0) = Maximum number of clock ticks to skip
1229 * OUTPUT PARAMETERS:
1231 * r0 (v0) = Number of clock ticks actually skipped.
1233 ORG_CALL_PAL_PRIV(0x3E)
1241 * Return From Trap, Fault, or Interrupt
1245 * r30 (sp) = Pointer to the top of the kernel stack
1247 * OUTPUT PARAMETERS:
1251 * r29 (gp) <- (sp+16)
1252 * r16 (a0) <- (sp+24)
1253 * r17 (a1) <- (sp+32)
1254 * r18 (a2) <- (sp+40)
1256 ORG_CALL_PAL_PRIV(0x3F)
1259 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
1261 ldq p4, FRM_Q_PS($sp) // Get the PS
1262 ldq p5, FRM_Q_PC($sp) // Get the return PC
1263 ldq $gp, FRM_Q_GP($sp) // Get gp
1264 ldq a0, FRM_Q_A0($sp) // Get a0
1265 ldq a1, FRM_Q_A1($sp) // Get a1
1266 ldq a2, FRM_Q_A2($sp) // Get a2
1267 lda $sp, FRM_K_SIZE($sp) // Pop the stack
1269 andnot p5, 3, p5 // Clean return PC<1:0>
1272 bne p3, CallPal_Rti_ToUser
1274 and p4, PS_M_IPL, p4
1285 ENDFN CallPal_Rti_ToUser
1289 * OSF/1 Unprivileged CALL_PAL Entry Points
1292 #define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80)
1295 * A helper routine for the unprivaledged kernel entry points, since the
1296 * actual stack frame setup code is just a tad too large to fit inline.
1302 * p7 = return address
1310 CallPal_Stack_Frame:
1311 // Test if we're currently in user mode
1314 CallPal_Stack_Frame_FromUser:
1315 // Switch to kernel mode
1320 // Allocate the stack frame
1321 lda $sp, -FRM_K_SIZE($sp)
1322 stq p5, FRM_Q_PS($sp)
1323 stq p6, FRM_Q_PC($sp)
1324 stq $gp, FRM_Q_GP($sp)
1325 stq a0, FRM_Q_A0($sp)
1326 stq a1, FRM_Q_A1($sp)
1327 stq a2, FRM_Q_A2($sp)
1329 ENDFN CallPal_Stack_Frame
1335 * OUTPUT PARAMETERS:
1337 * r16 (a0) = Code for bpt (0)
1338 * r17 (a1) = UNPREDICTABLE
1339 * r18 (a2) = UNPREDICTABLE
1341 ORG_CALL_PAL_UNPRIV(0x80)
1344 mfpr p6, qemu_exc_addr
1345 bsr p7, CallPal_Stack_Frame
1356 * OUTPUT PARAMETERS:
1358 * r16 (a0) = Code for bugchk (1)
1359 * r17 (a1) = UNPREDICTABLE
1360 * r18 (a2) = UNPREDICTABLE
1362 ORG_CALL_PAL_UNPRIV(0x81)
1365 mfpr p6, qemu_exc_addr
1366 bsr p7, CallPal_Stack_Frame
1372 ENDFN CallPal_BugChk
1375 ORG_CALL_PAL_UNPRIV(0x82)
1378 ENDFN CallPal_OpcDec82
1383 ORG_CALL_PAL_UNPRIV(0x83)
1386 mfpr p6, qemu_exc_addr
1391 bsr p7, CallPal_Stack_Frame_FromUser
1397 0: subq p6, 4, p6 // Get PC of CALL_PAL insn
1399 ENDFN CallPal_CallSys
1401 ORG_CALL_PAL_UNPRIV(0x84)
1404 ENDFN CallPal_OpcDec84
1406 ORG_CALL_PAL_UNPRIV(0x85)
1409 ENDFN CallPal_OpcDec85
1413 * I-Stream Memory Barrier
1415 * For QEMU, this is of course a no-op.
1417 ORG_CALL_PAL_UNPRIV(0x86)
1423 ORG_CALL_PAL_UNPRIV(0x87)
1426 ENDFN CallPal_OpcDec87
1428 ORG_CALL_PAL_UNPRIV(0x88)
1431 ENDFN CallPal_OpcDec88
1433 ORG_CALL_PAL_UNPRIV(0x89)
1436 ENDFN CallPal_OpcDec89
1438 ORG_CALL_PAL_UNPRIV(0x8A)
1441 ENDFN CallPal_OpcDec8A
1443 ORG_CALL_PAL_UNPRIV(0x8B)
1446 ENDFN CallPal_OpcDec8B
1448 ORG_CALL_PAL_UNPRIV(0x8C)
1451 ENDFN CallPal_OpcDec8C
1453 ORG_CALL_PAL_UNPRIV(0x8D)
1456 ENDFN CallPal_OpcDec8D
1458 ORG_CALL_PAL_UNPRIV(0x8E)
1461 ENDFN CallPal_OpcDec8E
1463 ORG_CALL_PAL_UNPRIV(0x8F)
1466 ENDFN CallPal_OpcDec8F
1468 ORG_CALL_PAL_UNPRIV(0x90)
1471 ENDFN CallPal_OpcDec90
1473 ORG_CALL_PAL_UNPRIV(0x91)
1476 ENDFN CallPal_OpcDec91
1478 ORG_CALL_PAL_UNPRIV(0x92)
1481 ENDFN CallPal_OpcDec92
1483 ORG_CALL_PAL_UNPRIV(0x93)
1486 ENDFN CallPal_OpcDec93
1488 ORG_CALL_PAL_UNPRIV(0x94)
1491 ENDFN CallPal_OpcDec94
1493 ORG_CALL_PAL_UNPRIV(0x95)
1496 ENDFN CallPal_OpcDec95
1498 ORG_CALL_PAL_UNPRIV(0x96)
1501 ENDFN CallPal_OpcDec96
1503 ORG_CALL_PAL_UNPRIV(0x97)
1506 ENDFN CallPal_OpcDec97
1508 ORG_CALL_PAL_UNPRIV(0x98)
1511 ENDFN CallPal_OpcDec98
1513 ORG_CALL_PAL_UNPRIV(0x99)
1516 ENDFN CallPal_OpcDec99
1518 ORG_CALL_PAL_UNPRIV(0x9A)
1521 ENDFN CallPal_OpcDec9A
1523 ORG_CALL_PAL_UNPRIV(0x9B)
1526 ENDFN CallPal_OpcDec9B
1528 ORG_CALL_PAL_UNPRIV(0x9C)
1531 ENDFN CallPal_OpcDec9C
1533 ORG_CALL_PAL_UNPRIV(0x9D)
1536 ENDFN CallPal_OpcDec9D
1541 * OUTPUT PARAMETERS:
1543 * r0 (v0) = Returned process unique value
1545 ORG_CALL_PAL_UNPRIV(0x9E)
1547 mfpr v0, qemu_unique
1549 ENDFN CallPal_RdUnique
1552 * Write Unique Value
1556 * r16 (a0) = New process unique value
1558 ORG_CALL_PAL_UNPRIV(0x9F)
1560 mtpr a0, qemu_unique
1562 ENDFN CallPal_WrUnique
1564 ORG_CALL_PAL_UNPRIV(0xA0)
1567 ENDFN CallPal_OpcDecA0
1569 ORG_CALL_PAL_UNPRIV(0xA1)
1572 ENDFN CallPal_OpcDecA1
1574 ORG_CALL_PAL_UNPRIV(0xA2)
1577 ENDFN CallPal_OpcDecA2
1579 ORG_CALL_PAL_UNPRIV(0xA3)
1582 ENDFN CallPal_OpcDecA3
1584 ORG_CALL_PAL_UNPRIV(0xA4)
1587 ENDFN CallPal_OpcDecA4
1589 ORG_CALL_PAL_UNPRIV(0xA5)
1592 ENDFN CallPal_OpcDecA5
1594 ORG_CALL_PAL_UNPRIV(0xA6)
1597 ENDFN CallPal_OpcDecA6
1599 ORG_CALL_PAL_UNPRIV(0xA7)
1602 ENDFN CallPal_OpcDecA7
1604 ORG_CALL_PAL_UNPRIV(0xA8)
1607 ENDFN CallPal_OpcDecA8
1609 ORG_CALL_PAL_UNPRIV(0xA9)
1612 ENDFN CallPal_OpcDecA9
1617 * OUTPUT PARAMETERS:
1619 * r16 (a0) = Code for gentrap (2)
1620 * r17 (a1) = UNPREDICTABLE
1621 * r18 (a2) = UNPREDICTABLE
1623 ORG_CALL_PAL_UNPRIV(0xAA)
1626 mfpr p6, qemu_exc_addr
1627 bsr p7, CallPal_Stack_Frame
1631 mov IF_K_GENTRAP, a0
1633 ENDFN CallPal_GenTrap
1635 ORG_CALL_PAL_UNPRIV(0xAB)
1638 ENDFN CallPal_OpcDecAB
1640 ORG_CALL_PAL_UNPRIV(0xAC)
1643 ENDFN CallPal_OpcDecAC
1645 ORG_CALL_PAL_UNPRIV(0xAD)
1648 ENDFN CallPal_OpcDecAD
1650 ORG_CALL_PAL_UNPRIV(0xAE)
1653 ENDFN CallPal_OpcDecAE
1655 ORG_CALL_PAL_UNPRIV(0xAF)
1658 ENDFN CallPal_OpcDecAF
1660 ORG_CALL_PAL_UNPRIV(0xB0)
1663 ENDFN CallPal_OpcDecB0
1665 ORG_CALL_PAL_UNPRIV(0xB1)
1668 ENDFN CallPal_OpcDecB1
1670 ORG_CALL_PAL_UNPRIV(0xB2)
1673 ENDFN CallPal_OpcDecB2
1675 ORG_CALL_PAL_UNPRIV(0xB3)
1678 ENDFN CallPal_OpcDecB3
1680 ORG_CALL_PAL_UNPRIV(0xB4)
1683 ENDFN CallPal_OpcDecB4
1685 ORG_CALL_PAL_UNPRIV(0xB5)
1688 ENDFN CallPal_OpcDecB5
1690 ORG_CALL_PAL_UNPRIV(0xB6)
1693 ENDFN CallPal_OpcDecB6
1695 ORG_CALL_PAL_UNPRIV(0xB7)
1698 ENDFN CallPal_OpcDecB7
1700 ORG_CALL_PAL_UNPRIV(0xB8)
1703 ENDFN CallPal_OpcDecB8
1705 ORG_CALL_PAL_UNPRIV(0xB9)
1708 ENDFN CallPal_OpcDecB9
1710 ORG_CALL_PAL_UNPRIV(0xBA)
1713 ENDFN CallPal_OpcDecBA
1715 ORG_CALL_PAL_UNPRIV(0xBB)
1718 ENDFN CallPal_OpcDecBB
1720 ORG_CALL_PAL_UNPRIV(0xBC)
1723 ENDFN CallPal_OpcDecBC
1725 ORG_CALL_PAL_UNPRIV(0xBD)
1728 ENDFN CallPal_OpcDecBD
1730 ORG_CALL_PAL_UNPRIV(0xBE)
1733 ENDFN CallPal_OpcDecBE
1735 ORG_CALL_PAL_UNPRIV(0xBF)
1738 mfpr p6, qemu_exc_addr
1739 bsr p7, CallPal_Stack_Frame
1745 ENDFN CallPal_OpcDec
1750 * PALcode detected processor machine check handler.
1752 * The PALcode-detected machine check handler loads a code
1753 * indicating the type of machine check error, loads
1754 * the System Control Block (SCB) vector for the
1755 * processor machine check service routine, sets the
1756 * Machine-Check-In-Progress (MIP) flag in the Machine
1757 * Check Error Summary register (MCES), and merges
1758 * with the common machine check flow.
1760 * If a second processor machine check error condition
1761 * is detected while the MIP flag is set, the processor
1762 * is forced into console I/O mode indicating "double
1763 * error abort encountered" as the reason for the halt.
1767 * Called when an internal processor error is detected
1768 * that cannot be successfully corrected by hardware or
1773 * r14 (p6) = Exception address
1775 * OUTPUT PARAMETERS:
1777 * ptMchk0 = saved v0
1778 * ptMchk1 = saved t0
1779 * ptMchk2 = saved t3
1780 * ptMchk3 = saved t4
1781 * ptMchk4 = saved t5
1782 * ptMchk5 = saved exc_addr
1783 * ptMisc<47:32> = MCHK code
1784 * ptMisc<31:16> = SCB vector
1789 * r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
1790 * PAL temporaries and are available for use as scratch
1791 * registers by the system specific machine check
1801 * Common Machine Check Handler
1810 * ptMchk5 Saved exc_addr
1811 * ptMisc<47:32> MCHK code
1812 * ptMisc<31:16> SCB vector
1815 * Registers v0, t0, and t3 .. t5 are available for use, in
1816 * addition to the shadow registers.
1824 * Build Machine Check Logout Frame
1826 * This portion of the machine check handler builds a logout frame
1827 * in the PAL impure scratch area, builds a stack frame on the kernel
1828 * stack (already built if there was an interrupt machine check),
1829 * loads the GP with the KGP, loads the machine check entry
1830 * code in a0, loads a platform-specific interrupt vector
1831 * (typically the same value as the SCB offset) in a1, loads
1832 * the kseg address of the logout area in a2, and dispatches
1833 * to the kernel interrupt handler pointed to by the entInt
1834 * operating system entry point.
1836 * OUTPUT PARAMETERS:
1838 * a0 (r16) = Machine check entry type
1839 * a1 (r17) = Platform-specific interrupt vector
1840 * a2 (r18) = Pointer to logout area
1843 .macro STORE_IPR which, offset, base
1845 stq_p v0, \offset(\base)
1854 lda v0, HLT_K_DBL_MCHK
1860 lda v0, HLT_K_MCHK_FROM_PAL
1866 lda v0, HLT_K_KSP_INVAL
1868 ENDFN MchkKspInvalid
1871 * Update the current PCB with new SP and CC info.
1875 * p7 = return linkage
1882 mfpr p3, qemu_ps // Check current mode
1886 mtpr $sp, qemu_usp // Save user stack pointer
1887 stq_p $sp, PCB_Q_USP(p4)
1890 1: mtpr $sp, ptKsp // Save kernel stack pointer
1891 stq_p $sp, PCB_Q_KSP(p4)
1893 2: srl p5, 32, p3 // Merge for new time
1895 stl_p p3, PCB_L_PCC(p4) // Store new time
1897 mfpr p5, qemu_unique // Save unique
1898 stq_p p5, PCB_Q_UNIQUE(p4)
1910 * Allocate the initial bootup stack.
1917 .size stack,STACK_SIZE
1918 stack: .skip STACK_SIZE