blob: d6046662119a52c2a296cb92beaa67082d6e1583 [file] [log] [blame]
.set noat
.set nomacro
.text
#include "osf.h"
#include "uart.h"
/* General Purpose Registers. */
#define v0 $0
#define t0 $1
#define t1 $2
#define t2 $3
#define t3 $4
#define t4 $5
#define t5 $6
#define a0 $16
#define a1 $17
#define a2 $18
#define a3 $19
#define a4 $20
#define a5 $21
#define t8 $22
#define t9 $23
#define t10 $24
/* PALcode Shadow Registers. These registers are swapped out when
QEMU is in PALmode. Unlike real hardware, there is no enable bit.
However, also unlike real hardware, the originals can be accessed
via MTPR/MFPR. */
#define p0 $8
#define p1 $9
#define p2 $10
#define p3 $11
#define p4 $12
#define p5 $13
#define p6 $14 // Used to save exc_addr for machine check
#define p7 $25
/* QEMU Processor Registers. */
#define qemu_ps 0
#define qemu_fen 1
#define qemu_pcc_ofs 2
#define qemu_trap_arg0 3
#define qemu_trap_arg1 4
#define qemu_trap_arg2 5
#define qemu_exc_addr 6
#define qemu_palbr 7
#define qemu_ptbr 8
#define qemu_vptptr 9
#define qemu_unique 10
#define qemu_sysval 11
#define qemu_usp 12
#define qemu_shadow0 32
#define qemu_shadow1 33
#define qemu_shadow2 34
#define qemu_shadow3 35
#define qemu_shadow4 36
#define qemu_shadow5 37
#define qemu_shadow6 38
#define qemu_shadow7 39
/* PALcode Processor Register Private Storage. */
#define pt0 40
#define pt1 41
#define pt2 42
#define pt3 43
#define pt4 44
#define pt5 45
#define pt6 46
#define pt7 47
#define pt8 48
#define pt9 49
#define pt10 50
#define pt11 51
#define pt12 52
#define pt13 53
#define pt14 54
#define pt15 55
#define pt16 56
#define pt17 57
#define pt18 58
#define pt19 59
#define pt20 60
#define pt21 61
#define pt22 62
#define pt23 63
/* QEMU function calls, via mtpr. */
#define qemu_tbia 255
#define qemu_tbis 254
#define qemu_wait 253
/* PALcode uses of the private storage slots. */
#define ptEntUna pt0
#define ptEntIF pt1
#define ptEntSys pt2
#define ptEntInt pt3
#define ptEntArith pt4
#define ptEntMM pt5
#define ptMces pt6
#define ptKsp pt7
#define ptKgp pt8
#define ptPcbb pt9
#define ptPgp pt10
#define ptMisc pt11
#define ptMchk0 pt12
#define ptMchk1 pt13
#define ptMchk2 pt14
#define ptMchk3 pt15
#define ptMchk4 pt16
#define ptMchk5 pt17
/*
* Shortcuts for various PALmode instructions.
*/
#define mtpr hw_mtpr
#define mfpr hw_mfpr
#define stq_p hw_stq/p
#define stl_p hw_stl/p
#define ldl_p hw_ldl/p
#define ldq_p hw_ldq/p
/* QEMU recognizes the EV4/EV5 HW_REI instruction as a special case of
the EV6 HW_RET instruction. This pulls the destination address from
the EXC_ADDR processor register. */
#define hw_rei hw_ret ($31)
/*
* Create a standard kernel entry stack frame.
*/
#define FRM_Q_PS 0
#define FRM_Q_PC 8
#define FRM_Q_GP 16
#define FRM_Q_A0 24
#define FRM_Q_A1 32
#define FRM_Q_A2 40
#define FRM_K_SIZE 48
.macro STACK_FRAME save_ps, save_pc, temp, do_ps
// Test if we're currently in user mode
and \save_ps, PS_M_CM, \temp
beq \temp, 0f
// Switch to kernel mode
.ifne \do_ps
mtpr $31, qemu_ps
.endif
mtpr $sp, qemu_usp
mfpr $sp, ptKsp
// Allocate the stack frame
0: lda $sp, -FRM_K_SIZE($sp)
stq \save_ps, FRM_Q_PS($sp)
stq \save_pc, FRM_Q_PC($sp)
stq $gp, FRM_Q_GP($sp)
stq a0, FRM_Q_A0($sp)
stq a1, FRM_Q_A1($sp)
stq a2, FRM_Q_A2($sp)
.endm
.macro ENDFN function
.type \function, @function
.size \function, . - \function
.endm
/*
* Allocate a 1 page stack for use by the console.
*/
#define STACK_SIZE 8192
/*
* QEMU emulator "hardware" entry points.
*/
/*
* Reset
*
* INPUT PARAMETERS:
*
* trap_arg0 = Memory size
* trap_arg1 = Kernel entry (if loaded)
*/
.org 0x0000
.globl __start
__start:
// Initialize GP and stack.
br $gp, .+4
ldah $gp, 0($gp) !gpdisp!1
lda $gp, 0($gp) !gpdisp!1
mtpr $gp, ptPgp
lda $sp, stack+STACK_SIZE($gp) !gprel
// Disable interrupts; kernel mode
lda t0, IPL_K_HIGH
mtpr t0, qemu_ps
// Make sure kernel entry points are invalid.
lda t0, -1
mtpr t0, ptEntUna
mtpr t0, ptEntIF
mtpr t0, ptEntSys
mtpr t0, ptEntInt
mtpr t0, ptEntArith
mtpr t0, ptEntMM
// Load boot arguments
mfpr a0, qemu_trap_arg0
mfpr a1, qemu_trap_arg1
mfpr a2, qemu_trap_arg2
// Continue in do_start, outside PALmode.
ldah $27, do_start($gp) !gprelhigh
lda $27, do_start($27) !gprellow
hw_ret ($27)
ENDFN __start
/*
* Machine Check
*
* INPUT PARAMETERS:
*
* trap_arg0 =
* trap_arg1 =
* trap_arg2 =
*/
.org 0x0080
Pal_Mchk:
mfpr p5, ptMces // Get the error summary
or p5, MCES_M_MIP, p4 // Set machine-check-in-progress
zap p4, 0x3c, p4 // Clear space for MCHK and SCB
mtpr p4, ptMces
ldah p0, SCB_Q_PROCMCHK
or p4, p0, p4 // Merge in the SCB vector
lda p0, MCHK_K_PROC_HERR
sll p0, PT16_V_MCHK, p0
or p4, p0, p4 // Merge in the MCHK code
mtpr p4, ptMisc
br MchkCommon_SaveRegs
ENDFN Pal_Mchk
/*
* Clock Interrupt
*
* INPUT PARAMETERS:
*
* trap_arg0 =
* trap_arg1 =
* trap_arg2 =
*
* The clock interrupt is special, in that PALcode is supposed
* to clear the interupt and not wait for the OS to do it.
*/
.org 0x0100
Pal_Clk_Interrupt:
mfpr p6, qemu_exc_addr
// Load CIA_BW_IO. Note that this is the KSEG address,
// since there is no hw_stb with physical address access.
lda p0, -887
sll p0, 32, p0
mov 0xc, p1 // Set RTCADD (0x70) to index register 0xC
stb p1, 0x70(p0)
ldbu p1, 0x71(p0) // Read RTCDAT to clear interrupt.
#if 0
and p1, 0x40, p1 // Check for real interrupt.
bne p1, 9f // If not, exit now, no stack frame.
#endif
mfpr p0, qemu_ps
STACK_FRAME p0, p6, p2, 0
mov IPL_K_CLK, p0 // Raise IPL
mtpr p0, qemu_ps
mfpr p6, ptEntInt
mfpr $gp, ptKgp
lda a0, INT_K_CLK
lda a1, 0
lda a2, 0
9: hw_ret (p6)
ENDFN Pal_Clk_Interrupt
/*
* Device Interrupt
*
* INPUT PARAMETERS:
*
* trap_arg0 =
* trap_arg1 =
* trap_arg2 =
*/
.org 0x0180
Pal_Dev_Interrupt:
mfpr p6, qemu_exc_addr
mfpr p0, qemu_ps
STACK_FRAME p0, p6, p2, 0
mov IPL_K_DEV1, p0 // Raise IPL
mtpr p0, qemu_ps
mfpr p7, ptEntInt
mfpr $gp, ptKgp
lda a0, INT_K_DEV
lda a1, 0x800
lda a2, 0
hw_ret (p7)
ENDFN Pal_Dev_Interrupt
/*
* Memory Fault
*
* INPUT PARAMETERS:
*
* trap_arg0 = faulting address
* trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
* trap_arg2 = access type (exec=-1, read=0, write=1)
*/
.org 0x0200
Pal_MMFault:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
blbs p6, MchkBugCheck
STACK_FRAME p0, p6, p2, 1
mfpr p0, ptEntMM
mfpr $gp, ptKgp
mfpr a0, qemu_trap_arg0
mfpr a1, qemu_trap_arg1
mfpr a2, qemu_trap_arg2
hw_ret (p0)
ENDFN Pal_MMFault
/*
* Unaligned Data
*
* INPUT PARAMETERS:
*
* trap_arg0 = faulting address
* trap_arg1 = opcode of faulting insn
* trap_arg2 = src/dst register number
*/
.org 0x0280
Pal_Unalign:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
addq p6, 4, p1 // increment past the faulting insn
blbs p6, MchkBugCheck
STACK_FRAME p0, p1, p2, 1
mfpr p0, ptEntUna
mfpr $gp, ptKgp
mfpr a0, qemu_trap_arg0
mfpr a1, qemu_trap_arg1
mfpr a2, qemu_trap_arg2
hw_ret (p0)
ENDFN Pal_Unalign
/*
* Illegal Opcode
*
* INPUT PARAMETERS:
*
* trap_arg0 = UNDEFINED
* trap_arg1 = UNDEFINED
* trap_arg2 = UNDEFINED
*
* OUTPUT PARAMETERS:
*
* r16 (a0) = Instruction fault code
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
.org 0x0300
Pal_OpcDec:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
addq p6, 4, p1 // increment past the faulting insn
blbs p6, MchkBugCheck
STACK_FRAME p0, p1, p2, 1
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_OPCDEC, a0
hw_ret (p0)
ENDFN Pal_OpcDec
/*
* Arithmetic Trap
*
* INPUT PARAMETERS:
*
* trap_arg0 = exception type
* trap_arg1 = register modification mask
* trap_arg2 = UNDEFINED
*/
.org 0x0380
Pal_Arith:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
blbs p6, MchkBugCheck
STACK_FRAME p0, p6, p2, 1
mfpr p0, ptEntArith
mfpr $gp, ptKgp
mfpr a0, qemu_trap_arg0
mfpr a1, qemu_trap_arg1
hw_ret (p0)
ENDFN Pal_Arith
/*
* Floating Point Disabled
*
* INPUT PARAMETERS:
*
* trap_arg0 = UNDEFINED
* trap_arg1 = UNDEFINED
* trap_arg2 = UNDEFINED
*
* OUTPUT PARAMETERS:
*
* r16 (a0) = Instruction fault code
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
.org 0x0400
Pal_Fen:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
blbs p6, MchkBugCheck
STACK_FRAME p0, p6, p2, 1
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_FEN, a0
hw_ret (p0)
ENDFN Pal_Fen
/*
* OSF/1 Privileged CALL_PAL Entry Points
*/
#define ORG_CALL_PAL_PRIV(X) .org 0x1000+64*X
/*
* Halt
*
* SIDE EFFECTS:
*
* We either power down the system or re-enter the console.
* But given that we're not returning to the kernel, there's
* no reason to continue processing in assembler. Go to C.
*/
ORG_CALL_PAL_PRIV(0x00)
CallPal_Halt:
bsr p7, UpdatePCB // Save kernel data
lda v0, HLT_K_SW_HALT
ldah p0, 1 // Store 0xdead into CIA RESET reg
lda p0, -(0x10000 - 0xdead)(p0)
lda p1, 0x878
sll p1, 28, p1
lda p1, 0x900(p1)
stl_p p0, 0(p1)
br Sys_EnterConsole
ENDFN CallPal_Halt
/*
* Cache Flush
*
* For QEMU, this is of course a no-op.
*/
ORG_CALL_PAL_PRIV(0x01)
CallPal_Cflush:
hw_rei
ENDFN CallPal_Cflush
/*
* Drain Aborts
*
* For QEMU, this is of course a no-op.
*/
ORG_CALL_PAL_PRIV(0x02)
CallPal_Draina:
hw_rei
ENDFN CallPal_Draina
ORG_CALL_PAL_PRIV(0x03)
CallPal_OpcDec03:
br CallPal_OpcDec
ENDFN CallPal_OpcDec03
ORG_CALL_PAL_PRIV(0x04)
CallPal_OpcDec04:
br CallPal_OpcDec
ENDFN CallPal_OpcDec04
ORG_CALL_PAL_PRIV(0x05)
CallPal_OpcDec05:
br CallPal_OpcDec
ENDFN CallPal_OpcDec05
ORG_CALL_PAL_PRIV(0x06)
CallPal_OpcDec06:
br CallPal_OpcDec
ENDFN CallPal_OpcDec06
ORG_CALL_PAL_PRIV(0x07)
CallPal_OpcDec07:
br CallPal_OpcDec
ENDFN CallPal_OpcDec07
ORG_CALL_PAL_PRIV(0x08)
CallPal_OpcDec08:
br CallPal_OpcDec
ENDFN CallPal_OpcDec08
/*
* Console Service
*
* INPUT PARAMETERS:
*
* r16 (a0) = Option selector
* r17..r21 (a1..a5) = Implementation specific entry parameters
*
* SIDE EFFECTS:
*
* Registers a0..a5, and v0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x09)
CallPal_Cserve:
cmpeq a0, 15, v0
bne v0, Cserve_putc
cmpeq a0, 52, v0
bne v0, Cserve_ena
cmpeq a0, 53, v0
bne v0, Cserve_dis
hw_rei
ENDFN CallPal_Cserve
.text 1
Cserve_putc:
// Load CIA_BW_IO. Note that this is the KSEG address,
// since there is no hw_stb with physical address access.
lda p0, -887
sll p0, 32, p0
ldbu v0, com1Lsr(p0) // Get Transmit Holding Register Empty
and v0, 0x20, v0
beq v0, 1f
stb a1, com1Thr(p0) // Output the byte
mov 1, v0
1: hw_rei
ENDFN Cserve_putc
Cserve_ena:
lda p0, 0x87a // Load PYXIS INT REG base.
sll p0, 28, p0
lda p1, 1 // Shift the interrupt line in place.
sll p1, a1, p1
ldq_p p2, 0x40(p0) // Load PYXIS_INT_MASK
sll p2, a1, v0 // Return the current setting
and v0, 1, v0
andnot p2, p1, p2 // Clear the bit
stq_p p2, 0x40(p0) // Store PYXIS_INT_MASK
hw_rei
ENDFN Cserve_ena
Cserve_dis:
lda p0, 0x87a // Load PYXIS INT REG base.
sll p0, 28, p0
lda p1, 1 // Shift the interrupt line in place.
sll p1, a1, p1
ldq_p p2, 0x40(p0) // Load PYXIS_INT_MASK
sll p2, a1, v0 // Return the current setting
and v0, 1, v0
or p2, p1, p2 // Set the bit
stq_p p2, 0x40(p0) // Store PYXIS_INT_MASK
hw_rei
ENDFN Cserve_dis
.previous
/*
* Swap PALcode
*
* FUNCTIONAL DESCRIPTION:
*
* The swap PALcode (swppal) function replaces the current
* (active) PALcode by the specified new PALcode image.
* This function is intended for use by operating systems
* only during bootstraps and restarts, or during transitions
* to console I/O mode.
*
* The PALcode descriptor passed in a0 is interpreted as
* either a PALcode variant or the base physical address
* of the new PALcode image. If a variant, the PALcode
* image must have been previously loaded. No PALcode
* loading occurs as a result of this function.
*
* NOTE:
* This implementation of SWPPAL does not support PALcode
* variants. If a variant is specified in a0, a check is
* performed to determine whether the variant is OSF/1 or
* not and the returned status is either unknown variant
* (if not OSF/1) or variant not loaded.
*
* INPUT PARAMETERS:
*
* r16 (a0) = New PALcode variant or base physical address
* r17 (a1) = New PC
* r18 (a2) = New PCB
* r19 (a3) = New VptPtr
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Returned status indicating:
* 0 - Success (PALcode was switched)
* 1 - Unknown PALcode variant
* 2 - Known PALcode variant, but PALcode not loaded
*
* r26 (ra) = r27 (pv) = New PC
* Note that this is non-architected, but is relied on by
* the usage of SwpPal within our own console code in order
* to simplify its use within C code.
*
*/
ORG_CALL_PAL_PRIV(0x0A)
CallPal_SwpPal:
// Save a copy of the return address in case of machine check.
mfpr p6, qemu_exc_addr
// Accept swapping to OSF PALcode. The side effect here is to
// load the other parameters for the kernel.
cmpeq a0, 2, v0
bne v0, CallPal_SwpPal_Cont
// Return as an unknown PALcode variant
mov 1, v0
hw_rei
ENDFN CallPal_SwpPal
.text 1
CallPal_SwpPal_Cont:
rpcc p0
mtpr a2, ptPcbb
mtpr a3, qemu_vptptr
ldq_p $sp, PCB_Q_KSP(a2)
ldq_p t0, PCB_Q_USP(a2)
ldq_p t1, PCB_Q_PTBR(a2)
ldl_p t2, PCB_L_PCC(a2)
ldq_p t3, PCB_Q_UNIQUE(a2)
ldq_p t4, PCB_Q_FEN(a2)
mtpr t0, qemu_usp
sll t1, VA_S_OFF, t1
mtpr t1, qemu_ptbr
subl t2, p0, t2
mtpr t2, qemu_pcc_ofs
mtpr t3, qemu_unique
and t4, 1, t4
mtpr t4, qemu_fen
mtpr $31, qemu_tbia // Flush TLB for new PTBR
mov a1, $26
mov a1, $27
hw_ret (a1)
ENDFN CallPal_SwpPal_Cont
.previous
ORG_CALL_PAL_PRIV(0x0B)
CallPal_OpcDec0B:
br CallPal_OpcDec
ENDFN CallPal_OpcDec0B
ORG_CALL_PAL_PRIV(0x0C)
CallPal_OpcDec0C:
br CallPal_OpcDec
ENDFN CallPal_OpcDec0C
/*
* Write Interprocessor Interrupt Request
*
* INPUT PARAMETERS:
*
* r16 (a0) = target processor number
*
* OUTPUT PARAMETERS:
*
* SIDE EFFECTS:
*
*/
ORG_CALL_PAL_PRIV(0x0D)
CallPal_WrIpir:
// We do not currently support more cpus
hw_rei
ENDFN CallPal_WrIpir
ORG_CALL_PAL_PRIV(0x0E)
CallPal_OpcDec0E:
br CallPal_OpcDec
ENDFN CallPal_OpcDec0E
ORG_CALL_PAL_PRIV(0x0F)
CallPal_OpcDec0F:
br CallPal_OpcDec
ENDFN CallPal_OpcDec0F
/*
* Read Machine Check Error Summary
*
* INPUT PARAMETERS:
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = returned MCES value
*
* SIDE EFFECTS:
*
*/
ORG_CALL_PAL_PRIV(0x10)
CallPal_RdMces:
mfpr v0, ptMces // Get current MCES value
and v0, MCES_M_ALL, v0 // Clear all other bits
hw_rei
ENDFN CallPal_RdMces
/*
* Write Machine Check Error Summary
*
* INPUT PARAMETERS:
*
* r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4>
*
* OUTPUT PARAMETERS:
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x11)
CallPal_WrMces:
// Clear MIP, SCE, PCE
and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
mfpr p1, ptMces
bic p1, p0, p1
// Copy DPC and DSC
and a0, (MCES_M_DPC | MCES_M_DSC), p0
bic p1, (MCES_M_DPC | MCES_M_DSC), p1
or p1, p0, p1
mtpr p1, ptMces
hw_rei
ENDFN CallPal_WrMces
ORG_CALL_PAL_PRIV(0x12)
CallPal_OpcDec12:
br CallPal_OpcDec
ENDFN CallPal_OpcDec12
ORG_CALL_PAL_PRIV(0x13)
CallPal_OpcDec13:
br CallPal_OpcDec
ENDFN CallPal_OpcDec13
ORG_CALL_PAL_PRIV(0x14)
CallPal_OpcDec14:
br CallPal_OpcDec
ENDFN CallPal_OpcDec14
ORG_CALL_PAL_PRIV(0x15)
CallPal_OpcDec15:
br CallPal_OpcDec
ENDFN CallPal_OpcDec15
ORG_CALL_PAL_PRIV(0x16)
CallPal_OpcDec16:
br CallPal_OpcDec
ENDFN CallPal_OpcDec16
ORG_CALL_PAL_PRIV(0x17)
CallPal_OpcDec17:
br CallPal_OpcDec
ENDFN CallPal_OpcDec17
ORG_CALL_PAL_PRIV(0x18)
CallPal_OpcDec18:
br CallPal_OpcDec
ENDFN CallPal_OpcDec18
ORG_CALL_PAL_PRIV(0x19)
CallPal_OpcDec19:
br CallPal_OpcDec
ENDFN CallPal_OpcDec19
ORG_CALL_PAL_PRIV(0x1A)
CallPal_OpcDec1A:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1A
ORG_CALL_PAL_PRIV(0x1B)
CallPal_OpcDec1B:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1B
ORG_CALL_PAL_PRIV(0x1C)
CallPal_OpcDec1C:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1C
ORG_CALL_PAL_PRIV(0x1D)
CallPal_OpcDec1D:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1D
ORG_CALL_PAL_PRIV(0x1E)
CallPal_OpcDec1E:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1E
ORG_CALL_PAL_PRIV(0x1F)
CallPal_OpcDec1F:
br CallPal_OpcDec
ENDFN CallPal_OpcDec1F
ORG_CALL_PAL_PRIV(0x20)
CallPal_OpcDec20:
br CallPal_OpcDec
ENDFN CallPal_OpcDec20
ORG_CALL_PAL_PRIV(0x21)
CallPal_OpcDec21:
br CallPal_OpcDec
ENDFN CallPal_OpcDec21
ORG_CALL_PAL_PRIV(0x22)
CallPal_OpcDec22:
br CallPal_OpcDec
ENDFN CallPal_OpcDec22
ORG_CALL_PAL_PRIV(0x23)
CallPal_OpcDec23:
br CallPal_OpcDec
ENDFN CallPal_OpcDec23
ORG_CALL_PAL_PRIV(0x24)
CallPal_OpcDec24:
br CallPal_OpcDec
ENDFN CallPal_OpcDec24
ORG_CALL_PAL_PRIV(0x25)
CallPal_OpcDec25:
br CallPal_OpcDec
ENDFN CallPal_OpcDec25
ORG_CALL_PAL_PRIV(0x26)
CallPal_OpcDec26:
br CallPal_OpcDec
ENDFN CallPal_OpcDec26
ORG_CALL_PAL_PRIV(0x27)
CallPal_OpcDec27:
br CallPal_OpcDec
ENDFN CallPal_OpcDec27
ORG_CALL_PAL_PRIV(0x28)
CallPal_OpcDec28:
br CallPal_OpcDec
ENDFN CallPal_OpcDec28
ORG_CALL_PAL_PRIV(0x29)
CallPal_OpcDec29:
br CallPal_OpcDec
ENDFN CallPal_OpcDec29
ORG_CALL_PAL_PRIV(0x2A)
CallPal_OpcDec2A:
br CallPal_OpcDec
ENDFN CallPal_OpcDec2A
/*
* Write Floating Point Enable
*
* INPUT PARAMETERS:
*
* r16 (a0) = ICSR<FPE> <- a0<0>
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x2B)
CallPal_WrFen:
mfpr p0, ptPcbb // Get PCBB
and a0, 1, a0 // Clean new FEN value to single bit
mtpr a0, qemu_fen
stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN>
hw_rei
ENDFN CallPal_WrFen
ORG_CALL_PAL_PRIV(0x2C)
CallPal_OpcDec2C:
br CallPal_OpcDec
ENDFN CallPal_OpcDec2C
/*
* Write Virtual Page Table Pointer
*
* INPUT PARAMETERS:
*
* r16 (a0) = New virtual page table pointer
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x2D)
CallPal_WrVptPtr:
mtpr a0, qemu_vptptr
hw_rei
ENDFN CallPal_WrVptPtr
ORG_CALL_PAL_PRIV(0x2E)
CallPal_OpcDec2E:
br CallPal_OpcDec
ENDFN CallPal_OpcDec2E
ORG_CALL_PAL_PRIV(0x2F)
CallPal_OpcDec2F:
br CallPal_OpcDec
ENDFN CallPal_OpcDec2F
/*
* Swap Process Context
*
* FUNCTIONAL DESCRIPTION:
*
* The swap process context (swpctx) function saves
* the current process data in the current PCB, then
* switches to the PCB passed in a0 and loads the
* new process context. The old PCB is returned in v0.
*
* INPUT PARAMETERS:
*
* r16 (a0) = New PCBB
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Old PCBB
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x30)
CallPal_SwpCtx:
rpcc p5 // Get cycle counter
mfpr p6, qemu_exc_addr // Save exc_addr for machine check
mfpr v0, ptPcbb // Get current PCBB
mtpr a0, ptPcbb // Save new PCBB
srl p5, 32, p7 // Move CC<OFFSET> to low longword
addl p5, p7, p7 // Accumulate time for old pcb
stl_p p7, PCB_L_PCC(v0)
ldl_p t9, PCB_L_PCC(a0) // Get new PCC
subl t9, p5, p5 // Generate and ...
mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits
stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer
mfpr t10, qemu_usp // Save old user stack pointer
stq_p t10, PCB_Q_USP(v0)
br CallPal_SwpCtx_Cont
ENDFN CallPal_SwpCtx
.text 1
CallPal_SwpCtx_Cont:
ldq_p $sp, PCB_Q_KSP(a0) // Install new stack pointers
ldq_p t10, PCB_Q_USP(a0)
mtpr t10, qemu_usp
mfpr t10, qemu_unique // Save old unique value
stq_p t10, PCB_Q_UNIQUE(v0)
ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
mtpr t10, qemu_unique
ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
and t8, 1, t8
mtpr t8, qemu_fen
// QEMU does not implement an ASN; skip that.
ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
sll t10, VA_S_OFF, t10
mtpr t10, qemu_ptbr
mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
hw_rei
ENDFN CallPal_SwpCtx_Cont
.previous
/*
* Write System Value
*
* INPUT PARAMETERS:
*
* r16 (a0) = New system value
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x31)
CallPal_WrVal:
mtpr a0, qemu_sysval
hw_rei
ENDFN CallPal_WrVal
/*
* Read System Value
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Returned system value
*
* SIDE EFFECTS:
*
* Registers t0 and t8..t11 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x32)
CallPal_RdVal:
mfpr v0, qemu_sysval
hw_rei
ENDFN CallPal_RdVal
/*
* Translation Buffer Invalidate
*
* INPUT PARAMETERS:
*
* r16 (a0) = tbi selector type:
*
* -2 - Flush all TB entries (tbia)
* -1 - Invalidate all TB entries with ASM=0 (tbiap)
* 1 - Invalidate ITB entry for va=a1 (tbisi)
* 2 - Invalidate DTB entry for va=a1 (tbisd)
* 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
*
* r17 (a1) = VA for TBISx types
*
* Qemu does not implement ASNs or split I/D tlbs. Therefore these
* collapse to tbia and tbis.
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x33)
CallPal_Tbi:
bge a0, 1f
mtpr $31, qemu_tbia
hw_rei
1: mtpr a1, qemu_tbis
hw_rei
ENDFN CallPal_Tbi
/*
* Write System Entry Address
*
* INPUT PARAMETERS:
*
* r16 (a0) = VA of system entry point
* r17 (a1) = System entry point selector
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
* upon return.
*/
ORG_CALL_PAL_PRIV(0x34)
CallPal_WrEnt:
andnot a0, 3, a0 // Clean PC<1:0>
cmpult a1, 6, t8 // Bound the input
cmoveq t8, 6, a1
br t0, 1f
1: lda t0, WrEnt_Table-1b(t0)
s8addq a1, t0, t0
jmp $31, (t0), 0
ENDFN CallPal_WrEnt
.text 1
WrEnt_Table:
0: mtpr a0, ptEntInt
hw_rei
1: mtpr a0, ptEntArith
hw_rei
2: mtpr a0, ptEntMM
hw_rei
3: mtpr a0, ptEntIF
hw_rei
4: mtpr a0, ptEntUna
hw_rei
5: mtpr a0, ptEntSys
hw_rei
6: nop
hw_rei
ENDFN WrEnt_Table
.previous
/*
* Swap Interrupt Priority Level
*
* INPUT PARAMETERS:
*
* r16 (a0) = New IPL
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Old IPL
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x35)
CallPal_SwpIpl:
mfpr v0, qemu_ps
and a0, PS_M_IPL, a0
and v0, PS_M_IPL, v0
mtpr a0, qemu_ps
hw_rei
ENDFN CallPal_SwpIpl
/*
* Read Processor Status
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Current PS
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x36)
CallPal_RdPs:
mfpr v0, qemu_ps
hw_rei
ENDFN CallPal_RdPs
/*
* Write Kernel Global Pointer
*
* INPUT PARAMETERS:
*
* r16 (a0) = New KGP value
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x37)
CallPal_WrKgp:
mtpr a0, ptKgp
hw_rei
ENDFN CallPal_WrKgp
/*
* Write User Stack Pointer
*
* INPUT PARAMETERS:
*
* r16 (a0) = New user stack pointer value
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x38)
CallPal_WrUsp:
mtpr a0, qemu_usp
hw_rei
ENDFN CallPal_WrUsp
/*
* Write Performance Monitor
*
* INPUT PARAMETERS:
*
* r16 (a0) = New user stack pointer value
*
* SIDE EFFECTS:
*
* Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x39)
CallPal_WrPerfMon:
// Not implemented
hw_rei
ENDFN CallPal_WrPerfMon
/*
* Read User Stack Pointer
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = User stack pointer value
*
* SIDE EFFECTS:
*
* Registers t0, and t8..t11 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x3A)
CallPal_RdUsp:
mfpr v0, qemu_usp
hw_rei
ENDFN CallPal_RdUsp
ORG_CALL_PAL_PRIV(0x3B)
CallPal_OpcDec3B:
br CallPal_OpcDec
ENDFN CallPal_OpcDec3B
/*
* Who Am I
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Current processor number
*
* SIDE EFFECTS:
*
* Registers t0 and t8..t11 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x3C)
CallPal_Whami:
// We do not currently support more cpus
mov 0, v0
hw_rei
ENDFN CallPal_Whami
/*
* Return From System Call
*
* INPUT PARAMETERS:
*
* r30 (sp) = Pointer to the top of the kernel stack
*
* OUTPUT PARAMETERS:
*
* r29 (gp) = Restored user mode global pointer
* r30 (sp) = User stack pointer
*
* SIDE EFFECTS:
*
* Registers t0 and t8..t11 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x3D)
CallPal_RetSys:
ldq t9, FRM_Q_PC($sp) // Pop the return address
ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer
lda t8, FRM_K_SIZE($sp)
mtpr t8, ptKsp
mov PS_K_USER, t8 // Set new mode to user
mtpr t8, qemu_ps
mfpr $sp, qemu_usp // Get the user stack pointer
andnot t9, 3, t9 // Clean return PC<1:0>
hw_ret (t9)
ENDFN CallPal_RetSys
/*
* Wait For Interrupt
*
* FUNCTIONAL DESCRIPTION:
*
* If possible, wait for the first of either of the following
* conditions before returning: any interrupt other than a clock
* tick; or the first clock tick after a specified number of clock
* ticks have bbeen skipped.
*
* INPUT PARAMETERS:
*
* r16 (a0) = Maximum number of clock ticks to skip
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Number of clock ticks actually skipped.
*/
ORG_CALL_PAL_PRIV(0x3E)
CallPal_WtInt:
mtpr $31, qemu_wait
mov 0, v0
hw_rei
ENDFN CallPal_WtInt
/*
* Return From Trap, Fault, or Interrupt
*
* INPUT PARAMETERS:
*
* r30 (sp) = Pointer to the top of the kernel stack
*
* OUTPUT PARAMETERS:
*
* ps <- (sp+00)
* pc <- (sp+08)
* r29 (gp) <- (sp+16)
* r16 (a0) <- (sp+24)
* r17 (a1) <- (sp+32)
* r18 (a2) <- (sp+40)
*/
ORG_CALL_PAL_PRIV(0x3F)
CallPal_Rti:
mfpr p6, qemu_exc_addr // Save exc_addr for machine check
ldq p4, FRM_Q_PS($sp) // Get the PS
ldq p5, FRM_Q_PC($sp) // Get the return PC
ldq $gp, FRM_Q_GP($sp) // Get gp
ldq a0, FRM_Q_A0($sp) // Get a0
ldq a1, FRM_Q_A1($sp) // Get a1
ldq a2, FRM_Q_A2($sp) // Get a2
lda $sp, FRM_K_SIZE($sp) // Pop the stack
andnot p5, 3, p5 // Clean return PC<1:0>
and p4, PS_M_CM, p3
bne p3, CallPal_Rti_ToUser
and p4, PS_M_IPL, p4
mtpr p4, qemu_ps
hw_ret (p5)
ENDFN CallPal_Rti
.text 1
CallPal_Rti_ToUser:
mtpr p3, qemu_ps
mtpr $sp, ptKsp
mfpr $sp, qemu_usp
hw_ret (p5)
ENDFN CallPal_Rti_ToUser
.previous
/*
* OSF/1 Unprivileged CALL_PAL Entry Points
*/
#define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80)
/*
* A helper routine for the unprivaledged kernel entry points, since the
* actual stack frame setup code is just a tad too large to fit inline.
*
* INPUT PARAMETERS:
*
* p5 = ps
* p6 = exc_addr
* p7 = return address
*
* SIDE EFFECTS:
*
* p0 is clobbered
*
*/
.text 1
CallPal_Stack_Frame:
// Test if we're currently in user mode
and p5, PS_M_CM, p0
beq p0, 0f
CallPal_Stack_Frame_FromUser:
// Switch to kernel mode
mtpr $31, qemu_ps
mtpr $sp, qemu_usp
mfpr $sp, ptKsp
0:
// Allocate the stack frame
lda $sp, -FRM_K_SIZE($sp)
stq p5, FRM_Q_PS($sp)
stq p6, FRM_Q_PC($sp)
stq $gp, FRM_Q_GP($sp)
stq a0, FRM_Q_A0($sp)
stq a1, FRM_Q_A1($sp)
stq a2, FRM_Q_A2($sp)
ret $31, (p7), 0
ENDFN CallPal_Stack_Frame
.previous
/*
* Breakpoint Trap
*
* OUTPUT PARAMETERS:
*
* r16 (a0) = Code for bpt (0)
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
ORG_CALL_PAL_UNPRIV(0x80)
CallPal_Bpt:
mfpr p5, qemu_ps
mfpr p6, qemu_exc_addr
bsr p7, CallPal_Stack_Frame
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_BPT, a0
hw_ret (p0)
ENDFN CallPal_Bpt
/*
* Bugcheck Trap
*
* OUTPUT PARAMETERS:
*
* r16 (a0) = Code for bugchk (1)
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
ORG_CALL_PAL_UNPRIV(0x81)
CallPal_BugChk:
mfpr p5, qemu_ps
mfpr p6, qemu_exc_addr
bsr p7, CallPal_Stack_Frame
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_BUGCHK, a0
hw_ret (p0)
ENDFN CallPal_BugChk
ORG_CALL_PAL_UNPRIV(0x82)
CallPal_OpcDec82:
br CallPal_OpcDec
ENDFN CallPal_OpcDec82
/*
* System Call
*/
ORG_CALL_PAL_UNPRIV(0x83)
CallPal_CallSys:
mfpr p5, qemu_ps
mfpr p6, qemu_exc_addr
and p5, PS_M_CM, p0
beq p0, 0f
bsr p7, CallPal_Stack_Frame_FromUser
mfpr p0, ptEntSys
mfpr $gp, ptKgp
hw_ret (p0)
0: subq p6, 4, p6 // Get PC of CALL_PAL insn
br MchkOSBugCheck
ENDFN CallPal_CallSys
ORG_CALL_PAL_UNPRIV(0x84)
CallPal_OpcDec84:
br CallPal_OpcDec
ENDFN CallPal_OpcDec84
ORG_CALL_PAL_UNPRIV(0x85)
CallPal_OpcDec85:
br CallPal_OpcDec
ENDFN CallPal_OpcDec85
/*
* I-Stream Memory Barrier
*
* For QEMU, this is of course a no-op.
*/
ORG_CALL_PAL_UNPRIV(0x86)
CallPal_Imb:
hw_rei
ENDFN CallPal_Imb
ORG_CALL_PAL_UNPRIV(0x87)
CallPal_OpcDec87:
br CallPal_OpcDec
ENDFN CallPal_OpcDec87
ORG_CALL_PAL_UNPRIV(0x88)
CallPal_OpcDec88:
br CallPal_OpcDec
ENDFN CallPal_OpcDec88
ORG_CALL_PAL_UNPRIV(0x89)
CallPal_OpcDec89:
br CallPal_OpcDec
ENDFN CallPal_OpcDec89
ORG_CALL_PAL_UNPRIV(0x8A)
CallPal_OpcDec8A:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8A
ORG_CALL_PAL_UNPRIV(0x8B)
CallPal_OpcDec8B:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8B
ORG_CALL_PAL_UNPRIV(0x8C)
CallPal_OpcDec8C:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8C
ORG_CALL_PAL_UNPRIV(0x8D)
CallPal_OpcDec8D:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8D
ORG_CALL_PAL_UNPRIV(0x8E)
CallPal_OpcDec8E:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8E
ORG_CALL_PAL_UNPRIV(0x8F)
CallPal_OpcDec8F:
br CallPal_OpcDec
ENDFN CallPal_OpcDec8F
ORG_CALL_PAL_UNPRIV(0x90)
CallPal_OpcDec90:
br CallPal_OpcDec
ENDFN CallPal_OpcDec90
ORG_CALL_PAL_UNPRIV(0x91)
CallPal_OpcDec91:
br CallPal_OpcDec
ENDFN CallPal_OpcDec91
ORG_CALL_PAL_UNPRIV(0x92)
CallPal_OpcDec92:
br CallPal_OpcDec
ENDFN CallPal_OpcDec92
ORG_CALL_PAL_UNPRIV(0x93)
CallPal_OpcDec93:
br CallPal_OpcDec
ENDFN CallPal_OpcDec93
ORG_CALL_PAL_UNPRIV(0x94)
CallPal_OpcDec94:
br CallPal_OpcDec
ENDFN CallPal_OpcDec94
ORG_CALL_PAL_UNPRIV(0x95)
CallPal_OpcDec95:
br CallPal_OpcDec
ENDFN CallPal_OpcDec95
ORG_CALL_PAL_UNPRIV(0x96)
CallPal_OpcDec96:
br CallPal_OpcDec
ENDFN CallPal_OpcDec96
ORG_CALL_PAL_UNPRIV(0x97)
CallPal_OpcDec97:
br CallPal_OpcDec
ENDFN CallPal_OpcDec97
ORG_CALL_PAL_UNPRIV(0x98)
CallPal_OpcDec98:
br CallPal_OpcDec
ENDFN CallPal_OpcDec98
ORG_CALL_PAL_UNPRIV(0x99)
CallPal_OpcDec99:
br CallPal_OpcDec
ENDFN CallPal_OpcDec99
ORG_CALL_PAL_UNPRIV(0x9A)
CallPal_OpcDec9A:
br CallPal_OpcDec
ENDFN CallPal_OpcDec9A
ORG_CALL_PAL_UNPRIV(0x9B)
CallPal_OpcDec9B:
br CallPal_OpcDec
ENDFN CallPal_OpcDec9B
ORG_CALL_PAL_UNPRIV(0x9C)
CallPal_OpcDec9C:
br CallPal_OpcDec
ENDFN CallPal_OpcDec9C
ORG_CALL_PAL_UNPRIV(0x9D)
CallPal_OpcDec9D:
br CallPal_OpcDec
ENDFN CallPal_OpcDec9D
/*
* Read Unique Value
*
* OUTPUT PARAMETERS:
*
* r0 (v0) = Returned process unique value
*/
ORG_CALL_PAL_UNPRIV(0x9E)
CallPal_RdUnique:
mfpr v0, qemu_unique
hw_rei
ENDFN CallPal_RdUnique
/*
* Write Unique Value
*
* INPUT PARAMETERS:
*
* r16 (a0) = New process unique value
*/
ORG_CALL_PAL_UNPRIV(0x9F)
CallPal_WrUnique:
mtpr a0, qemu_unique
hw_rei
ENDFN CallPal_WrUnique
ORG_CALL_PAL_UNPRIV(0xA0)
CallPal_OpcDecA0:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA0
ORG_CALL_PAL_UNPRIV(0xA1)
CallPal_OpcDecA1:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA1
ORG_CALL_PAL_UNPRIV(0xA2)
CallPal_OpcDecA2:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA2
ORG_CALL_PAL_UNPRIV(0xA3)
CallPal_OpcDecA3:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA3
ORG_CALL_PAL_UNPRIV(0xA4)
CallPal_OpcDecA4:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA4
ORG_CALL_PAL_UNPRIV(0xA5)
CallPal_OpcDecA5:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA5
ORG_CALL_PAL_UNPRIV(0xA6)
CallPal_OpcDecA6:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA6
ORG_CALL_PAL_UNPRIV(0xA7)
CallPal_OpcDecA7:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA7
ORG_CALL_PAL_UNPRIV(0xA8)
CallPal_OpcDecA8:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA8
ORG_CALL_PAL_UNPRIV(0xA9)
CallPal_OpcDecA9:
br CallPal_OpcDec
ENDFN CallPal_OpcDecA9
/*
* Generate Trap
*
* OUTPUT PARAMETERS:
*
* r16 (a0) = Code for gentrap (2)
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
ORG_CALL_PAL_UNPRIV(0xAA)
CallPal_GenTrap:
mfpr p5, qemu_ps
mfpr p6, qemu_exc_addr
bsr p7, CallPal_Stack_Frame
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_GENTRAP, a0
hw_ret (p0)
ENDFN CallPal_GenTrap
ORG_CALL_PAL_UNPRIV(0xAB)
CallPal_OpcDecAB:
br CallPal_OpcDec
ENDFN CallPal_OpcDecAB
ORG_CALL_PAL_UNPRIV(0xAC)
CallPal_OpcDecAC:
br CallPal_OpcDec
ENDFN CallPal_OpcDecAC
ORG_CALL_PAL_UNPRIV(0xAD)
CallPal_OpcDecAD:
br CallPal_OpcDec
ENDFN CallPal_OpcDecAD
ORG_CALL_PAL_UNPRIV(0xAE)
CallPal_OpcDecAE:
br CallPal_OpcDec
ENDFN CallPal_OpcDecAE
ORG_CALL_PAL_UNPRIV(0xAF)
CallPal_OpcDecAF:
br CallPal_OpcDec
ENDFN CallPal_OpcDecAF
ORG_CALL_PAL_UNPRIV(0xB0)
CallPal_OpcDecB0:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB0
ORG_CALL_PAL_UNPRIV(0xB1)
CallPal_OpcDecB1:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB1
ORG_CALL_PAL_UNPRIV(0xB2)
CallPal_OpcDecB2:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB2
ORG_CALL_PAL_UNPRIV(0xB3)
CallPal_OpcDecB3:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB3
ORG_CALL_PAL_UNPRIV(0xB4)
CallPal_OpcDecB4:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB4
ORG_CALL_PAL_UNPRIV(0xB5)
CallPal_OpcDecB5:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB5
ORG_CALL_PAL_UNPRIV(0xB6)
CallPal_OpcDecB6:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB6
ORG_CALL_PAL_UNPRIV(0xB7)
CallPal_OpcDecB7:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB7
ORG_CALL_PAL_UNPRIV(0xB8)
CallPal_OpcDecB8:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB8
ORG_CALL_PAL_UNPRIV(0xB9)
CallPal_OpcDecB9:
br CallPal_OpcDec
ENDFN CallPal_OpcDecB9
ORG_CALL_PAL_UNPRIV(0xBA)
CallPal_OpcDecBA:
br CallPal_OpcDec
ENDFN CallPal_OpcDecBA
ORG_CALL_PAL_UNPRIV(0xBB)
CallPal_OpcDecBB:
br CallPal_OpcDec
ENDFN CallPal_OpcDecBB
ORG_CALL_PAL_UNPRIV(0xBC)
CallPal_OpcDecBC:
br CallPal_OpcDec
ENDFN CallPal_OpcDecBC
ORG_CALL_PAL_UNPRIV(0xBD)
CallPal_OpcDecBD:
br CallPal_OpcDec
ENDFN CallPal_OpcDecBD
ORG_CALL_PAL_UNPRIV(0xBE)
CallPal_OpcDecBE:
br CallPal_OpcDec
ENDFN CallPal_OpcDecBE
ORG_CALL_PAL_UNPRIV(0xBF)
CallPal_OpcDec:
mfpr p5, qemu_ps
mfpr p6, qemu_exc_addr
bsr p7, CallPal_Stack_Frame
mfpr p0, ptEntIF
mfpr $gp, ptKgp
mov IF_K_OPCDEC, a0
hw_ret (p0)
ENDFN CallPal_OpcDec
.org 0x3000
.text 1
/*
* PALcode detected processor machine check handler.
*
* The PALcode-detected machine check handler loads a code
* indicating the type of machine check error, loads
* the System Control Block (SCB) vector for the
* processor machine check service routine, sets the
* Machine-Check-In-Progress (MIP) flag in the Machine
* Check Error Summary register (MCES), and merges
* with the common machine check flow.
*
* If a second processor machine check error condition
* is detected while the MIP flag is set, the processor
* is forced into console I/O mode indicating "double
* error abort encountered" as the reason for the halt.
*
* CALLING SEQUENCE:
*
* Called when an internal processor error is detected
* that cannot be successfully corrected by hardware or
* PALcode.
*
* INPUT PARAMETERS:
*
* r14 (p6) = Exception address
*
* OUTPUT PARAMETERS:
*
* ptMchk0 = saved v0
* ptMchk1 = saved t0
* ptMchk2 = saved t3
* ptMchk3 = saved t4
* ptMchk4 = saved t5
* ptMchk5 = saved exc_addr
* ptMisc<47:32> = MCHK code
* ptMisc<31:16> = SCB vector
* ptMces<MIP> = Set
*
* SIDE EFFECTS:
*
* r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
* PAL temporaries and are available for use as scratch
* registers by the system specific machine check
* handler.
*/
MchkBugCheck:
lda p7, MCHK_K_BUGCHECK
br 1f
MchkOSBugCheck:
lda p7, MCHK_K_OS_BUGCHECK
1: sll p7, PT16_V_MCHK, p7 // Move error code into upper longword
mfpr p4, ptMces // Get and isolate MCES bits
zap p4, 0x3c, p4
or p4, p7, p4 // Combine MCES and error code
ldah p7, SCB_Q_PROCMCHK // Combine SCB and MCHK bits
or p4, p7, p7
or p7, MCES_M_MIP, p7 // Set machine-check-in-progress
mtpr p7, ptMces
MchkCommon_SaveRegs:
mtpr v0, ptMchk0 // Save temporaries
mtpr t0, ptMchk1
mtpr t3, ptMchk2
mtpr t4, ptMchk3
mtpr t5, ptMchk4
mtpr p6, ptMchk5 // Save the exception address
blbs p4, MchkDouble
blbs p6, MchkFromPal
ENDFN MchkBugCheck
/*
* Common Machine Check Handler
*
* INPUT STATE:
*
* ptMchk0 Saved v0
* ptMchk1 Saved t0
* ptMchk2 Saved t3
* ptMchk3 Saved t4
* ptMchk4 Saved t5
* ptMchk5 Saved exc_addr
* ptMisc<47:32> MCHK code
* ptMisc<31:16> SCB vector
* ptMces<MIP> Set
*
* Registers v0, t0, and t3 .. t5 are available for use, in
* addition to the shadow registers.
*/
MchkCommon:
mov 0, t4 // Assume non-retryable.
mfpr t5, ptMisc // Load MCHK code
extwl t5, 4, t5
andnot t5, 1, t5
ENDFN MchkCommon
/*
* Build Machine Check Logout Frame
*
* This portion of the machine check handler builds a logout frame
* in the PAL impure scratch area, builds a stack frame on the kernel
* stack (already built if there was an interrupt machine check),
* loads the GP with the KGP, loads the machine check entry
* code in a0, loads a platform-specific interrupt vector
* (typically the same value as the SCB offset) in a1, loads
* the kseg address of the logout area in a2, and dispatches
* to the kernel interrupt handler pointed to by the entInt
* operating system entry point.
*
* OUTPUT PARAMETERS:
*
* a0 (r16) = Machine check entry type
* a1 (r17) = Platform-specific interrupt vector
* a2 (r18) = Pointer to logout area
*/
.macro STORE_IPR which, offset, base
mfpr v0, \which
stq_p v0, \offset(\base)
.endm
MchkLogOut:
mfpr p6, ptPgp // Get address of logout frame
lda p6, laf_base(p6) !gprel
lda t3, $laf_size
stl_p t3, laf_l_size - laf_base(p6)
stl_p t4, laf_l_flag - laf_base(p6)
lda t3, laf_cpu_base - laf_base
stl_p t3, laf_l_cpu - laf_base(p6)
lda t3, laf_sys_base - laf_base
stl_p t3, laf_l_sys - laf_base(p6)
STORE_IPR qemu_shadow0, laf_q_shadow - laf_base + 0x00, p6
STORE_IPR qemu_shadow1, laf_q_shadow - laf_base + 0x08, p6
STORE_IPR qemu_shadow2, laf_q_shadow - laf_base + 0x10, p6
STORE_IPR qemu_shadow3, laf_q_shadow - laf_base + 0x18, p6
STORE_IPR qemu_shadow4, laf_q_shadow - laf_base + 0x20, p6
STORE_IPR qemu_shadow5, laf_q_shadow - laf_base + 0x28, p6
STORE_IPR qemu_shadow6, laf_q_shadow - laf_base + 0x30, p6
STORE_IPR qemu_shadow7, laf_q_shadow - laf_base + 0x38, p6
STORE_IPR pt0, laf_q_pt - laf_base + 0x00, p6
STORE_IPR pt1, laf_q_pt - laf_base + 0x08, p6
STORE_IPR pt2, laf_q_pt - laf_base + 0x10, p6
STORE_IPR pt3, laf_q_pt - laf_base + 0x18, p6
STORE_IPR pt4, laf_q_pt - laf_base + 0x20, p6
STORE_IPR pt5, laf_q_pt - laf_base + 0x28, p6
STORE_IPR pt6, laf_q_pt - laf_base + 0x30, p6
STORE_IPR pt7, laf_q_pt - laf_base + 0x38, p6
STORE_IPR pt8, laf_q_pt - laf_base + 0x40, p6
STORE_IPR pt9, laf_q_pt - laf_base + 0x48, p6
STORE_IPR pt10, laf_q_pt - laf_base + 0x50, p6
STORE_IPR pt11, laf_q_pt - laf_base + 0x58, p6
STORE_IPR pt12, laf_q_pt - laf_base + 0x60, p6
STORE_IPR pt13, laf_q_pt - laf_base + 0x68, p6
STORE_IPR pt14, laf_q_pt - laf_base + 0x70, p6
STORE_IPR pt15, laf_q_pt - laf_base + 0x78, p6
STORE_IPR pt16, laf_q_pt - laf_base + 0x80, p6
STORE_IPR pt17, laf_q_pt - laf_base + 0x88, p6
STORE_IPR pt18, laf_q_pt - laf_base + 0x90, p6
STORE_IPR pt19, laf_q_pt - laf_base + 0x98, p6
STORE_IPR pt20, laf_q_pt - laf_base + 0xa0, p6
STORE_IPR pt21, laf_q_pt - laf_base + 0xa8, p6
STORE_IPR pt22, laf_q_pt - laf_base + 0xb0, p6
STORE_IPR pt23, laf_q_pt - laf_base + 0xb8, p6
mfpr t0, ptMchk1
mfpr t3, ptMchk2
mfpr t4, ptMchk3
mfpr t5, ptMchk4
mfpr p7, ptMchk5
stq_p p7, laf_q_exc_addr - laf_base(p6)
stq_p $31, laf_q_exc_sum - laf_base(p6)
stq_p $31, laf_q_exc_mask - laf_base(p6)
STORE_IPR qemu_palbr, laf_q_pal_base - laf_base, p6
stq_p $31, laf_q_isr - laf_base(p6)
stq_p $31, laf_q_icsr - laf_base(p6)
stq_p $31, laf_q_icperr - laf_base(p6)
stq_p $31, laf_q_dcperr - laf_base(p6)
stq_p $31, laf_q_va - laf_base(p6)
stq_p $31, laf_q_mm_stat - laf_base(p6)
stq_p $31, laf_q_sc_addr - laf_base(p6)
stq_p $31, laf_q_sc_stat - laf_base(p6)
stq_p $31, laf_q_bc_addr - laf_base(p6)
stq_p $31, laf_q_ei_addr - laf_base(p6)
stq_p $31, laf_q_fill_syndrome - laf_base(p6)
stq_p $31, laf_q_ei_stat - laf_base(p6)
stq_p $31, laf_q_ld_lock - laf_base(p6)
// bsr v0, Sys_MchkLogOut
mfpr v0, ptMchk0
// Build the stack frame on the kernel stack and post the interrupt
mfpr p7, ptMisc
extwl p7, 4, p7
mov p6, p4 // Stash pointer to logout
lda a1, SCB_Q_SYSMCHK
blbs p7, 0f // Check if stack frame already built
mfpr p5, qemu_ps
mfpr p6, ptMchk5 // Reload exc_addr for double mchk
STACK_FRAME p5, p6, p7, 0
mov IPL_K_MCHK, p5 // Raise IPL
mtpr p5, qemu_ps
mfpr a1, ptMisc // Isolate SCB vector
extwl a1, 2, a1
0: mfpr p7, ptEntInt
lda a0, INT_K_MCHK
lda a2, -1 // Load kseg offset
srl a2, VA_S_SIZE-1, a2
sll a2, VA_S_SIZE-1, a2
addq a2, p4, a2 // Pass ptr to logout area
mfpr $gp, ptKgp
hw_ret (p7)
ENDFN MchkLogOut
MchkDouble:
bsr p7, UpdatePCB
lda v0, HLT_K_DBL_MCHK
br Sys_EnterConsole
ENDFN MchkDouble
MchkFromPal:
bsr p7, UpdatePCB
lda v0, HLT_K_MCHK_FROM_PAL
br Sys_EnterConsole
ENDFN MchkFromPal
MchkKspInvalid:
bsr p7, UpdatePCB
lda v0, HLT_K_KSP_INVAL
br Sys_EnterConsole
ENDFN MchkKspInvalid
/*
* Update the current PCB with new SP and CC info.
*
* INPUT PARAMETERS:
*
* p7 = return linkage
*/
UpdatePCB:
rpcc p5
mfpr p4, ptPcbb
mfpr p3, qemu_ps // Check current mode
and p3, PS_M_CM, p3
beq p3, 1f
mtpr $sp, qemu_usp // Save user stack pointer
stq_p $sp, PCB_Q_USP(p4)
br 2f
1: mtpr $sp, ptKsp // Save kernel stack pointer
stq_p $sp, PCB_Q_KSP(p4)
2: srl p5, 32, p3 // Merge for new time
addl p5, p3, p3
stl_p p3, PCB_L_PCC(p4) // Store new time
mfpr p5, qemu_unique // Save unique
stq_p p5, PCB_Q_UNIQUE(p4)
ret $31, (p7), 0
ENDFN UpdatePCB
/*
* FIXME
*/
Sys_EnterConsole:
halt
/*
* Allocate the logout frame.
*/
.section .sbss
.type laf_base,@object
.align 3
laf_base:
laf_l_size: .long 0
laf_l_flag: .long 0
laf_l_cpu: .long 0
laf_l_sys: .long 0
laf_q_mchk_code: .quad 0
$las_size = . - laf_base
laf_cpu_base:
laf_q_shadow: .skip 8*8
laf_q_pt: .skip 8*24
laf_q_exc_addr: .quad 0
laf_q_exc_sum: .quad 0
laf_q_exc_mask: .quad 0
laf_q_pal_base: .quad 0
laf_q_isr: .quad 0
laf_q_icsr: .quad 0
laf_q_icperr: .quad 0
laf_q_dcperr: .quad 0
laf_q_va: .quad 0
laf_q_mm_stat: .quad 0
laf_q_sc_addr: .quad 0
laf_q_sc_stat: .quad 0
laf_q_bc_addr: .quad 0
laf_q_ei_addr: .quad 0
laf_q_fill_syndrome: .quad 0
laf_q_ei_stat: .quad 0
laf_q_ld_lock: .quad 0
laf_sys_base:
laf_q_cpu_err0: .quad 0
laf_q_cpu_err1: .quad 0
laf_q_cia_err: .quad 0
laf_q_err_mask: .quad 0
laf_q_cia_syn: .quad 0
laf_q_mem_err0: .quad 0
laf_q_mem_err1: .quad 0
laf_q_pci_err0: .quad 0
laf_q_pci_err1: .quad 0
laf_q_pci_err2: .quad 0
$laf_size = . - laf_base
.size laf_base, . - laf_base
.align 3
.globl stack
.type stack,@object
.size stack,STACK_SIZE
stack: .skip STACK_SIZE