7 /* General Purpose Registers. */
25 /* PALcode Shadow Registers. These registers are swapped out when
26 QEMU is in PALmode. Unlike real hardware, there is no enable bit.
27 However, also unlike real hardware, the originals can be accessed
35 #define p6 $14 // Used to save exc_addr for machine check
38 /* QEMU Processor Registers. */
41 #define qemu_pcc_ofs 2
42 #define qemu_trap_arg0 3
43 #define qemu_trap_arg1 4
44 #define qemu_trap_arg2 5
45 #define qemu_exc_addr 6
49 #define qemu_unique 10
50 #define qemu_lock_addr 11
52 #define qemu_shadow0 32
53 #define qemu_shadow1 33
54 #define qemu_shadow2 34
55 #define qemu_shadow3 35
56 #define qemu_shadow4 36
57 #define qemu_shadow5 37
58 #define qemu_shadow6 38
59 #define qemu_shadow7 39
61 /* PALcode Processor Register Private Storage. */
87 /* QEMU function calls, via mtpr. */
91 /* PALcode uses of the private storage slots. */
96 #define ptEntArith pt5
114 * Shortcuts for various PALmode instructions.
118 #define stq_p hw_stq/p
119 #define stl_p hw_stl/p
120 #define ldl_p hw_ldl/p
121 #define ldq_p hw_ldq/p
123 /* QEMU recognizes the EV4/EV5 HW_REI instruction as a special case of
124 the EV6 HW_RET instruction. This pulls the destination address from
125 the EXC_ADDR processor register. */
126 #define hw_rei hw_ret ($31)
129 * Create a standard kernel entry stack frame.
138 #define FRM_K_SIZE 48
140 .macro STACK_FRAME save_ps, save_pc, temp
141 // Test if we're currently in user mode
142 and \save_ps, PS_M_CM, \temp
144 // Switch to kernel mode
148 // Allocate the stack frame
149 0: lda $sp, -FRM_K_SIZE($sp)
150 stq \save_ps, FRM_Q_PS($sp)
151 stq \save_pc, FRM_Q_PC($sp)
152 stq $gp, FRM_Q_GP($sp)
153 stq a0, FRM_Q_A0($sp)
154 stq a1, FRM_Q_A1($sp)
155 stq a2, FRM_Q_A2($sp)
159 * Allocate a 1 page stack for use by the console.
161 #define STACK_SIZE 8192
164 * QEMU emulator "hardware" entry points.
172 * trap_arg0 = Memory size
173 * trap_arg1 = Kernel entry (if loaded)
178 // Initialize GP and stack.
180 ldah $gp, 0($gp) !gpdisp!1
181 lda $gp, 0($gp) !gpdisp!1
184 lda $sp, stack+STACK_SIZE($gp) !gprel
186 // Disable interrupts; kernel mode
190 // Load the initial PCB and page table elements.
191 lda t0, page_dir($gp) !gprel
195 lda t0, pal_pcb($gp) !gprel
199 // Load boot arguments
200 mfpr a0, qemu_trap_arg0
201 mfpr a1, qemu_trap_arg1
202 mfpr a2, qemu_trap_arg2
204 // Continue in do_start, outside PALmode.
205 ldah $27, do_start($gp) !gprelhigh
206 lda $27, do_start($27) !gprellow
220 mfpr p5, ptMces // Get the error summary
221 or p5, MCES_M_MIP, p4 // Set machine-check-in-progress
222 zap p4, 0x3c, p4 // Clear space for MCHK and SCB
225 ldah p0, SCB_Q_PROCMCHK
226 or p4, p0, p4 // Merge in the SCB vector
227 lda p0, MCHK_K_PROC_HERR
228 sll p0, PT16_V_MCHK, p0
229 or p4, p0, p4 // Merge in the MCHK code
232 br MchkCommon_SaveRegs
239 * trap_arg0 = interrupt type
240 * trap_arg1 = UNDEFINED
241 * trap_arg2 = UNDEFINED
245 mfpr p6, qemu_exc_addr
248 STACK_FRAME p0, p6, p2
252 mfpr a0, qemu_trap_arg0
260 * trap_arg0 = faulting address
261 * trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
262 * trap_arg2 = access type (exec=-1, read=0, write=1)
267 mfpr p6, qemu_exc_addr
269 STACK_FRAME p0, p6, p2
273 mfpr a0, qemu_trap_arg0
274 mfpr a1, qemu_trap_arg1
275 mfpr a2, qemu_trap_arg2
283 * trap_arg0 = faulting address
284 * trap_arg1 = opcode of faulting insn
285 * trap_arg2 = src/dst register number
290 mfpr p6, qemu_exc_addr
291 addq p6, 4, p1 // increment past the faulting insn
292 blbs p6, MchkBugCheck
294 STACK_FRAME p0, p1, p2
298 mfpr a0, qemu_trap_arg0
299 mfpr a1, qemu_trap_arg1
300 mfpr a2, qemu_trap_arg2
308 * trap_arg0 = UNDEFINED
309 * trap_arg1 = UNDEFINED
310 * trap_arg2 = UNDEFINED
314 * r16 (a0) = Instruction fault code
315 * r17 (a1) = UNPREDICTABLE
316 * r18 (a2) = UNPREDICTABLE
321 mfpr p6, qemu_exc_addr
322 addq p6, 4, p1 // increment past the faulting insn
323 blbs p6, MchkBugCheck
325 STACK_FRAME p0, p1, p2
337 * trap_arg0 = exception type
338 * trap_arg1 = register modification mask
339 * trap_arg2 = UNDEFINED
344 mfpr p6, qemu_exc_addr
345 blbs p6, MchkBugCheck
347 STACK_FRAME p0, p6, p2
351 mfpr a0, qemu_trap_arg0
352 mfpr a1, qemu_trap_arg1
356 * Floating Point Disabled
360 * trap_arg0 = UNDEFINED
361 * trap_arg1 = UNDEFINED
362 * trap_arg2 = UNDEFINED
366 * r16 (a0) = Instruction fault code
367 * r17 (a1) = UNPREDICTABLE
368 * r18 (a2) = UNPREDICTABLE
373 mfpr p6, qemu_exc_addr
374 blbs p6, MchkBugCheck
376 STACK_FRAME p0, p6, p2
384 * OSF/1 Privileged CALL_PAL Entry Points
387 #define ORG_CALL_PAL_PRIV(X) .org 0x1000+64*X
394 * We either power down the system or re-enter the console.
395 * But given that we're not returning to the kernel, there's
396 * no reason to continue processing in assembler. Go to C.
398 ORG_CALL_PAL_PRIV(0x00)
400 bsr p7, UpdatePCB // Save kernel data
401 lda v0, HLT_K_SW_HALT
403 ldah p0, 1 // Store 0xdead into CIA RESET reg
404 lda p0, -(0x10000 - 0xdead)(p0)
415 * For QEMU, this is of course a no-op.
417 ORG_CALL_PAL_PRIV(0x01)
424 * For QEMU, this is of course a no-op.
426 ORG_CALL_PAL_PRIV(0x02)
430 ORG_CALL_PAL_PRIV(0x03)
434 ORG_CALL_PAL_PRIV(0x04)
438 ORG_CALL_PAL_PRIV(0x05)
442 ORG_CALL_PAL_PRIV(0x06)
446 ORG_CALL_PAL_PRIV(0x07)
450 ORG_CALL_PAL_PRIV(0x08)
459 * r0 (v0) = Option selector
460 * r16..r21 (a0..a5) = Implementation specific entry parameters
464 * Registers a0..a5, and v0 are UNPREDICTABLE upon return.
466 ORG_CALL_PAL_PRIV(0x09)
473 * FUNCTIONAL DESCRIPTION:
475 * The swap PALcode (swppal) function replaces the current
476 * (active) PALcode by the specified new PALcode image.
477 * This function is intended for use by operating systems
478 * only during bootstraps and restarts, or during transitions
479 * to console I/O mode.
481 * The PALcode descriptor passed in a0 is interpreted as
482 * either a PALcode variant or the base physical address
483 * of the new PALcode image. If a variant, the PALcode
484 * image must have been previously loaded. No PALcode
485 * loading occurs as a result of this function.
488 * This implementation of SWPPAL does not support PALcode
489 * variants. If a variant is specified in a0, a check is
490 * performed to determine whether the variant is OSF/1 or
491 * not and the returned status is either unknown variant
492 * (if not OSF/1) or variant not loaded.
496 * r16 (a0) = New PALcode variant or base physical address
499 * r19 (a3) = New VptPtr
503 * r0 (v0) = Returned status indicating:
504 * 0 - Success (PALcode was switched)
505 * 1 - Unknown PALcode variant
506 * 2 - Known PALcode variant, but PALcode not loaded
508 ORG_CALL_PAL_PRIV(0x0A)
510 // Save a copy of the return address in case of machine check.
511 mfpr p6, qemu_exc_addr
513 // Accept swapping to OSF PALcode. The side effect here is to
514 // load the other parameters for the kernel.
516 bne v0, CallPal_SwpPal_Cont
518 // Return as an unknown PALcode variant
527 ORG_CALL_PAL_PRIV(0x0B)
531 ORG_CALL_PAL_PRIV(0x0C)
536 * Write Interprocessor Interrupt Request
540 * r16 (a0) = target processor number
547 ORG_CALL_PAL_PRIV(0x0D)
549 // We do not currently support more cpus
552 ORG_CALL_PAL_PRIV(0x0E)
556 ORG_CALL_PAL_PRIV(0x0F)
561 * Read Machine Check Error Summary
567 * r0 (v0) = returned MCES value
572 ORG_CALL_PAL_PRIV(0x10)
574 mfpr v0, ptMces // Get current MCES value
575 and v0, MCES_M_ALL, v0 // Clear all other bits
579 * Write Machine Check Error Summary
583 * r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4>
589 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
591 ORG_CALL_PAL_PRIV(0x11)
593 // Clear MIP, SCE, PCE
594 and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
599 and a0, (MCES_M_DPC | MCES_M_DSC), p0
600 bic p1, (MCES_M_DPC | MCES_M_DSC), p1
606 ORG_CALL_PAL_PRIV(0x12)
610 ORG_CALL_PAL_PRIV(0x13)
614 ORG_CALL_PAL_PRIV(0x14)
618 ORG_CALL_PAL_PRIV(0x15)
622 ORG_CALL_PAL_PRIV(0x16)
626 ORG_CALL_PAL_PRIV(0x17)
630 ORG_CALL_PAL_PRIV(0x18)
634 ORG_CALL_PAL_PRIV(0x19)
638 ORG_CALL_PAL_PRIV(0x1A)
642 ORG_CALL_PAL_PRIV(0x1B)
646 ORG_CALL_PAL_PRIV(0x1C)
650 ORG_CALL_PAL_PRIV(0x1D)
654 ORG_CALL_PAL_PRIV(0x1E)
658 ORG_CALL_PAL_PRIV(0x1F)
662 ORG_CALL_PAL_PRIV(0x20)
666 ORG_CALL_PAL_PRIV(0x21)
670 ORG_CALL_PAL_PRIV(0x22)
674 ORG_CALL_PAL_PRIV(0x23)
678 ORG_CALL_PAL_PRIV(0x24)
682 ORG_CALL_PAL_PRIV(0x25)
686 ORG_CALL_PAL_PRIV(0x26)
690 ORG_CALL_PAL_PRIV(0x27)
694 ORG_CALL_PAL_PRIV(0x28)
698 ORG_CALL_PAL_PRIV(0x29)
702 ORG_CALL_PAL_PRIV(0x2A)
707 * Write Floating Point Enable
711 * r16 (a0) = ICSR<FPE> <- a0<0>
715 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
717 ORG_CALL_PAL_PRIV(0x2B)
719 mfpr p0, ptPcbb // Get PCBB
720 and a0, 1, a0 // Clean new FEN value to single bit
722 stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN>
725 ORG_CALL_PAL_PRIV(0x2C)
730 * Write Virtual Page Table Pointer
734 * r16 (a0) = New virtual page table pointer
738 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
740 ORG_CALL_PAL_PRIV(0x2D)
745 ORG_CALL_PAL_PRIV(0x2E)
749 ORG_CALL_PAL_PRIV(0x2F)
754 * Swap Process Context
756 * FUNCTIONAL DESCRIPTION:
758 * The swap process context (swpctx) function saves
759 * the current process data in the current PCB, then
760 * switches to the PCB passed in a0 and loads the
761 * new process context. The old PCB is returned in v0.
765 * r16 (a0) = New PCBB
773 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
775 ORG_CALL_PAL_PRIV(0x30)
777 rpcc p5 // Get cycle counter
778 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
780 mfpr v0, ptPcbb // Get current PCBB
781 mtpr a0, ptPcbb // Save new PCBB
782 srl p5, 32, p7 // Move CC<OFFSET> to low longword
784 addl p5, p7, p7 // Accumulate time for old pcb
785 stl_p p7, PCB_L_PCC(v0)
787 ldl_p t9, PCB_L_PCC(a0) // Get new PCC
788 subl t9, p5, p5 // Generate and ...
789 mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits
791 stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer
792 mfpr t10, ptUsp // Save old user stack pointer
793 stq_p t10, PCB_Q_USP(v0)
795 br CallPal_SwpCtxCont
799 ldq_p $sp, PCB_Q_KSP(v0) // Install new stack pointers
800 ldq_p t10, PCB_Q_USP(v0)
803 mfpr t10, qemu_unique // Save old unique value
804 stq_p t10, PCB_Q_UNIQUE(v0)
805 ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
806 mtpr t10, qemu_unique
808 ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
812 // QEMU does not implement an ASN; skip that.
814 ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
816 mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
826 * r16 (a0) = New system value
830 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
832 ORG_CALL_PAL_PRIV(0x31)
842 * r0 (v0) = Returned system value
846 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
848 ORG_CALL_PAL_PRIV(0x32)
854 * Translation Buffer Invalidate
858 * r16 (a0) = tbi selector type:
860 * -2 - Flush all TB entries (tbia)
861 * -1 - Invalidate all TB entries with ASM=0 (tbiap)
862 * 1 - Invalidate ITB entry for va=a1 (tbisi)
863 * 2 - Invalidate DTB entry for va=a1 (tbisd)
864 * 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
866 * r17 (a1) = VA for TBISx types
868 * Qemu does not implement ASNs or split I/D tlbs. Therefore these
869 * collapse to tbia and tbis.
873 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
875 ORG_CALL_PAL_PRIV(0x33)
882 1: mtpr a1, qemu_tbis
886 * Write System Entry Address
890 * r16 (a0) = VA of system entry point
891 * r17 (a1) = System entry point selector
895 * Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
898 ORG_CALL_PAL_PRIV(0x34)
900 andnot a0, 3, a0 // Clean PC<1:0>
902 cmpult a1, 6, t8 // Bound the input
906 1: lda t0, WrEnt_Table-1b(t0)
908 jmp $31, (t0), WrEnt_Table
914 1: mtpr a0, ptEntArith
929 * Swap Interrupt Priority Level
941 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
943 ORG_CALL_PAL_PRIV(0x35)
952 * Read Processor Status
956 * r0 (v0) = Current PS
960 * Registers t0, t8..t11 are UNPREDICTABLE upon return.
962 ORG_CALL_PAL_PRIV(0x36)
968 * Write Kernel Global Pointer
972 * r16 (a0) = New KGP value
976 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
978 ORG_CALL_PAL_PRIV(0x37)
984 * Write User Stack Pointer
988 * r16 (a0) = New user stack pointer value
992 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
994 ORG_CALL_PAL_PRIV(0x38)
1000 * Write Performance Monitor
1004 * r16 (a0) = New user stack pointer value
1008 * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1010 ORG_CALL_PAL_PRIV(0x39)
1015 * Read User Stack Pointer
1017 * OUTPUT PARAMETERS:
1019 * r0 (v0) = User stack pointer value
1023 * Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1025 ORG_CALL_PAL_PRIV(0x3A)
1030 ORG_CALL_PAL_PRIV(0x3B)
1037 * OUTPUT PARAMETERS:
1039 * r0 (v0) = Current processor number
1043 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1045 ORG_CALL_PAL_PRIV(0x3C)
1047 // We do not currently support more cpus
1052 * Return From System Call
1056 * r30 (sp) = Pointer to the top of the kernel stack
1058 * OUTPUT PARAMETERS:
1060 * r29 (gp) = Restored user mode global pointer
1061 * r30 (sp) = User stack pointer
1065 * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1067 ORG_CALL_PAL_PRIV(0x3D)
1069 ldq t9, FRM_Q_PC($sp) // Pop the return address
1070 ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer
1071 lda t8, FRM_K_SIZE($sp)
1074 mov PS_K_USER, t8 // Set new mode to user
1077 mfpr $sp, ptUsp // Get the user stack pointer
1079 andnot t9, 3, t9 // Clean return PC<1:0>
1083 * Wait For Interrupt
1085 * FUNCTIONAL DESCRIPTION:
1087 * If possible, wait for the first of either of the following
1088 * conditions before returning: any interrupt other than a clock
1089 * tick; or the first clock tick after a specified number of clock
1090 * ticks have bbeen skipped.
1096 * OUTPUT PARAMETERS:
1104 ORG_CALL_PAL_PRIV(0x3E)
1109 * Return From Trap, Fault, or Interrupt
1113 * r30 (sp) = Pointer to the top of the kernel stack
1115 * OUTPUT PARAMETERS:
1119 * r29 (gp) <- (sp+16)
1120 * r16 (a0) <- (sp+24)
1121 * r17 (a1) <- (sp+32)
1122 * r18 (a2) <- (sp+40)
1124 ORG_CALL_PAL_PRIV(0x3F)
1126 mfpr p6, qemu_exc_addr // Save exc_addr for machine check
1128 ldq p4, FRM_Q_PS($sp) // Get the PS
1129 ldq p5, FRM_Q_PC($sp) // Get the return PC
1130 ldq $gp, FRM_Q_GP($sp) // Get gp
1131 ldq a0, FRM_Q_A0($sp) // Get a0
1133 ldq a1, FRM_Q_A1(p7) // Get a1
1134 ldq a2, FRM_Q_A2(p7) // Get a2
1135 lda $sp, FRM_K_SIZE($sp) // Pop the stack
1136 bic p5, 3, p5 // Clean return PC<1:0>
1139 bne p3, CallPal_Rti_ToUser
1141 and p4, PS_M_IPL, p4
1155 * OSF/1 Unprivileged CALL_PAL Entry Points
1158 #define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80)
1161 * A helper routine for the unprivaledged kernel entry points, since the
1162 * actual stack frame setup code is just a tad too large to fit inline.
1168 * p7 = return address
1176 CallPal_Stack_Frame:
1177 // Test if we're currently in user mode
1180 CallPal_Stack_Frame_FromUser:
1181 // Switch to kernel mode
1186 // Allocate the stack frame
1187 lda $sp, -FRM_K_SIZE($sp)
1188 stq p5, FRM_Q_PS($sp)
1189 stq p6, FRM_Q_PC($sp)
1190 stq $gp, FRM_Q_GP($sp)
1191 stq a0, FRM_Q_A0($sp)
1192 stq a1, FRM_Q_A1($sp)
1193 stq a2, FRM_Q_A2($sp)
1200 * OUTPUT PARAMETERS:
1202 * r16 (a0) = Code for bpt (0)
1203 * r17 (a1) = UNPREDICTABLE
1204 * r18 (a2) = UNPREDICTABLE
1206 ORG_CALL_PAL_UNPRIV(0x80)
1209 mfpr p6, qemu_exc_addr
1210 bsr p7, CallPal_Stack_Frame
1220 * OUTPUT PARAMETERS:
1222 * r16 (a0) = Code for bugchk (1)
1223 * r17 (a1) = UNPREDICTABLE
1224 * r18 (a2) = UNPREDICTABLE
1226 ORG_CALL_PAL_UNPRIV(0x81)
1229 mfpr p6, qemu_exc_addr
1230 bsr p7, CallPal_Stack_Frame
1238 ORG_CALL_PAL_UNPRIV(0x82)
1245 ORG_CALL_PAL_UNPRIV(0x83)
1248 mfpr p6, qemu_exc_addr
1253 bsr p7, CallPal_Stack_Frame_FromUser
1259 0: subq p6, 4, p6 // Get PC of CALL_PAL insn
1262 ORG_CALL_PAL_UNPRIV(0x84)
1266 ORG_CALL_PAL_UNPRIV(0x85)
1272 * I-Stream Memory Barrier
1274 * For QEMU, this is of course a no-op.
1276 ORG_CALL_PAL_UNPRIV(0x86)
1281 ORG_CALL_PAL_UNPRIV(0x87)
1285 ORG_CALL_PAL_UNPRIV(0x88)
1289 ORG_CALL_PAL_UNPRIV(0x89)
1293 ORG_CALL_PAL_UNPRIV(0x8A)
1297 ORG_CALL_PAL_UNPRIV(0x8B)
1301 ORG_CALL_PAL_UNPRIV(0x8C)
1305 ORG_CALL_PAL_UNPRIV(0x8D)
1309 ORG_CALL_PAL_UNPRIV(0x8E)
1313 ORG_CALL_PAL_UNPRIV(0x8F)
1317 ORG_CALL_PAL_UNPRIV(0x90)
1321 ORG_CALL_PAL_UNPRIV(0x91)
1325 ORG_CALL_PAL_UNPRIV(0x92)
1329 ORG_CALL_PAL_UNPRIV(0x93)
1333 ORG_CALL_PAL_UNPRIV(0x94)
1337 ORG_CALL_PAL_UNPRIV(0x95)
1341 ORG_CALL_PAL_UNPRIV(0x96)
1345 ORG_CALL_PAL_UNPRIV(0x97)
1349 ORG_CALL_PAL_UNPRIV(0x98)
1353 ORG_CALL_PAL_UNPRIV(0x99)
1357 ORG_CALL_PAL_UNPRIV(0x9A)
1361 ORG_CALL_PAL_UNPRIV(0x9B)
1365 ORG_CALL_PAL_UNPRIV(0x9C)
1369 ORG_CALL_PAL_UNPRIV(0x9D)
1376 * OUTPUT PARAMETERS:
1378 * r0 (v0) = Returned process unique value
1380 ORG_CALL_PAL_UNPRIV(0x9E)
1382 mfpr v0, qemu_unique
1386 * Write Unique Value
1390 * r16 (a0) = New process unique value
1392 ORG_CALL_PAL_UNPRIV(0x9F)
1394 mtpr a0, qemu_unique
1398 ORG_CALL_PAL_UNPRIV(0xA0)
1402 ORG_CALL_PAL_UNPRIV(0xA1)
1406 ORG_CALL_PAL_UNPRIV(0xA2)
1410 ORG_CALL_PAL_UNPRIV(0xA3)
1414 ORG_CALL_PAL_UNPRIV(0xA4)
1418 ORG_CALL_PAL_UNPRIV(0xA5)
1422 ORG_CALL_PAL_UNPRIV(0xA6)
1426 ORG_CALL_PAL_UNPRIV(0xA7)
1430 ORG_CALL_PAL_UNPRIV(0xA8)
1434 ORG_CALL_PAL_UNPRIV(0xA9)
1440 * OUTPUT PARAMETERS:
1442 * r16 (a0) = Code for gentrap (2)
1443 * r17 (a1) = UNPREDICTABLE
1444 * r18 (a2) = UNPREDICTABLE
1446 ORG_CALL_PAL_UNPRIV(0xAA)
1449 mfpr p6, qemu_exc_addr
1450 bsr p7, CallPal_Stack_Frame
1454 mov IF_K_GENTRAP, a0
1458 ORG_CALL_PAL_UNPRIV(0xAB)
1462 ORG_CALL_PAL_UNPRIV(0xAC)
1466 ORG_CALL_PAL_UNPRIV(0xAD)
1470 ORG_CALL_PAL_UNPRIV(0xAE)
1474 ORG_CALL_PAL_UNPRIV(0xAF)
1478 ORG_CALL_PAL_UNPRIV(0xB0)
1482 ORG_CALL_PAL_UNPRIV(0xB1)
1486 ORG_CALL_PAL_UNPRIV(0xB2)
1490 ORG_CALL_PAL_UNPRIV(0xB3)
1494 ORG_CALL_PAL_UNPRIV(0xB4)
1498 ORG_CALL_PAL_UNPRIV(0xB5)
1502 ORG_CALL_PAL_UNPRIV(0xB6)
1506 ORG_CALL_PAL_UNPRIV(0xB7)
1510 ORG_CALL_PAL_UNPRIV(0xB8)
1514 ORG_CALL_PAL_UNPRIV(0xB9)
1518 ORG_CALL_PAL_UNPRIV(0xBA)
1522 ORG_CALL_PAL_UNPRIV(0xBB)
1526 ORG_CALL_PAL_UNPRIV(0xBC)
1530 ORG_CALL_PAL_UNPRIV(0xBD)
1534 ORG_CALL_PAL_UNPRIV(0xBE)
1538 ORG_CALL_PAL_UNPRIV(0xBF)
1541 mfpr p6, qemu_exc_addr
1542 bsr p7, CallPal_Stack_Frame
1552 * PALcode detected processor machine check handler.
1554 * The PALcode-detected machine check handler loads a code
1555 * indicating the type of machine check error, loads
1556 * the System Control Block (SCB) vector for the
1557 * processor machine check service routine, sets the
1558 * Machine-Check-In-Progress (MIP) flag in the Machine
1559 * Check Error Summary register (MCES), and merges
1560 * with the common machine check flow.
1562 * If a second processor machine check error condition
1563 * is detected while the MIP flag is set, the processor
1564 * is forced into console I/O mode indicating "double
1565 * error abort encountered" as the reason for the halt.
1569 * Called when an internal processor error is detected
1570 * that cannot be successfully corrected by hardware or
1575 * r14 (p6) = Exception address
1577 * OUTPUT PARAMETERS:
1579 * ptMchk0 = saved v0
1580 * ptMchk1 = saved t0
1581 * ptMchk2 = saved t3
1582 * ptMchk3 = saved t4
1583 * ptMchk4 = saved t5
1584 * ptMchk5 = saved exc_addr
1585 * ptMisc<47:32> = MCHK code
1586 * ptMisc<31:16> = SCB vector
1591 * r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
1592 * PAL temporaries and are available for use as scratch
1593 * registers by the system specific machine check
1598 lda p7, MCHK_K_BUGCHECK
1601 lda p7, MCHK_K_OS_BUGCHECK
1602 1: sll p7, PT16_V_MCHK, p7 // Move error code into upper longword
1604 mfpr p4, ptMces // Get and isolate MCES bits
1606 or p4, p7, p4 // Combine MCES and error code
1608 ldah p7, SCB_Q_PROCMCHK // Combine SCB and MCHK bits
1610 or p7, MCES_M_MIP, p7 // Set machine-check-in-progress
1613 MchkCommon_SaveRegs:
1614 mtpr v0, ptMchk0 // Save temporaries
1619 mtpr p6, ptMchk5 // Save the exception address
1622 blbs p6, MchkFromPal
1625 * Common Machine Check Handler
1634 * ptMchk5 Saved exc_addr
1635 * ptMisc<47:32> MCHK code
1636 * ptMisc<31:16> SCB vector
1639 * Registers v0, t0, and t3 .. t5 are available for use, in
1640 * addition to the shadow registers.
1644 mov 0, t4 // Assume non-retryable.
1646 mfpr t5, ptMisc // Load MCHK code
1651 * Build Machine Check Logout Frame
1653 * This portion of the machine check handler builds a logout frame
1654 * in the PAL impure scratch area, builds a stack frame on the kernel
1655 * stack (already built if there was an interrupt machine check),
1656 * loads the GP with the KGP, loads the machine check entry
1657 * code in a0, loads a platform-specific interrupt vector
1658 * (typically the same value as the SCB offset) in a1, loads
1659 * the kseg address of the logout area in a2, and dispatches
1660 * to the kernel interrupt handler pointed to by the entInt
1661 * operating system entry point.
1663 * OUTPUT PARAMETERS:
1665 * a0 (r16) = Machine check entry type
1666 * a1 (r17) = Platform-specific interrupt vector
1667 * a2 (r18) = Pointer to logout area
1670 .macro STORE_IPR which, offset, base
1672 stq_p v0, \offset(\base)
1676 mfpr p6, ptPgp // Get address of logout frame
1677 lda p6, laf_base(p6) !gprel
1680 stl_p t3, laf_l_size - laf_base(p6)
1681 stl_p t4, laf_l_flag - laf_base(p6)
1683 lda t3, laf_cpu_base - laf_base
1684 stl_p t3, laf_l_cpu - laf_base(p6)
1685 lda t3, laf_sys_base - laf_base
1686 stl_p t3, laf_l_sys - laf_base(p6)
1688 STORE_IPR qemu_shadow0, laf_q_shadow - laf_base + 0x00, p6
1689 STORE_IPR qemu_shadow1, laf_q_shadow - laf_base + 0x08, p6
1690 STORE_IPR qemu_shadow2, laf_q_shadow - laf_base + 0x10, p6
1691 STORE_IPR qemu_shadow3, laf_q_shadow - laf_base + 0x18, p6
1692 STORE_IPR qemu_shadow4, laf_q_shadow - laf_base + 0x20, p6
1693 STORE_IPR qemu_shadow5, laf_q_shadow - laf_base + 0x28, p6
1694 STORE_IPR qemu_shadow6, laf_q_shadow - laf_base + 0x30, p6
1695 STORE_IPR qemu_shadow7, laf_q_shadow - laf_base + 0x38, p6
1697 STORE_IPR pt0, laf_q_pt - laf_base + 0x00, p6
1698 STORE_IPR pt1, laf_q_pt - laf_base + 0x08, p6
1699 STORE_IPR pt2, laf_q_pt - laf_base + 0x10, p6
1700 STORE_IPR pt3, laf_q_pt - laf_base + 0x18, p6
1701 STORE_IPR pt4, laf_q_pt - laf_base + 0x20, p6
1702 STORE_IPR pt5, laf_q_pt - laf_base + 0x28, p6
1703 STORE_IPR pt6, laf_q_pt - laf_base + 0x30, p6
1704 STORE_IPR pt7, laf_q_pt - laf_base + 0x38, p6
1705 STORE_IPR pt8, laf_q_pt - laf_base + 0x40, p6
1706 STORE_IPR pt9, laf_q_pt - laf_base + 0x48, p6
1707 STORE_IPR pt10, laf_q_pt - laf_base + 0x50, p6
1708 STORE_IPR pt11, laf_q_pt - laf_base + 0x58, p6
1709 STORE_IPR pt12, laf_q_pt - laf_base + 0x60, p6
1710 STORE_IPR pt13, laf_q_pt - laf_base + 0x68, p6
1711 STORE_IPR pt14, laf_q_pt - laf_base + 0x70, p6
1712 STORE_IPR pt15, laf_q_pt - laf_base + 0x78, p6
1713 STORE_IPR pt16, laf_q_pt - laf_base + 0x80, p6
1714 STORE_IPR pt17, laf_q_pt - laf_base + 0x88, p6
1715 STORE_IPR pt18, laf_q_pt - laf_base + 0x90, p6
1716 STORE_IPR pt19, laf_q_pt - laf_base + 0x98, p6
1717 STORE_IPR pt20, laf_q_pt - laf_base + 0xa0, p6
1718 STORE_IPR pt21, laf_q_pt - laf_base + 0xa8, p6
1719 STORE_IPR pt22, laf_q_pt - laf_base + 0xb0, p6
1720 STORE_IPR pt23, laf_q_pt - laf_base + 0xb8, p6
1727 stq_p p7, laf_q_exc_addr - laf_base(p6)
1729 stq_p $31, laf_q_exc_sum - laf_base(p6)
1730 stq_p $31, laf_q_exc_mask - laf_base(p6)
1732 STORE_IPR qemu_palbr, laf_q_pal_base - laf_base, p6
1734 stq_p $31, laf_q_isr - laf_base(p6)
1735 stq_p $31, laf_q_icsr - laf_base(p6)
1736 stq_p $31, laf_q_icperr - laf_base(p6)
1737 stq_p $31, laf_q_dcperr - laf_base(p6)
1738 stq_p $31, laf_q_va - laf_base(p6)
1739 stq_p $31, laf_q_mm_stat - laf_base(p6)
1740 stq_p $31, laf_q_sc_addr - laf_base(p6)
1741 stq_p $31, laf_q_sc_stat - laf_base(p6)
1742 stq_p $31, laf_q_bc_addr - laf_base(p6)
1743 stq_p $31, laf_q_ei_addr - laf_base(p6)
1744 stq_p $31, laf_q_fill_syndrome - laf_base(p6)
1745 stq_p $31, laf_q_ei_stat - laf_base(p6)
1747 STORE_IPR qemu_lock_addr, laf_q_ld_lock - laf_base, p6
1749 // bsr v0, Sys_MchkLogOut
1753 // Build the stack frame on the kernel stack and post the interrupt
1756 mov p6, p4 // Stash pointer to logout
1757 lda a1, SCB_Q_SYSMCHK
1758 blbs p7, 0f // Check if stack frame already built
1761 mfpr p6, ptMchk5 // Reload exc_addr for double mchk
1763 STACK_FRAME p5, p6, p7
1765 mov IPL_K_MCHK, p5 // Raise IPL
1768 mfpr a1, ptMisc // Isolate SCB vector
1771 0: mfpr p7, ptEntInt
1774 lda a2, -1 // Load kseg offset
1775 srl a2, VA_S_SIZE-1, a2
1776 sll a2, VA_S_SIZE-1, a2
1777 addq a2, p4, a2 // Pass ptr to logout area
1785 lda v0, HLT_K_DBL_MCHK
1790 lda v0, HLT_K_MCHK_FROM_PAL
1795 lda v0, HLT_K_KSP_INVAL
1799 * Update the current PCB with new SP and CC info.
1803 * p7 = return linkage
1810 mfpr p3, qemu_ps // Check current mode
1814 mtpr $sp, ptUsp // Save user stack pointer
1815 stq_p $sp, PCB_Q_USP(p4)
1818 1: mtpr $sp, ptKsp // Save kernel stack pointer
1819 stq_p $sp, PCB_Q_KSP(p4)
1821 2: srl p5, 32, p3 // Merge for new time
1823 stl_p p3, PCB_L_PCC(p4) // Store new time
1825 mfpr p5, qemu_unique // Save unique
1826 stq_p p5, PCB_Q_UNIQUE(p4)
1838 * Allocate the logout frame.
1841 .type laf_base,@object
1848 laf_q_mchk_code: .quad 0
1850 $las_size = . - laf_base
1853 laf_q_shadow: .skip 8*8
1854 laf_q_pt: .skip 8*24
1855 laf_q_exc_addr: .quad 0
1856 laf_q_exc_sum: .quad 0
1857 laf_q_exc_mask: .quad 0
1858 laf_q_pal_base: .quad 0
1861 laf_q_icperr: .quad 0
1862 laf_q_dcperr: .quad 0
1864 laf_q_mm_stat: .quad 0
1865 laf_q_sc_addr: .quad 0
1866 laf_q_sc_stat: .quad 0
1867 laf_q_bc_addr: .quad 0
1868 laf_q_ei_addr: .quad 0
1869 laf_q_fill_syndrome: .quad 0
1870 laf_q_ei_stat: .quad 0
1871 laf_q_ld_lock: .quad 0
1874 laf_q_cpu_err0: .quad 0
1875 laf_q_cpu_err1: .quad 0
1876 laf_q_cia_err: .quad 0
1877 laf_q_err_mask: .quad 0
1878 laf_q_cia_syn: .quad 0
1879 laf_q_mem_err0: .quad 0
1880 laf_q_mem_err1: .quad 0
1881 laf_q_pci_err0: .quad 0
1882 laf_q_pci_err1: .quad 0
1883 laf_q_pci_err2: .quad 0
1885 $laf_size = . - laf_base
1886 .size laf_base, . - laf_base
1890 .size stack,STACK_SIZE
1891 stack: .skip STACK_SIZE