Signal halt properly.
[qemu-palcode.git] / pal.S
blobb31b63e1fb9d202651710fd476c52e1ca9a207fe
1         .set            noat
2         .set            nomacro
3         .text
5 #include "osf.h"
7 /* General Purpose Registers.  */
8 #define v0      $0
9 #define t0      $1
10 #define t1      $2
11 #define t2      $3
12 #define t3      $4
13 #define t4      $5
14 #define t5      $6
15 #define a0      $16
16 #define a1      $17
17 #define a2      $18
18 #define a3      $19
19 #define a4      $20
20 #define a5      $21
21 #define t8      $22
22 #define t9      $23
23 #define t10     $24
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
28    via MTPR/MFPR.  */
29 #define p0      $8
30 #define p1      $9
31 #define p2      $10
32 #define p3      $11
33 #define p4      $12
34 #define p5      $13
35 #define p6      $14             // Used to save exc_addr for machine check
36 #define p7      $25
38 /* QEMU Processor Registers.  */
39 #define qemu_ps         0
40 #define qemu_fen        1
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
46 #define qemu_palbr      7
47 #define qemu_ptbr       8
48 #define qemu_vptptr     9
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.  */
62 #define pt0             40
63 #define pt1             41
64 #define pt2             42
65 #define pt3             43
66 #define pt4             44
67 #define pt5             45
68 #define pt6             46
69 #define pt7             47
70 #define pt8             48
71 #define pt9             49
72 #define pt10            50
73 #define pt11            51
74 #define pt12            52
75 #define pt13            53
76 #define pt14            54
77 #define pt15            55
78 #define pt16            56
79 #define pt17            57
80 #define pt18            58
81 #define pt19            59
82 #define pt20            60
83 #define pt21            61
84 #define pt22            62
85 #define pt23            63
87 /* QEMU function calls, via mtpr.  */
88 #define qemu_tbia       255
89 #define qemu_tbis       254
91 /* PALcode uses of the private storage slots.  */
92 #define ptEntUna        pt1
93 #define ptEntIF         pt2
94 #define ptEntSys        pt3
95 #define ptEntInt        pt4
96 #define ptEntArith      pt5
97 #define ptEntMM         pt6
98 #define ptMces          pt7
99 #define ptSysVal        pt8
100 #define ptUsp           pt9
101 #define ptKsp           pt10
102 #define ptKgp           pt11
103 #define ptPcbb          pt12
104 #define ptPgp           pt13
105 #define ptMchk0         pt14
106 #define ptMchk1         pt15
107 #define ptMisc          pt16
108 #define ptMchk2         pt17
109 #define ptMchk3         pt18
110 #define ptMchk4         pt19
111 #define ptMchk5         pt20
114  * Shortcuts for various PALmode instructions.
115  */
116 #define mtpr    hw_mtpr
117 #define mfpr    hw_mfpr
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.
130  */
132 #define FRM_Q_PS        0
133 #define FRM_Q_PC        8
134 #define FRM_Q_GP        16
135 #define FRM_Q_A0        24
136 #define FRM_Q_A1        32
137 #define FRM_Q_A2        40
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
143         bne     \temp, 0f
144         // Switch to kernel mode
145         mtpr    $31, qemu_ps
146         mtpr    $sp, ptUsp
147         mfpr    $sp, ptKsp
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)
156 .endm
159  * Allocate a 1 page stack for use by the console.
160  */
161 #define STACK_SIZE      8192
164  * QEMU emulator "hardware" entry points.
165  */
168  * Reset
169  * 
170  * INPUT PARAMETERS:
171  * 
172  *      trap_arg0 = Memory size
173  *      trap_arg1 = Kernel entry (if loaded)
174  */ 
175         .org    0x0000
176         .globl  __start
177 __start:
178         // Initialize GP and stack.
179         br      $gp, .+4
180         ldah    $gp, 0($gp)             !gpdisp!1
181         lda     $gp, 0($gp)                     !gpdisp!1
182         mtpr    $gp, ptPgp
184         lda     $sp, stack+STACK_SIZE($gp)      !gprel
186         // Disable interrupts; kernel mode
187         lda     t0, IPL_K_HIGH
188         mtpr    t0, qemu_ps
190         // Load the initial PCB and page table elements.
191         lda     t0, page_dir($gp)               !gprel
192         zap     t0, 0xf0, t0
193         mtpr    t0, qemu_ptbr
195         lda     t0, pal_pcb($gp)                !gprel
196         zap     t0, 0xf0, t0
197         mtpr    t0, ptPcbb
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
207         hw_ret  ($27)
210  * Machine Check
212  * INPUT PARAMETERS:
213  * 
214  *      trap_arg0 = 
215  *      trap_arg1 = 
216  *      trap_arg2 = 
217  */
218         .org    0x0080
219 Pal_Mchk:
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
223         mtpr    p4, ptMces
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
230         mtpr    p4, ptMisc
232         br      MchkCommon_SaveRegs
235  * Interrupt
237  * INPUT PARAMETERS:
239  *      trap_arg0 = interrupt type
240  *      trap_arg1 = UNDEFINED
241  *      trap_arg2 = UNDEFINED
242  */ 
243         .org    0x0100
244 Pal_Interrupt:
245         mfpr    p6, qemu_exc_addr
246         mfpr    p0, qemu_ps
248         STACK_FRAME p0, p6, p2
250         mfpr    p0, ptEntInt
251         mfpr    $gp, ptKgp
252         mfpr    a0, qemu_trap_arg0
253         hw_ret  (p0)
256  * Memory Fault
258  * INPUT PARAMETERS:
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)
263  */ 
264         .org    0x0180
265 Pal_MMFault:
266         mfpr    p0, qemu_ps
267         mfpr    p6, qemu_exc_addr
269         STACK_FRAME p0, p6, p2
271         mfpr    p0, ptEntMM
272         mfpr    $gp, ptKgp
273         mfpr    a0, qemu_trap_arg0
274         mfpr    a1, qemu_trap_arg1
275         mfpr    a2, qemu_trap_arg2
276         hw_ret  (p0)
279  * Unaligned Data
280  * 
281  * INPUT PARAMETERS:
283  *      trap_arg0 = faulting address
284  *      trap_arg1 = opcode of faulting insn
285  *      trap_arg2 = src/dst register number
286  */ 
287         .org    0x0200
288 Pal_Unalign:
289         mfpr    p0, qemu_ps
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
296         mfpr    p0, ptEntUna
297         mfpr    $gp, ptKgp
298         mfpr    a0, qemu_trap_arg0
299         mfpr    a1, qemu_trap_arg1
300         mfpr    a2, qemu_trap_arg2
301         hw_ret  (p0)
304  * Illegal Opcode
306  * INPUT PARAMETERS:
308  *      trap_arg0 = UNDEFINED
309  *      trap_arg1 = UNDEFINED
310  *      trap_arg2 = UNDEFINED
312  * OUTPUT PARAMETERS:
314  *      r16 (a0) = Instruction fault code
315  *      r17 (a1) = UNPREDICTABLE
316  *      r18 (a2) = UNPREDICTABLE
317  */ 
318         .org    0x0280
319 Pal_OpcDec:
320         mfpr    p0, qemu_ps
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
327         mfpr    p0, ptEntIF
328         mfpr    $gp, ptKgp
329         mov     IF_K_OPCDEC, a0
330         hw_ret  (p0)
333  * Arithmetic Trap
335  * INPUT PARAMETERS:
337  *      trap_arg0 = exception type
338  *      trap_arg1 = register modification mask
339  *      trap_arg2 = UNDEFINED
340  */
341         .org    0x0300
342 Pal_Arith:
343         mfpr    p0, qemu_ps
344         mfpr    p6, qemu_exc_addr
345         blbs    p6, MchkBugCheck
347         STACK_FRAME p0, p6, p2
349         mfpr    p0, ptEntArith
350         mfpr    $gp, ptKgp
351         mfpr    a0, qemu_trap_arg0
352         mfpr    a1, qemu_trap_arg1
353         hw_ret  (p0)
356  * Floating Point Disabled
358  * INPUT PARAMETERS:
360  *      trap_arg0 = UNDEFINED
361  *      trap_arg1 = UNDEFINED
362  *      trap_arg2 = UNDEFINED
364  * OUTPUT PARAMETERS:
366  *      r16 (a0) = Instruction fault code
367  *      r17 (a1) = UNPREDICTABLE
368  *      r18 (a2) = UNPREDICTABLE
369  */ 
370         .org    0x0380
371 Pal_Fen:
372         mfpr    p0, qemu_ps
373         mfpr    p6, qemu_exc_addr
374         blbs    p6, MchkBugCheck
376         STACK_FRAME p0, p6, p2
378         mfpr    p0, ptEntIF
379         mfpr    $gp, ptKgp
380         mov     IF_K_FEN, a0
381         hw_ret  (p0)
384  * OSF/1 Privileged CALL_PAL Entry Points
385  */
387 #define ORG_CALL_PAL_PRIV(X)    .org    0x1000+64*X
390  * Halt
392  * SIDE EFFECTS:
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.
397  */
398         ORG_CALL_PAL_PRIV(0x00)
399 CallPal_Halt:
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)
405         lda     p1, 0x878
406         sll     p1, 28, p1
407         lda     p1, 0x900(p1)
408         stl_p   p0, 0(p1)
410         br      Sys_EnterConsole
413  * Cache Flush
415  * For QEMU, this is of course a no-op.
416  */
417         ORG_CALL_PAL_PRIV(0x01)
418 CallPal_Cflush:
419         hw_rei
422  * Drain Aborts
424  * For QEMU, this is of course a no-op.
425  */
426         ORG_CALL_PAL_PRIV(0x02)
427 CallPal_Draina:
428         hw_rei
430         ORG_CALL_PAL_PRIV(0x03)
431 CallPal_OpcDec03:
432         br      CallPal_OpcDec
434         ORG_CALL_PAL_PRIV(0x04)
435 CallPal_OpcDec04:
436         br      CallPal_OpcDec
438         ORG_CALL_PAL_PRIV(0x05)
439 CallPal_OpcDec05:
440         br      CallPal_OpcDec
442         ORG_CALL_PAL_PRIV(0x06)
443 CallPal_OpcDec06:
444         br      CallPal_OpcDec
446         ORG_CALL_PAL_PRIV(0x07)
447 CallPal_OpcDec07:
448         br      CallPal_OpcDec
450         ORG_CALL_PAL_PRIV(0x08)
451 CallPal_OpcDec08:
452         br      CallPal_OpcDec
455  * Console Service
456  * 
457  * INPUT PARAMETERS:
458  * 
459  *      r0 (v0)           = Option selector
460  *      r16..r21 (a0..a5) = Implementation specific entry parameters
461  * 
462  * SIDE EFFECTS:
464  *      Registers a0..a5, and v0 are UNPREDICTABLE upon return.
465  */ 
466         ORG_CALL_PAL_PRIV(0x09)
467 CallPal_Cserve:
468         br      Sys_Cserve
471  * Swap PALcode
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.
480  * 
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. 
487  *      NOTE:
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.
494  * INPUT PARAMETERS:
496  *      r16 (a0) = New PALcode variant or base physical address
497  *      r17 (a1) = New PC
498  *      r18 (a2) = New PCB
499  *      r19 (a3) = New VptPtr
500  * 
501  * OUTPUT PARAMETERS:
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
507  */
508         ORG_CALL_PAL_PRIV(0x0A)
509 CallPal_SwpPal:
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.
515         cmpeq   a0, 2, v0
516         bne     v0, CallPal_SwpPal_Cont
518         // Return as an unknown PALcode variant
519         mov     1, v0
520         hw_rei
522         .text   1
523 CallPal_SwpPal_Cont:
524         // YOUAREHERE
525         .previous
527         ORG_CALL_PAL_PRIV(0x0B)
528 CallPal_OpcDec0B:
529         br      CallPal_OpcDec
531         ORG_CALL_PAL_PRIV(0x0C)
532 CallPal_OpcDec0C:
533         br      CallPal_OpcDec
536  * Write Interprocessor Interrupt Request
538  * INPUT PARAMETERS:
540  *      r16 (a0) = target processor number 
541  * 
542  * OUTPUT PARAMETERS:
544  * SIDE EFFECTS:
545  * 
546  */ 
547         ORG_CALL_PAL_PRIV(0x0D)
548 CallPal_WrIpir:
549         // We do not currently support more cpus
550         hw_rei
552         ORG_CALL_PAL_PRIV(0x0E)
553 CallPal_OpcDec0E:
554         br      CallPal_OpcDec
556         ORG_CALL_PAL_PRIV(0x0F)
557 CallPal_OpcDec0F:
558         br      CallPal_OpcDec
561  * Read Machine Check Error Summary
563  * INPUT PARAMETERS:
564  * 
565  * OUTPUT PARAMETERS:
567  *      r0 (v0) = returned MCES value
568  * 
569  * SIDE EFFECTS:
571  */ 
572         ORG_CALL_PAL_PRIV(0x10)
573 CallPal_RdMces:
574         mfpr    v0, ptMces              // Get current MCES value
575         and     v0, MCES_M_ALL, v0      // Clear all other bits
576         hw_rei
579  * Write Machine Check Error Summary
581  * INPUT PARAMETERS:
582  * 
583  *      r16 (a0) = MCES<DPC> <- a0<3>,  MCES<DSC> <- a0<4>
584  * 
585  * OUTPUT PARAMETERS:
587  * SIDE EFFECTS:
589  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
590  */ 
591         ORG_CALL_PAL_PRIV(0x11)
592 CallPal_WrMces:
593         // Clear MIP, SCE, PCE
594         and     a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
595         mfpr    p1, ptMces
596         bic     p1, p0, p1
598         // Copy DPC and DSC
599         and     a0, (MCES_M_DPC | MCES_M_DSC), p0
600         bic     p1, (MCES_M_DPC | MCES_M_DSC), p1
601         or      p1, p0, p1
603         mtpr    p1, ptMces
604         hw_rei
606         ORG_CALL_PAL_PRIV(0x12)
607 CallPal_OpcDec12:
608         br      CallPal_OpcDec
610         ORG_CALL_PAL_PRIV(0x13)
611 CallPal_OpcDec13:
612         br      CallPal_OpcDec
614         ORG_CALL_PAL_PRIV(0x14)
615 CallPal_OpcDec14:
616         br      CallPal_OpcDec
618         ORG_CALL_PAL_PRIV(0x15)
619 CallPal_OpcDec15:
620         br      CallPal_OpcDec
622         ORG_CALL_PAL_PRIV(0x16)
623 CallPal_OpcDec16:
624         br      CallPal_OpcDec
626         ORG_CALL_PAL_PRIV(0x17)
627 CallPal_OpcDec17:
628         br      CallPal_OpcDec
630         ORG_CALL_PAL_PRIV(0x18)
631 CallPal_OpcDec18:
632         br      CallPal_OpcDec
634         ORG_CALL_PAL_PRIV(0x19)
635 CallPal_OpcDec19:
636         br      CallPal_OpcDec
638         ORG_CALL_PAL_PRIV(0x1A)
639 CallPal_OpcDec1A:
640         br      CallPal_OpcDec
642         ORG_CALL_PAL_PRIV(0x1B)
643 CallPal_OpcDec1B:
644         br      CallPal_OpcDec
646         ORG_CALL_PAL_PRIV(0x1C)
647 CallPal_OpcDec1C:
648         br      CallPal_OpcDec
650         ORG_CALL_PAL_PRIV(0x1D)
651 CallPal_OpcDec1D:
652         br      CallPal_OpcDec
654         ORG_CALL_PAL_PRIV(0x1E)
655 CallPal_OpcDec1E:
656         br      CallPal_OpcDec
658         ORG_CALL_PAL_PRIV(0x1F)
659 CallPal_OpcDec1F:
660         br      CallPal_OpcDec
662         ORG_CALL_PAL_PRIV(0x20)
663 CallPal_OpcDec20:
664         br      CallPal_OpcDec
666         ORG_CALL_PAL_PRIV(0x21)
667 CallPal_OpcDec21:
668         br      CallPal_OpcDec
670         ORG_CALL_PAL_PRIV(0x22)
671 CallPal_OpcDec22:
672         br      CallPal_OpcDec
674         ORG_CALL_PAL_PRIV(0x23)
675 CallPal_OpcDec23:
676         br      CallPal_OpcDec
678         ORG_CALL_PAL_PRIV(0x24)
679 CallPal_OpcDec24:
680         br      CallPal_OpcDec
682         ORG_CALL_PAL_PRIV(0x25)
683 CallPal_OpcDec25:
684         br      CallPal_OpcDec
686         ORG_CALL_PAL_PRIV(0x26)
687 CallPal_OpcDec26:
688         br      CallPal_OpcDec
690         ORG_CALL_PAL_PRIV(0x27)
691 CallPal_OpcDec27:
692         br      CallPal_OpcDec
694         ORG_CALL_PAL_PRIV(0x28)
695 CallPal_OpcDec28:
696         br      CallPal_OpcDec
698         ORG_CALL_PAL_PRIV(0x29)
699 CallPal_OpcDec29:
700         br      CallPal_OpcDec
702         ORG_CALL_PAL_PRIV(0x2A)
703 CallPal_OpcDec2A:
704         br      CallPal_OpcDec
707  * Write Floating Point Enable
709  * INPUT PARAMETERS:
710  * 
711  *      r16 (a0) = ICSR<FPE> <- a0<0>
712  * 
713  * SIDE EFFECTS:
715  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
716  */ 
717         ORG_CALL_PAL_PRIV(0x2B)
718 CallPal_WrFen:
719         mfpr    p0, ptPcbb              // Get PCBB
720         and     a0, 1, a0               // Clean new FEN value to single bit
721         mtpr    a0, qemu_fen
722         stl_p   a0, PCB_Q_FEN(p0)       // Write new PCB<FEN>
723         hw_rei
725         ORG_CALL_PAL_PRIV(0x2C)
726 CallPal_OpcDec2C:
727         br      CallPal_OpcDec
730  * Write Virtual Page Table Pointer
732  * INPUT PARAMETERS:
734  *      r16 (a0) = New virtual page table pointer 
736  * SIDE EFFECTS:
738  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
739  */ 
740         ORG_CALL_PAL_PRIV(0x2D)
741 CallPal_WrVptPtr:
742         mtpr    a0, qemu_vptptr
743         hw_rei
745         ORG_CALL_PAL_PRIV(0x2E)
746 CallPal_OpcDec2E:
747         br      CallPal_OpcDec
749         ORG_CALL_PAL_PRIV(0x2F)
750 CallPal_OpcDec2F:
751         br      CallPal_OpcDec
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.    
762  * 
763  * INPUT PARAMETERS:
764  * 
765  *      r16 (a0) = New PCBB 
766  * 
767  * OUTPUT PARAMETERS:
769  *      r0  (v0) = Old PCBB
770  * 
771  * SIDE EFFECTS:
773  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
774  */ 
775         ORG_CALL_PAL_PRIV(0x30)
776 CallPal_SwpCtx:
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
797         .text   1
798 CallPal_SwpCtxCont:
799         ldq_p   $sp, PCB_Q_KSP(v0)      // Install new stack pointers
800         ldq_p   t10, PCB_Q_USP(v0)
801         mtpr    t10, ptUsp
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
809         and     t8, 1, t8
810         mtpr    t8, qemu_fen
812         // QEMU does not implement an ASN; skip that.
814         ldq_p   t10, PCB_Q_PTBR(a0)     // Install new page tables
815         mtpr    t10, qemu_ptbr
816         mtpr    $31, qemu_tbia          // Flush TLB, since we don't do ASNs
818         hw_rei
819         .previous
822  * Write System Value
824  * INPUT PARAMETERS:
826  *      r16 (a0) = New system value 
827  * 
828  * SIDE EFFECTS:
830  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
831  */ 
832         ORG_CALL_PAL_PRIV(0x31)
833 CallPal_WrVal:
834         mtpr    a0, ptSysVal
835         hw_rei
838  * Read System Value
840  * OUTPUT PARAMETERS:
842  *      r0 (v0) = Returned system value
843  * 
844  * SIDE EFFECTS:
846  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
847  */ 
848         ORG_CALL_PAL_PRIV(0x32)
849 CallPal_RdVal:
850         mfpr    v0, ptSysVal
851         hw_rei
854  * Translation Buffer Invalidate
855  * 
856  * INPUT PARAMETERS:
857  * 
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.
870  * 
871  * SIDE EFFECTS:
873  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
874  */ 
875         ORG_CALL_PAL_PRIV(0x33)
876 CallPal_Tbi:
877         bge     a0, 1f
879         mtpr    $31, qemu_tbia
880         hw_rei
882 1:      mtpr    a1, qemu_tbis
883         hw_rei
886  * Write System Entry Address
888  * INPUT PARAMETERS:
890  *      r16 (a0) = VA of system entry point
891  *      r17 (a1) = System entry point selector 
892  * 
893  * SIDE EFFECTS:
895  *      Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
896  *      upon return.
897  */ 
898         ORG_CALL_PAL_PRIV(0x34)
899 CallPal_WrEnt:
900         andnot  a0, 3, a0               // Clean PC<1:0>
902         cmpult  a1, 6, t8               // Bound the input
903         cmoveq  t8, 7, a1
905         br      t0, 1f
906 1:      lda     t0, WrEnt_Table-1b(t0)
907         s8addq  t0, a1, t0
908         jmp     $31, (t0), WrEnt_Table
910         .text   1
911 WrEnt_Table:
912 0:      mtpr    a0, ptEntInt
913         hw_rei
914 1:      mtpr    a0, ptEntArith
915         hw_rei
916 2:      mtpr    a0, ptEntMM
917         hw_rei
918 3:      mtpr    a0, ptEntIF
919         hw_rei
920 4:      mtpr    a0, ptEntUna
921         hw_rei
922 5:      mtpr    a0, ptEntSys
923         hw_rei
924 6:      nop
925         hw_rei
926         .previous
929  * Swap Interrupt Priority Level
930  * 
931  * INPUT PARAMETERS:
932  * 
933  *      r16 (a0) = New IPL
934  * 
935  * OUTPUT PARAMETERS:
937  *      r0  (v0) = Old IPL
938  * 
939  * SIDE EFFECTS:
941  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
942  */ 
943         ORG_CALL_PAL_PRIV(0x35)
944 CallPal_SwpIpl:
945         mfpr    v0, qemu_ps
946         and     a0, PS_M_IPL, a0
947         and     v0, PS_M_IPL, v0
948         mtpr    a0, qemu_ps
949         hw_rei
952  * Read Processor Status
954  * OUTPUT PARAMETERS:
956  *      r0 (v0) = Current PS
957  * 
958  * SIDE EFFECTS:
960  *      Registers t0, t8..t11 are UNPREDICTABLE upon return.
961  */ 
962         ORG_CALL_PAL_PRIV(0x36)
963 CallPal_RdPs:
964         mfpr    v0, qemu_ps
965         hw_rei
968  * Write Kernel Global Pointer
970  * INPUT PARAMETERS:
971  * 
972  *      r16 (a0) = New KGP value
974  * SIDE EFFECTS:
976  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
977  */ 
978         ORG_CALL_PAL_PRIV(0x37)
979 CallPal_WrKgp:
980         mtpr    a0, ptKgp
981         hw_rei
984  * Write User Stack Pointer
985  * 
986  * INPUT PARAMETERS:
987  * 
988  *      r16 (a0) = New user stack pointer value
989  * 
990  * SIDE EFFECTS:
992  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
993  */ 
994         ORG_CALL_PAL_PRIV(0x38)
995 CallPal_WrUsp:
996         mtpr    a0, ptUsp
997         hw_rei
1000  * Write Performance Monitor
1002  * INPUT PARAMETERS:
1003  * 
1004  *      r16 (a0) = New user stack pointer value
1005  * 
1006  * SIDE EFFECTS:
1008  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1009  */
1010         ORG_CALL_PAL_PRIV(0x39)
1011 CallPal_WrPerfMon:
1012         // Not implemented
1013         hw_rei
1015  * Read User Stack Pointer
1016  * 
1017  * OUTPUT PARAMETERS:
1019  *      r0 (v0) = User stack pointer value
1020  * 
1021  * SIDE EFFECTS:
1023  *      Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1024  */ 
1025         ORG_CALL_PAL_PRIV(0x3A)
1026 CallPal_RdUsp:
1027         mfpr    v0, ptUsp
1028         hw_rei
1030         ORG_CALL_PAL_PRIV(0x3B)
1031 CallPal_OpcDec3B:
1032         br      CallPal_OpcDec
1035  * Who Am I
1036  * 
1037  * OUTPUT PARAMETERS:
1039  *      r0 (v0) = Current processor number
1040  * 
1041  * SIDE EFFECTS:
1043  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1044  */ 
1045         ORG_CALL_PAL_PRIV(0x3C)
1046 CallPal_Whami:
1047         // We do not currently support more cpus
1048         mov     0, v0
1049         hw_rei
1052  * Return From System Call
1054  * INPUT PARAMETERS:
1055  * 
1056  *      r30 (sp) = Pointer to the top of the kernel stack
1057  * 
1058  * OUTPUT PARAMETERS:
1060  *      r29 (gp) = Restored user mode global pointer
1061  *      r30 (sp) = User stack pointer
1062  * 
1063  * SIDE EFFECTS:
1065  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1066  */ 
1067         ORG_CALL_PAL_PRIV(0x3D)
1068 CallPal_RetSys:
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)
1072         mtpr    t8, ptKsp
1074         mov     PS_K_USER, t8           // Set new mode to user
1075         mtpr    t8, qemu_ps
1077         mfpr    $sp, ptUsp              // Get the user stack pointer
1079         andnot  t9, 3, t9               // Clean return PC<1:0>
1080         hw_ret  (t9)
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.
1092  * INPUT PARAMETERS:
1093  * 
1094  *      ???
1095  * 
1096  * OUTPUT PARAMETERS:
1098  *      ???
1099  * 
1100  * SIDE EFFECTS:
1102  *      ???
1103  */
1104         ORG_CALL_PAL_PRIV(0x3E)
1105 CallPal_WtInt:
1106         hw_rei
1109  * Return From Trap, Fault, or Interrupt
1111  * INPUT PARAMETERS:
1112  * 
1113  *      r30 (sp) = Pointer to the top of the kernel stack
1114  * 
1115  * OUTPUT PARAMETERS:
1117  *      ps       <- (sp+00)
1118  *      pc       <- (sp+08)
1119  *      r29 (gp) <- (sp+16)
1120  *      r16 (a0) <- (sp+24)
1121  *      r17 (a1) <- (sp+32)
1122  *      r18 (a2) <- (sp+40)
1123  */ 
1124         ORG_CALL_PAL_PRIV(0x3F)
1125 CallPal_Rti:
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>
1138         and     p4, PS_M_CM, p3
1139         bne     p3, CallPal_Rti_ToUser
1141         and     p4, PS_M_IPL, p4
1142         mtpr    p4, qemu_ps
1143         hw_ret  (p5)
1145         .text   1
1146 CallPal_Rti_ToUser:
1147         mtpr    p4, qemu_ps
1148         mtpr    $sp, ptKsp
1149         mfpr    $sp, ptUsp
1150         hw_ret  (p5)
1151         .previous
1155  * OSF/1 Unprivileged CALL_PAL Entry Points
1156  */
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.
1164  * INPUT PARAMETERS:
1166  *      p5 = ps
1167  *      p6 = exc_addr
1168  *      p7 = return address
1170  * SIDE EFFECTS:
1172  *      p0 is clobbered
1174  */
1175         .text   1
1176 CallPal_Stack_Frame:
1177         // Test if we're currently in user mode
1178         and     p5, PS_M_CM, p0
1179         bne     p0, 0f
1180 CallPal_Stack_Frame_FromUser:
1181         // Switch to kernel mode
1182         mtpr    $31, qemu_ps
1183         mtpr    $sp, ptUsp
1184         mfpr    $sp, ptKsp
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)
1194         ret     $31, (p7), 0
1195         .previous
1198  * Breakpoint Trap
1200  * OUTPUT PARAMETERS:
1202  *      r16 (a0) = Code for bpt (0)
1203  *      r17 (a1) = UNPREDICTABLE
1204  *      r18 (a2) = UNPREDICTABLE
1205  */ 
1206         ORG_CALL_PAL_UNPRIV(0x80)
1207 CallPal_Bpt:
1208         mfpr    p5, qemu_ps
1209         mfpr    p6, qemu_exc_addr
1210         bsr     p7, CallPal_Stack_Frame
1212         mfpr    p0, ptEntIF
1213         mfpr    $gp, ptKgp
1214         mov     IF_K_BPT, a0
1215         hw_ret  (p0)
1218  * Bugcheck Trap
1219  * 
1220  * OUTPUT PARAMETERS:
1222  *      r16 (a0) = Code for bugchk (1)
1223  *      r17 (a1) = UNPREDICTABLE
1224  *      r18 (a2) = UNPREDICTABLE
1225  */ 
1226         ORG_CALL_PAL_UNPRIV(0x81)
1227 CallPal_BugChk:
1228         mfpr    p5, qemu_ps
1229         mfpr    p6, qemu_exc_addr
1230         bsr     p7, CallPal_Stack_Frame
1232         mfpr    p0, ptEntIF
1233         mfpr    $gp, ptKgp
1234         mov     IF_K_BUGCHK, a0
1235         hw_ret  (p0)
1238         ORG_CALL_PAL_UNPRIV(0x82)
1239 CallPal_OpcDec82:
1240         br      CallPal_OpcDec
1243  * System Call
1244  */ 
1245         ORG_CALL_PAL_UNPRIV(0x83)
1246 CallPal_CallSys:
1247         mfpr    p5, qemu_ps
1248         mfpr    p6, qemu_exc_addr
1250         and     p5, PS_M_CM, p0
1251         beq     p0, 0f
1253         bsr     p7, CallPal_Stack_Frame_FromUser
1255         mfpr    p0, ptEntSys
1256         mfpr    $gp, ptKgp
1257         hw_ret  (p0)
1259 0:      subq    p6, 4, p6               // Get PC of CALL_PAL insn
1260         br      MchkOSBugCheck
1262         ORG_CALL_PAL_UNPRIV(0x84)
1263 CallPal_OpcDec84:
1264         br      CallPal_OpcDec
1266         ORG_CALL_PAL_UNPRIV(0x85)
1267 CallPal_OpcDec85:
1268         br      CallPal_OpcDec
1272  * I-Stream Memory Barrier
1274  * For QEMU, this is of course a no-op.
1275  */ 
1276         ORG_CALL_PAL_UNPRIV(0x86)
1277 CallPal_Imb:
1278         hw_rei
1281         ORG_CALL_PAL_UNPRIV(0x87)
1282 CallPal_OpcDec87:
1283         br      CallPal_OpcDec
1285         ORG_CALL_PAL_UNPRIV(0x88)
1286 CallPal_OpcDec88:
1287         br      CallPal_OpcDec
1289         ORG_CALL_PAL_UNPRIV(0x89)
1290 CallPal_OpcDec89:
1291         br      CallPal_OpcDec
1293         ORG_CALL_PAL_UNPRIV(0x8A)
1294 CallPal_OpcDec8A:
1295         br      CallPal_OpcDec
1297         ORG_CALL_PAL_UNPRIV(0x8B)
1298 CallPal_OpcDec8B:
1299         br      CallPal_OpcDec
1301         ORG_CALL_PAL_UNPRIV(0x8C)
1302 CallPal_OpcDec8C:
1303         br      CallPal_OpcDec
1305         ORG_CALL_PAL_UNPRIV(0x8D)
1306 CallPal_OpcDec8D:
1307         br      CallPal_OpcDec
1309         ORG_CALL_PAL_UNPRIV(0x8E)
1310 CallPal_OpcDec8E:
1311         br      CallPal_OpcDec
1313         ORG_CALL_PAL_UNPRIV(0x8F)
1314 CallPal_OpcDec8F:
1315         br      CallPal_OpcDec
1317         ORG_CALL_PAL_UNPRIV(0x90)
1318 CallPal_OpcDec90:
1319         br      CallPal_OpcDec
1321         ORG_CALL_PAL_UNPRIV(0x91)
1322 CallPal_OpcDec91:
1323         br      CallPal_OpcDec
1325         ORG_CALL_PAL_UNPRIV(0x92)
1326 CallPal_OpcDec92:
1327         br      CallPal_OpcDec
1329         ORG_CALL_PAL_UNPRIV(0x93)
1330 CallPal_OpcDec93:
1331         br      CallPal_OpcDec
1333         ORG_CALL_PAL_UNPRIV(0x94)
1334 CallPal_OpcDec94:
1335         br      CallPal_OpcDec
1337         ORG_CALL_PAL_UNPRIV(0x95)
1338 CallPal_OpcDec95:
1339         br      CallPal_OpcDec
1341         ORG_CALL_PAL_UNPRIV(0x96)
1342 CallPal_OpcDec96:
1343         br      CallPal_OpcDec
1345         ORG_CALL_PAL_UNPRIV(0x97)
1346 CallPal_OpcDec97:
1347         br      CallPal_OpcDec
1349         ORG_CALL_PAL_UNPRIV(0x98)
1350 CallPal_OpcDec98:
1351         br      CallPal_OpcDec
1353         ORG_CALL_PAL_UNPRIV(0x99)
1354 CallPal_OpcDec99:
1355         br      CallPal_OpcDec
1357         ORG_CALL_PAL_UNPRIV(0x9A)
1358 CallPal_OpcDec9A:
1359         br      CallPal_OpcDec
1361         ORG_CALL_PAL_UNPRIV(0x9B)
1362 CallPal_OpcDec9B:
1363         br      CallPal_OpcDec
1365         ORG_CALL_PAL_UNPRIV(0x9C)
1366 CallPal_OpcDec9C:
1367         br      CallPal_OpcDec
1369         ORG_CALL_PAL_UNPRIV(0x9D)
1370 CallPal_OpcDec9D:
1371         br      CallPal_OpcDec
1374  * Read Unique Value
1375  * 
1376  * OUTPUT PARAMETERS:
1378  *      r0 (v0) = Returned process unique value
1379 */ 
1380         ORG_CALL_PAL_UNPRIV(0x9E)
1381 CallPal_RdUnique:
1382         mfpr    v0, qemu_unique
1383         hw_rei
1386  * Write Unique Value
1387  * 
1388  * INPUT PARAMETERS:
1389  * 
1390  *      r16 (a0) = New process unique value
1391  */ 
1392         ORG_CALL_PAL_UNPRIV(0x9F)
1393 CallPal_WrUnique:
1394         mtpr    a0, qemu_unique
1395         hw_rei
1398         ORG_CALL_PAL_UNPRIV(0xA0)
1399 CallPal_OpcDecA0:
1400         br      CallPal_OpcDec
1402         ORG_CALL_PAL_UNPRIV(0xA1)
1403 CallPal_OpcDecA1:
1404         br      CallPal_OpcDec
1406         ORG_CALL_PAL_UNPRIV(0xA2)
1407 CallPal_OpcDecA2:
1408         br      CallPal_OpcDec
1410         ORG_CALL_PAL_UNPRIV(0xA3)
1411 CallPal_OpcDecA3:
1412         br      CallPal_OpcDec
1414         ORG_CALL_PAL_UNPRIV(0xA4)
1415 CallPal_OpcDecA4:
1416         br      CallPal_OpcDec
1418         ORG_CALL_PAL_UNPRIV(0xA5)
1419 CallPal_OpcDecA5:
1420         br      CallPal_OpcDec
1422         ORG_CALL_PAL_UNPRIV(0xA6)
1423 CallPal_OpcDecA6:
1424         br      CallPal_OpcDec
1426         ORG_CALL_PAL_UNPRIV(0xA7)
1427 CallPal_OpcDecA7:
1428         br      CallPal_OpcDec
1430         ORG_CALL_PAL_UNPRIV(0xA8)
1431 CallPal_OpcDecA8:
1432         br      CallPal_OpcDec
1434         ORG_CALL_PAL_UNPRIV(0xA9)
1435 CallPal_OpcDecA9:
1436         br      CallPal_OpcDec
1438  * Generate Trap
1440  * OUTPUT PARAMETERS:
1442  *      r16 (a0) = Code for gentrap (2)
1443  *      r17 (a1) = UNPREDICTABLE
1444  *      r18 (a2) = UNPREDICTABLE
1445  */ 
1446         ORG_CALL_PAL_UNPRIV(0xAA)
1447 CallPal_GenTrap:
1448         mfpr    p5, qemu_ps
1449         mfpr    p6, qemu_exc_addr
1450         bsr     p7, CallPal_Stack_Frame
1452         mfpr    p0, ptEntIF
1453         mfpr    $gp, ptKgp
1454         mov     IF_K_GENTRAP, a0
1455         hw_ret  (p0)
1458         ORG_CALL_PAL_UNPRIV(0xAB)
1459 CallPal_OpcDecAB:
1460         br      CallPal_OpcDec
1462         ORG_CALL_PAL_UNPRIV(0xAC)
1463 CallPal_OpcDecAC:
1464         br      CallPal_OpcDec
1466         ORG_CALL_PAL_UNPRIV(0xAD)
1467 CallPal_OpcDecAD:
1468         br      CallPal_OpcDec
1470         ORG_CALL_PAL_UNPRIV(0xAE)
1471 CallPal_OpcDecAE:
1472         br      CallPal_OpcDec
1474         ORG_CALL_PAL_UNPRIV(0xAF)
1475 CallPal_OpcDecAF:
1476         br      CallPal_OpcDec
1478         ORG_CALL_PAL_UNPRIV(0xB0)
1479 CallPal_OpcDecB0:
1480         br      CallPal_OpcDec
1482         ORG_CALL_PAL_UNPRIV(0xB1)
1483 CallPal_OpcDecB1:
1484         br      CallPal_OpcDec
1486         ORG_CALL_PAL_UNPRIV(0xB2)
1487 CallPal_OpcDecB2:
1488         br      CallPal_OpcDec
1490         ORG_CALL_PAL_UNPRIV(0xB3)
1491 CallPal_OpcDecB3:
1492         br      CallPal_OpcDec
1494         ORG_CALL_PAL_UNPRIV(0xB4)
1495 CallPal_OpcDecB4:
1496         br      CallPal_OpcDec
1498         ORG_CALL_PAL_UNPRIV(0xB5)
1499 CallPal_OpcDecB5:
1500         br      CallPal_OpcDec
1502         ORG_CALL_PAL_UNPRIV(0xB6)
1503 CallPal_OpcDecB6:
1504         br      CallPal_OpcDec
1506         ORG_CALL_PAL_UNPRIV(0xB7)
1507 CallPal_OpcDecB7:
1508         br      CallPal_OpcDec
1510         ORG_CALL_PAL_UNPRIV(0xB8)
1511 CallPal_OpcDecB8:
1512         br      CallPal_OpcDec
1514         ORG_CALL_PAL_UNPRIV(0xB9)
1515 CallPal_OpcDecB9:
1516         br      CallPal_OpcDec
1518         ORG_CALL_PAL_UNPRIV(0xBA)
1519 CallPal_OpcDecBA:
1520         br      CallPal_OpcDec
1522         ORG_CALL_PAL_UNPRIV(0xBB)
1523 CallPal_OpcDecBB:
1524         br      CallPal_OpcDec
1526         ORG_CALL_PAL_UNPRIV(0xBC)
1527 CallPal_OpcDecBC:
1528         br      CallPal_OpcDec
1530         ORG_CALL_PAL_UNPRIV(0xBD)
1531 CallPal_OpcDecBD:
1532         br      CallPal_OpcDec
1534         ORG_CALL_PAL_UNPRIV(0xBE)
1535 CallPal_OpcDecBE:
1536         br      CallPal_OpcDec
1538         ORG_CALL_PAL_UNPRIV(0xBF)
1539 CallPal_OpcDec:
1540         mfpr    p5, qemu_ps
1541         mfpr    p6, qemu_exc_addr
1542         bsr     p7, CallPal_Stack_Frame
1544         mfpr    p0, ptEntIF
1545         mfpr    $gp, ptKgp
1546         mov     IF_K_OPCDEC, a0
1547         hw_ret  (p0)
1549         .org    0x3000
1550         .text   1
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. 
1566  * 
1567  * CALLING SEQUENCE:
1568  * 
1569  *      Called when an internal processor error is detected
1570  *      that cannot be successfully corrected by hardware or
1571  *      PALcode.
1572  * 
1573  * INPUT PARAMETERS:
1575  *      r14 (p6) = Exception address 
1576  * 
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
1587  *      ptMces<MIP>     = Set
1588  * 
1589  * SIDE EFFECTS:
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 
1594  *      handler.
1595  */
1597 MchkBugCheck:
1598         lda     p7, MCHK_K_BUGCHECK
1599         br      1f
1600 MchkOSBugCheck:
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
1605         zap     p4, 0x3c, p4
1606         or      p4, p7, p4              // Combine MCES and error code
1608         ldah    p7, SCB_Q_PROCMCHK      // Combine SCB and MCHK bits
1609         or      p4, p7, p7
1610         or      p7, MCES_M_MIP, p7      // Set machine-check-in-progress
1611         mtpr    p7, ptMces
1613 MchkCommon_SaveRegs:
1614         mtpr    v0, ptMchk0             // Save temporaries
1615         mtpr    t0, ptMchk1
1616         mtpr    t3, ptMchk2
1617         mtpr    t4, ptMchk3
1618         mtpr    t5, ptMchk4
1619         mtpr    p6, ptMchk5             // Save the exception address
1621         blbs    p4, MchkDouble
1622         blbs    p6, MchkFromPal
1625  * Common Machine Check Handler
1627  * INPUT STATE:
1629  *      ptMchk0         Saved v0
1630  *      ptMchk1         Saved t0
1631  *      ptMchk2         Saved t3
1632  *      ptMchk3         Saved t4
1633  *      ptMchk4         Saved t5
1634  *      ptMchk5         Saved exc_addr
1635  *      ptMisc<47:32>   MCHK code
1636  *      ptMisc<31:16>   SCB vector
1637  *      ptMces<MIP>     Set
1639  * Registers v0, t0, and t3 .. t5 are available for use, in
1640  * addition to the shadow registers.
1641  */
1643 MchkCommon:
1644         mov     0, t4                   // Assume non-retryable.
1646         mfpr    t5, ptMisc              // Load MCHK code
1647         extwl   t5, 4, t5
1648         andnot  t5, 1, t5
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:
1664  * 
1665  *      a0 (r16) = Machine check entry type
1666  *      a1 (r17) = Platform-specific interrupt vector
1667  *      a2 (r18) = Pointer to logout area
1668  */
1670 .macro  STORE_IPR       which, offset, base
1671         mfpr    v0, \which
1672         stq_p   v0, \offset(\base)
1673 .endm
1675 MchkLogOut:
1676         mfpr    p6, ptPgp               // Get address of logout frame
1677         lda     p6, laf_base(p6)        !gprel
1679         lda     t3, $laf_size
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
1722         mfpr    t0, ptMchk1
1723         mfpr    t3, ptMchk2
1724         mfpr    t4, ptMchk3
1725         mfpr    t5, ptMchk4
1726         mfpr    p7, ptMchk5
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
1751         mfpr    v0, ptMchk0
1753         // Build the stack frame on the kernel stack and post the interrupt
1754         mfpr    p7, ptMisc
1755         extwl   p7, 4, p7
1756         mov     p6, p4                  // Stash pointer to logout
1757         lda     a1, SCB_Q_SYSMCHK
1758         blbs    p7, 0f                  // Check if stack frame already built
1760         mfpr    p5, qemu_ps
1761         mfpr    p6, ptMchk5             // Reload exc_addr for double mchk
1763         STACK_FRAME     p5, p6, p7
1765         mov     IPL_K_MCHK, p5          // Raise IPL
1766         mtpr    p5, qemu_ps
1768         mfpr    a1, ptMisc              // Isolate SCB vector
1769         extwl   a1, 2, a1
1771 0:      mfpr    p7, ptEntInt
1772         lda     a0, INT_K_MCHK
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
1779         mfpr    $gp, ptKgp
1780         hw_ret  (p7)
1783 MchkDouble:
1784         bsr     p7, UpdatePCB
1785         lda     v0, HLT_K_DBL_MCHK
1786         br      Sys_EnterConsole
1788 MchkFromPal:
1789         bsr     p7, UpdatePCB
1790         lda     v0, HLT_K_MCHK_FROM_PAL
1791         br      Sys_EnterConsole
1793 MchkKspInvalid:
1794         bsr     p7, UpdatePCB
1795         lda     v0, HLT_K_KSP_INVAL
1796         br      Sys_EnterConsole
1799  * Update the current PCB with new SP and CC info.
1801  * INPUT PARAMETERS:
1803  *      p7      = return linkage
1804  */
1806 UpdatePCB:
1807         rpcc    p5
1808         mfpr    p4, ptPcbb
1810         mfpr    p3, qemu_ps             // Check current mode
1811         and     p3, PS_M_CM, p3
1812         beq     p3, 1f
1814         mtpr    $sp, ptUsp              // Save user stack pointer
1815         stq_p   $sp, PCB_Q_USP(p4)
1816         br      2f
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
1822         addl    p5, p3, p3
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)
1828         ret     $31, (p7), 0
1831  * FIXME
1832  */
1833 Sys_EnterConsole:
1834 Sys_Cserve:
1835         halt
1838  * Allocate the logout frame.
1839  */
1840         .section        .sbss
1841         .type   laf_base,@object
1842         .align  3
1843 laf_base:
1844 laf_l_size:             .long   0
1845 laf_l_flag:             .long   0
1846 laf_l_cpu:              .long   0
1847 laf_l_sys:              .long   0
1848 laf_q_mchk_code:        .quad   0
1850 $las_size               = . - laf_base
1852 laf_cpu_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
1859 laf_q_isr:              .quad   0
1860 laf_q_icsr:             .quad   0
1861 laf_q_icperr:           .quad   0
1862 laf_q_dcperr:           .quad   0
1863 laf_q_va:               .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
1873 laf_sys_base:
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
1888         .align 3
1889         .type   stack,@object
1890         .size   stack,STACK_SIZE
1891 stack:  .skip   STACK_SIZE