1946 lines
36 KiB
ArmAsm
1946 lines
36 KiB
ArmAsm
|
/* QEMU Emulation PALcode.
|
|||
|
|
|||
|
Copyright (C) 2011 Richard Henderson
|
|||
|
|
|||
|
This file is part of QEMU PALcode.
|
|||
|
|
|||
|
This program is free software; you can redistribute it and/or modify
|
|||
|
it under the terms of the GNU General Public License as published by
|
|||
|
the Free Software Foundation; either version 2 of the License or
|
|||
|
(at your option) any later version.
|
|||
|
|
|||
|
This program is distributed in the hope that it will be useful,
|
|||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
|
|||
|
of the GNU General Public License for more details.
|
|||
|
|
|||
|
You should have received a copy of the GNU General Public License
|
|||
|
along with this program; see the file COPYING. If not see
|
|||
|
<http://www.gnu.org/licenses/>. */
|
|||
|
|
|||
|
.set noat
|
|||
|
.set nomacro
|
|||
|
.text
|
|||
|
|
|||
|
#include "pal.h"
|
|||
|
#include "osf.h"
|
|||
|
#include SYSTEM_H
|
|||
|
|
|||
|
/*
|
|||
|
* Create a standard kernel entry stack frame.
|
|||
|
*/
|
|||
|
|
|||
|
.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
|
|||
|
|
|||
|
/*
|
|||
|
* 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.
|
|||
|
br $gp, .+4
|
|||
|
ldah $gp, 0($gp) !gpdisp!1
|
|||
|
lda $gp, 0($gp) !gpdisp!1
|
|||
|
mtpr $gp, ptPgp
|
|||
|
|
|||
|
// Disable interrupts; kernel mode
|
|||
|
lda t0, IPL_K_HIGH
|
|||
|
mtpr t0, qemu_ps
|
|||
|
|
|||
|
// Initialize Stack.
|
|||
|
SYS_WHAMI a0
|
|||
|
lda t0, STACK_SIZE
|
|||
|
addq a0, 1, t1
|
|||
|
mull t0, t1, t0
|
|||
|
ldah t1, stack($gp) !gprelhigh
|
|||
|
lda t1, stack(t1) !gprellow
|
|||
|
addq t0, t1, $sp
|
|||
|
|
|||
|
// Do any necessary system setup required for PALmode,
|
|||
|
// e.g. setting up ptSys[01].
|
|||
|
bsr $26, Sys_Setup
|
|||
|
|
|||
|
// Non-boot CPUs can go wait now.
|
|||
|
bne a0, 1f
|
|||
|
|
|||
|
// Load boot arguments
|
|||
|
mfpr a0, qemu_trap_arg0 // memsize
|
|||
|
mfpr a1, qemu_trap_arg1 // kernel entry
|
|||
|
mfpr a2, qemu_trap_arg2 // ncpus
|
|||
|
|
|||
|
// Continue in do_start, outside PALmode.
|
|||
|
ldah $27, do_start($gp) !gprelhigh
|
|||
|
lda $27, do_start($27) !gprellow
|
|||
|
hw_ret ($27)
|
|||
|
|
|||
|
1: ldah $27, do_start_wait($gp) !gprelhigh
|
|||
|
lda $27, do_start_wait($27) !gprellow
|
|||
|
hw_ret ($27)
|
|||
|
ENDFN __start
|
|||
|
|
|||
|
/*
|
|||
|
* Machine Check
|
|||
|
*
|
|||
|
* INPUT PARAMETERS:
|
|||
|
*
|
|||
|
* trap_arg0 =
|
|||
|
* trap_arg1 =
|
|||
|
* trap_arg2 =
|
|||
|
*/
|
|||
|
.org 0x0080
|
|||
|
Pal_Mchk:
|
|||
|
mfpr p6, qemu_exc_addr // Check for palcode mchk
|
|||
|
blbs p6, MchkFromPal
|
|||
|
mfpr p0, ptMces // Check for double mchk
|
|||
|
blbs p0, MchkDouble
|
|||
|
|
|||
|
// Since this is QEMU, the only MCHK we raise spontaneously
|
|||
|
// is for access to non-existent memory.
|
|||
|
//
|
|||
|
// ??? With MemTxResult we could perhaps distinguish
|
|||
|
// between MEMTX_DECODE_ERROR (no memory) and
|
|||
|
// MEMTX_ERROR (device error), but it's not clear whether
|
|||
|
// "device error" corresponds to "PCI target abort" or whatnot.
|
|||
|
// However the main reason to handle mchk at all is to allow
|
|||
|
// the guest OS to probe for devices, which is just "no memory".
|
|||
|
|
|||
|
lda t0, MCHK_K_SYS_NOMEM
|
|||
|
br MchkLogOut
|
|||
|
ENDFN Pal_Mchk
|
|||
|
|
|||
|
/*
|
|||
|
* Interprocessor Interrupt
|
|||
|
*
|
|||
|
* INPUT PARAMETERS:
|
|||
|
*
|
|||
|
* trap_arg0 =
|
|||
|
* trap_arg1 =
|
|||
|
* trap_arg2 =
|
|||
|
*
|
|||
|
* The interprocessor interrupt is special, in that PALcode is supposed
|
|||
|
* to clear the interupt and not wait for the OS to do it.
|
|||
|
*/
|
|||
|
.org 0x0100
|
|||
|
Pal_Smp_Interrupt:
|
|||
|
mfpr p6, qemu_exc_addr
|
|||
|
|
|||
|
SYS_ACK_SMP p0, p1, p2
|
|||
|
|
|||
|
mfpr p0, qemu_ps
|
|||
|
|
|||
|
STACK_FRAME p0, p6, p2, 0
|
|||
|
|
|||
|
mov IPL_K_IP, p0 // Raise IPL
|
|||
|
mtpr p0, qemu_ps
|
|||
|
|
|||
|
mfpr p6, ptEntInt
|
|||
|
mfpr $gp, ptKgp
|
|||
|
lda a0, INT_K_IP
|
|||
|
lda a1, 0
|
|||
|
lda a2, 0
|
|||
|
|
|||
|
hw_ret (p6)
|
|||
|
ENDFN Pal_Smp_Interrupt
|
|||
|
|
|||
|
/*
|
|||
|
* 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 0x0180
|
|||
|
Pal_Clk_Interrupt:
|
|||
|
mfpr p6, qemu_exc_addr
|
|||
|
|
|||
|
SYS_ACK_CLK p0, p1, p2
|
|||
|
|
|||
|
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 0x0200
|
|||
|
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
|
|||
|
|
|||
|
bsr p7, Sys_Dev_Vector
|
|||
|
|
|||
|
mfpr p7, ptEntInt
|
|||
|
mfpr $gp, ptKgp
|
|||
|
lda a0, INT_K_DEV
|
|||
|
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 0x0280
|
|||
|
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 0x0300
|
|||
|
Pal_Unalign:
|
|||
|
mfpr p0, qemu_ps
|
|||
|
mfpr p6, qemu_exc_addr
|
|||
|
blbs p6, MchkBugCheck
|
|||
|
addq p6, 4, p6 // increment past the faulting insn
|
|||
|
|
|||
|
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 0x0380
|
|||
|
Pal_OpcDec:
|
|||
|
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_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 0x0400
|
|||
|
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 0x0480
|
|||
|
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 // FIXME store this somewhere.
|
|||
|
|
|||
|
mtpr $31, qemu_halt
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
/*
|
|||
|
* Delay for N nanoseconds.
|
|||
|
*
|
|||
|
* This is unique to QEMU, used only within PALcode itself.
|
|||
|
*/
|
|||
|
ORG_CALL_PAL_PRIV(0x03)
|
|||
|
CallPal_Ndelay:
|
|||
|
mfpr p0, qemu_vmtime
|
|||
|
addq p0, a0, p0
|
|||
|
mtpr p0, qemu_alarm
|
|||
|
|
|||
|
mtpr $31, qemu_wait
|
|||
|
|
|||
|
SYS_ACK_CLK p2, p3, p4
|
|||
|
|
|||
|
mfpr v0, qemu_vmtime
|
|||
|
subq p0, v0, v0
|
|||
|
hw_rei
|
|||
|
ENDFN CallPal_Ndelay
|
|||
|
|
|||
|
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:
|
|||
|
// Most of the entries are densely clustered around 0.
|
|||
|
mov 0, v0
|
|||
|
cmpule a0, 7, p0
|
|||
|
cmovne p0, a0, v0
|
|||
|
br p0, 1f
|
|||
|
1: lda p0, Cserve_Table-1b(p0)
|
|||
|
s8addq v0, p0, p0
|
|||
|
jmp $31, (p0), 0
|
|||
|
ENDFN CallPal_Cserve
|
|||
|
|
|||
|
.text 1
|
|||
|
.align 3
|
|||
|
/* Note that the entries in the following table are all 2 insns.
|
|||
|
The first entry is unused, and is also where all out-of-range
|
|||
|
commands are vectored. */
|
|||
|
Cserve_Table:
|
|||
|
br CallPal_Cserve_Cont
|
|||
|
nop
|
|||
|
Cserve_Ldqp:
|
|||
|
ldq_p v0, 0(a1)
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Ldqp
|
|||
|
Cserve_Stqp:
|
|||
|
stq_p a2, 0(a1)
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Stqp
|
|||
|
Cserve_Get_Wall_Time:
|
|||
|
mfpr v0, qemu_walltime
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Get_Wall_Time
|
|||
|
Cserve_Get_Alarm:
|
|||
|
mfpr v0, qemu_alarm
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Get_Alarm
|
|||
|
Cserve_Set_Alarm_Rel:
|
|||
|
// Cheating here: create the absolute time and fall thru.
|
|||
|
mfpr p0, qemu_vmtime
|
|||
|
addq p0, a1, a1
|
|||
|
ENDFN Cserve_Set_Alarm_Rel
|
|||
|
Cserve_Set_Alarm_Abs:
|
|||
|
mtpr a1, qemu_alarm
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Set_Alarm_Abs
|
|||
|
Cserve_Get_VM_Time:
|
|||
|
mfpr v0, qemu_vmtime
|
|||
|
hw_rei
|
|||
|
ENDFN Cserve_Get_VM_Time
|
|||
|
|
|||
|
|
|||
|
CallPal_Cserve_Cont:
|
|||
|
// ??? For SRM compatibility and their use within Linux, use 52/53
|
|||
|
// for these. Anyone know what other "standard" SRM Cserve entry
|
|||
|
// points are? Certainly we don't want to be compatible with MILO,
|
|||
|
// which puts the selector at A2.
|
|||
|
cmpeq a0, 52, v0
|
|||
|
bne v0, Cserve_Ena
|
|||
|
cmpeq a0, 53, v0
|
|||
|
bne v0, Cserve_Dis
|
|||
|
hw_rei
|
|||
|
ENDFN CallPal_Cserve_Cont
|
|||
|
.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:
|
|||
|
// Save a copy of the return address in case of machine check.
|
|||
|
mfpr p6, qemu_exc_addr
|
|||
|
|
|||
|
SYS_WRIPIR a0, p0, p1, p2
|
|||
|
|
|||
|
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:
|
|||
|
SYS_WHAMI 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)
|
|||
|
.globl CallPal_Rti
|
|||
|
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
|
|||
|
lda p0, MCHK_K_OS_BUGCHECK
|
|||
|
br MchkLogOut
|
|||
|
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:
|
|||
|
mb
|
|||
|
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
|
|||
|
/*
|
|||
|
* 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.
|
|||
|
*
|
|||
|
* INPUT PARAMETERS:
|
|||
|
*
|
|||
|
* r8 (p0) = Machine check reason
|
|||
|
* r14 (p6) = Exception address
|
|||
|
*
|
|||
|
* OUTPUT PARAMETERS:
|
|||
|
*
|
|||
|
* a0 (r16) = Machine check entry type
|
|||
|
* a1 (r17) = Platform-specific interrupt vector
|
|||
|
* a2 (r18) = Pointer to logout area
|
|||
|
*/
|
|||
|
|
|||
|
#define MCHK_COMMON_SIZE 24
|
|||
|
#define MCHK_LOGOUT_SIZE 144
|
|||
|
|
|||
|
MchkLogOut:
|
|||
|
mfpr p1, qemu_ps
|
|||
|
|
|||
|
// ??? Apparently we skip the insn that caused the mchk.
|
|||
|
// ??? This is used by the kernel for mcheck_expected.
|
|||
|
addq p6, 4, p6
|
|||
|
|
|||
|
STACK_FRAME p1, p6, p2, 0
|
|||
|
|
|||
|
// Restore the real EXC_ADDR for the logout frame.
|
|||
|
subq p6, 4, p6
|
|||
|
|
|||
|
// Locate logout frame
|
|||
|
br $gp, .+4
|
|||
|
ldah $gp, 0($gp) !gpdisp!2
|
|||
|
lda $gp, 0($gp) !gpdisp!2
|
|||
|
ldah p1, mchk_logout($gp) !gprelhigh
|
|||
|
lda p1, mchk_logout(p1) !gprellow
|
|||
|
|
|||
|
SYS_WHAMI p2
|
|||
|
mull p2, MCHK_LOGOUT_SIZE, p2
|
|||
|
addq p2, p1, a2
|
|||
|
|
|||
|
// Populate the minimal logout frame
|
|||
|
lda p2, MCHK_LOGOUT_SIZE
|
|||
|
stl p2, 0(a2) // size
|
|||
|
stl $31, 4(a2) // flags
|
|||
|
lda p1, MCHK_COMMON_SIZE
|
|||
|
stl p1, 8(a2) // proc_offset
|
|||
|
stl p2, 12(a2) // sys_offset
|
|||
|
stl p0, 16(a2) // mchk_code
|
|||
|
stl $31, 20(a2) // frame_rev
|
|||
|
|
|||
|
// EV6 portion, format copied from Linux kernel
|
|||
|
// although there's not much we can fill in.
|
|||
|
stq $31, 24(a2) // I_STAT
|
|||
|
stq $31, 32(a2) // DC_STAT
|
|||
|
stq $31, 40(a2) // C_ADDR
|
|||
|
stq $31, 48(a2) // DC1_SYNDROME
|
|||
|
stq $31, 56(a2) // DC0_SYNDROME
|
|||
|
stq $31, 64(a2) // C_STAT
|
|||
|
stq $31, 72(a2) // C_STS
|
|||
|
stq $31, 80(a2) // MM_STAT
|
|||
|
stq p6, 88(a2) // EXC_ADDR
|
|||
|
stq $31, 96(a2) // IER_CM
|
|||
|
stq $31, 104(a2) // ISUM
|
|||
|
stq $31, 112(a2) // RESERVED0
|
|||
|
mfpr p2, qemu_palbr
|
|||
|
stq p2, 120(a2) // PAL_BASE
|
|||
|
stq $31, 128(a2) // I_CTL
|
|||
|
stq $31, 136(a2) // PCTX
|
|||
|
|
|||
|
mov IPL_K_MCHK, p1 // Raise IPL
|
|||
|
mtpr p1, qemu_ps
|
|||
|
|
|||
|
mfpr p6, ptEntInt
|
|||
|
mfpr $gp, ptKgp
|
|||
|
lda a0, INT_K_MCHK
|
|||
|
lda a1, 0 // "vector"
|
|||
|
|
|||
|
hw_ret (p6)
|
|||
|
ENDFN MchkLogOut
|
|||
|
|
|||
|
MchkDouble:
|
|||
|
bsr p7, UpdatePCB
|
|||
|
lda v0, HLT_K_DBL_MCHK
|
|||
|
br Sys_EnterConsole
|
|||
|
ENDFN MchkDouble
|
|||
|
|
|||
|
MchkBugCheck:
|
|||
|
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 initial bootup stack.
|
|||
|
*/
|
|||
|
|
|||
|
.section .bss.stack
|
|||
|
.align 3
|
|||
|
.globl stack
|
|||
|
.type stack,@object
|
|||
|
.size stack,STACK_SIZE * 4
|
|||
|
stack: .skip STACK_SIZE * 4
|
|||
|
|
|||
|
.globl mchk_logout
|
|||
|
.type mchk_logout,@object
|
|||
|
.size mchk_logout,MCHK_LOGOUT_SIZE * 4
|
|||
|
mchk_logout:
|
|||
|
.skip MCHK_LOGOUT_SIZE * 4
|