X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fqemu-palcode%2Fpal.S;fp=qemu%2Froms%2Fqemu-palcode%2Fpal.S;h=1befc9f4a2979699fc77e611bbb3efe146ef72fa;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/qemu-palcode/pal.S b/qemu/roms/qemu-palcode/pal.S new file mode 100644 index 000000000..1befc9f4a --- /dev/null +++ b/qemu/roms/qemu-palcode/pal.S @@ -0,0 +1,1918 @@ +/* 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 + . */ + + .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 + 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) + +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: + halt +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 + 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 0x0380 +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 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 + + 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: + // 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 <- a0<3>, MCES <- 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 <- 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 + 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 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 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 + 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 = 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: +MchkOSBugCheck: + halt +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 Set + * + * Registers v0, t0, and t3 .. t5 are available for use, in + * addition to the shadow registers. + */ + +MchkCommon: + halt +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: + halt +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 initial bootup stack. + */ + + .section .bss.stack + .align 3 + .globl stack + .type stack,@object + .size stack,STACK_SIZE +stack: .skip STACK_SIZE