diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/fwtrap.s | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/fw/mips/fwtrap.s')
-rw-r--r-- | private/ntos/fw/mips/fwtrap.s | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/fwtrap.s b/private/ntos/fw/mips/fwtrap.s new file mode 100644 index 000000000..cb73aaf0f --- /dev/null +++ b/private/ntos/fw/mips/fwtrap.s @@ -0,0 +1,655 @@ +#if defined(JAZZ) && defined(R4000) +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + fw4trap.s + +Abstract: + + This module contains the fw exception handling functions. + +Author: + + Lluis Abello (lluis) 4-Sep-91 + +--*/ + +// +// include header file +// +#include <ksmips.h> +#include <selfmap.h> + + +.data +// +// Declare the table where to store the processor registers. +// also align it so that we can store doubles. +// +.align 4 +ALTERNATE_ENTRY(RegisterTable) + .space RegisterTableSize +ALTERNATE_ENTRY(EndRegisterTable) +.text +.set noat +.set noreorder + + + SBTTL("User TLB dispatcher") +/*++ + +Routine Description: + + This routine gets control on a User TLB Miss exception. + It reads the TLB Miss handler address from the System + Parameter Block and jumps to it. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + LEAF_ENTRY(FwTbMissStartAddress) + li k0,KSEG0_BASE + lw k0,0x1018(k0)// Load address of UTLB handler + nop + jal k1,k0 // jump to handler saving return + nop // address in k1 + mtc0 k0,epc // Handler returns return address in K0 + nop // 2 cycle hazard + nop // + eret // restore from exception + nop + ALTERNATE_ENTRY(FwTbMissEndAddress) + .end FwTbMissStartAddress + + + SBTTL("General Exception dispatcher") +/*++ + +Routine Description: + + This routine gets control on a General exception. + It reads the General exception handler address from the System + Parameter Block and jumps to it. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + LEAF_ENTRY(FwGeneralExceptionStartAddress) + + li k0,KSEG0_BASE + lw k0,0x1014(k0)// Load address of GE handler + nop + jal k1,k0 // jump to handler saving return + nop // address in k1 + mtc0 k0,epc // Handler returns return address in K0 + nop // 2 cycle hazard + nop // + eret // restore from exception + nop + ALTERNATE_ENTRY(FwGeneralExceptionEndAddress) + + .end FwGeneralExceptionStartAddress + + + SBTTL("CacheError Exception dispatcher") +/*++ + +Routine Description: + + This routine gets control on a cache error exception. + It jumps to the Monitor exception handler. + It gets copied to address 0xA0000100 + +Arguments: + + None. + +Return Value: + + None. + +--*/ + + LEAF_ENTRY(FwCacheErrorExceptionStartAddress) + + la k0,CacheExceptionMonitorEntry // load address of Monitor entry + li k1,KSEG1_BASE // convert address to non cached + or k0,k0,k1 // + j k0 + nop + + ALTERNATE_ENTRY(FwCacheErrorExceptionEndAddress) + .end FwCacheErrorExceptionStartAddress + + SBTTL("Firmware Exception intialize") +/*++ + +Routine Description: + + This routine copies the User TLB dispatcher and + the General Exception dispatcher to the R4000 vector + addresses. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +// +// Copy the TB miss and general exception dispatchers to low memory. +// + NESTED_ENTRY(FwExceptionInitialize,4, zero) + subu sp,sp,4 // decrement stack pointer + sw ra,0(sp) // save ra + la t2,FwTbMissStartAddress // get user TB miss start address + la t3,FwTbMissEndAddress // get user TB miss end address + li t4,KSEG1_BASE // get copy address +10: lw t5,0(t2) // copy code to low memory + addu t2,t2,4 // advance copy pointers + sw t5,0(t4) // + bne t2,t3,10b // if ne, more to copy + addu t4,t4,4 // + + la t2,FwGeneralExceptionStartAddress // get general exception start address + la t3,FwGeneralExceptionEndAddress // get general exception end address + li t4,KSEG1_BASE + 0x180 // get copy address +20: lw t5,0(t2) // copy code to low memory + addu t2,t2,4 // advance copy pointers + sw t5,0(t4) // + bne t2,t3,20b // if ne, more to copy + addu t4,t4,4 // + + la t2,FwCacheErrorExceptionStartAddress // get cache error exception start address + la t3,FwCacheErrorExceptionEndAddress // get cache error exception end address + li t4,KSEG1_BASE + 0x100 // get copy address +30: lw t5,0(t2) // copy code to low memory + addu t2,t2,4 // advance copy pointers + sw t5,0(t4) // + bne t2,t3,30b // if ne, more to copy + addu t4,t4,4 // + + // + // Set the Monitor exception handler address in the vector. + // + li t0,KSEG0_BASE + la t1,FwExceptionHandler + sw t1,0x1014(t0) // Init GE vector + sw t1,0x1018(t0) // Init UTLB vector + + jal HalSweepIcache // sweep the instruction cache + nop + jal HalSweepDcache // sweep the data cache + nop + + // + // Clear the BEV in the psr and enable IO device interrupts + // + li t0,(1<<PSR_CU1) | (1 << PSR_IE) | (1<< (PSR_INTMASK+3)) + mtc0 t0,psr // set new psr. + nop // + nop // + nop // + lw ra,0(sp) // load return address + addiu sp,sp,4 // restore stack pointer + j ra // return to caller + nop + .end FwExceptionInitialize + + + SBTTL("Monitor Exception Handler") +/*++ + +Routine Description: + + This routine implements the exception handler for + the monitor. + +Arguments: + + k1 specifies the caller source in the following way: + + - If k1 contains a word aligned address. The exception is + either a UTLB or a GE. The cause register supplies the cause + of the exception. + + - Otherwise k1 contains a value that identifies the caller. + + None. + +Return Value: + + None. + +--*/ + + LEAF_ENTRY(FwExceptionHandler) + mfc0 k0,cause // read cause register + nop + andi k0,k0,R4000_XCODE_MASK // isolate cause of exception + bne k0,zero,10f // if not interrupt go to Monitor + nop + subu sp,sp,FwFrameSize // decrement state pointer + sw k1,FwFrameK1(sp) // save volatile state + sw ra,FwFrameRa(sp) // save volatile state + sw a0,FwFrameA0(sp) // save volatile state + sw a1,FwFrameA1(sp) // save volatile state + sw a2,FwFrameA2(sp) // save volatile state + sw a3,FwFrameA3(sp) // save volatile state + sw v0,FwFrameV0(sp) // save volatile state + sw v1,FwFrameV1(sp) // save volatile state + sw t0,FwFrameT0(sp) // save volatile state + sw t1,FwFrameT1(sp) // save volatile state + sw t2,FwFrameT2(sp) // save volatile state + sw t3,FwFrameT3(sp) // save volatile state + sw t4,FwFrameT4(sp) // save volatile state + sw t5,FwFrameT5(sp) // save volatile state + sw t6,FwFrameT6(sp) // save volatile state + sw t7,FwFrameT7(sp) // save volatile state + sw t8,FwFrameT8(sp) // save volatile state + sw t9,FwFrameT9(sp) // save volatile state + mfc0 a0,cause // read cause register + mfc0 a1,psr // read psr. + sw AT,FwFrameAT(sp) // save volatile state + jal FwInterruptHandler // call c routine + and a0,a0,a1 // mask IM to clear disabled interrupts. + + move k0,v0 // save return value in k0 + lw k1,FwFrameK1(sp) // restore volatile state + lw ra,FwFrameRa(sp) // restore volatile state + lw a0,FwFrameA0(sp) // restore volatile state + lw a1,FwFrameA1(sp) // restore volatile state + lw a2,FwFrameA2(sp) // restore volatile state + lw a3,FwFrameA3(sp) // restore volatile state + lw v0,FwFrameV0(sp) // restore volatile state + lw v1,FwFrameV1(sp) // restore volatile state + lw t0,FwFrameT0(sp) // restore volatile state + lw t1,FwFrameT1(sp) // restore volatile state + lw t2,FwFrameT2(sp) // restore volatile state + lw t3,FwFrameT3(sp) // restore volatile state + lw t4,FwFrameT4(sp) // restore volatile state + lw t5,FwFrameT5(sp) // restore volatile state + lw t6,FwFrameT6(sp) // restore volatile state + lw t7,FwFrameT7(sp) // restore volatile state + lw t8,FwFrameT8(sp) // restore volatile state + lw t9,FwFrameT9(sp) // restore volatile state + lw AT,FwFrameAT(sp) // save volatile state + beq k0,zero,10f // if routine returned false do not return + addiu sp,sp,FwFrameSize // restore stack pointer + mfc0 k0,epc // get return address + nop + j k1 // return to caller + nop // +// +// Control reaches here if an exception other than an interrupt occurred +// or if the interrupt handler returned false meaning that it didn't +// know how to handle the interrupt exception. +// +// At this time no state has been destroyed and register k1 still contains +// the address where to return. +// +10: + addiu k0,k0,-XCODE_BREAKPOINT // substract breakpoint code + beq k0,zero,10f // if eq Bp exception, call KD unconditionally + la k0,KdInstalled // load address of boolean + lbu k0,0(k0) // read boolean + beq k0,zero,MonitorExceptionHandler // if false go to the monitor + nop // otherwise +10: j KiGeneralException // go to the debugger. + nop + // + // This is the entry point when the monitor is called. + // Set k1 to 3 to tell the Monitor than can execute a j ra + // to quit. + // + ALTERNATE_ENTRY(FwMonitor) + b MonitorExceptionHandler + li k1,3 // set k1 to 3 to indicate we don't get + nop // here because of an exception + // The monitor returns to ra which points + // to where we got called from. + + ALTERNATE_ENTRY(CacheExceptionMonitorEntry) + la k0,RegisterTable // get address of table. + or k0,k0,k1 // set it non cached. + b MonitorEntry // go to monitor + ori k1,zero,CACHE_EXCEPTION // set flag to tell that parity error occurred + + ALTERNATE_ENTRY(MonitorExceptionHandler) + // + // Save the registers. + // + la k0,RegisterTable // get address of table. + + ALTERNATE_ENTRY(MonitorEntry) + + sw zero,zeroRegTable(k0) + sw AT,atRegTable(k0) + sw v0,v0RegTable(k0) + sw v1,v1RegTable(k0) + sw a0,a0RegTable(k0) + sw a1,a1RegTable(k0) + sw a2,a2RegTable(k0) + sw a3,a3RegTable(k0) + sw t0,t0RegTable(k0) + sw t1,t1RegTable(k0) + sw t2,t2RegTable(k0) + sw t3,t3RegTable(k0) + sw t4,t4RegTable(k0) + sw t5,t5RegTable(k0) + sw t6,t6RegTable(k0) + sw t7,t7RegTable(k0) + sw s0,s0RegTable(k0) + sw s1,s1RegTable(k0) + sw s2,s2RegTable(k0) + sw s3,s3RegTable(k0) + sw s4,s4RegTable(k0) + sw s5,s5RegTable(k0) + sw s6,s6RegTable(k0) + sw s7,s7RegTable(k0) + sw t8,t8RegTable(k0) + sw t9,t9RegTable(k0) + sw k0,k0RegTable(k0) + sw k1,k1RegTable(k0) + sw gp,gpRegTable(k0) + sw sp,spRegTable(k0) + sw s8,s8RegTable(k0) + sw ra,raRegTable(k0) + + // + // Store coprocessor1 registers. + // + cfc1 v0,fsr + sdc1 f0,f0RegTable(k0) + sdc1 f2,f2RegTable(k0) + sdc1 f4,f4RegTable(k0) + sdc1 f6,f6RegTable(k0) + sdc1 f8,f8RegTable(k0) + sdc1 f10,f10RegTable(k0) + sdc1 f12,f12RegTable(k0) + sdc1 f14,f14RegTable(k0) + sdc1 f16,f16RegTable(k0) + sdc1 f18,f18RegTable(k0) + sdc1 f20,f20RegTable(k0) + sdc1 f22,f22RegTable(k0) + sdc1 f24,f24RegTable(k0) + sdc1 f26,f26RegTable(k0) + sdc1 f28,f28RegTable(k0) + sdc1 f30,f30RegTable(k0) + sw v0,fsrRegTable(k0) + // + // Store cop0 registers. + // + mfc0 v1,index + mfc0 v0,random + sw v1,indexRegTable(k0) + sw v0,randomRegTable(k0) + mfc0 v1,entrylo0 + nop + mfc0 v0,entrylo1 + sw v1,entrylo0RegTable(k0) + sw v0,entrylo1RegTable(k0) + mfc0 v1,context + mfc0 v0,pagemask + sw v1,contextRegTable(k0) + sw v0,pagemaskRegTable(k0) + mfc0 v1,wired + mfc0 v0,badvaddr + sw v1,wiredRegTable(k0) + sw v0,badvaddrRegTable(k0) + mfc0 v1,count + mfc0 v0,entryhi + sw v1,countRegTable(k0) + sw v0,entryhiRegTable(k0) + mfc0 v1,compare + mfc0 v0,psr + sw v1,compareRegTable(k0) + sw v0,psrRegTable(k0) + mfc0 v1,cause + mfc0 v0,epc + sw v1,causeRegTable(k0) + sw v0,epcRegTable(k0) + mfc0 v1,prid + mfc0 v0,config + sw v1,pridRegTable(k0) + sw v0,configRegTable(k0) + mfc0 v1,lladdr + mfc0 v0,watchlo + sw v1,lladdrRegTable(k0) + sw v0,watchloRegTable(k0) + mfc0 v1,watchhi + mfc0 v0,ecc + sw v1,watchhiRegTable(k0) + sw v0,eccRegTable(k0) + mfc0 v1,cacheerr + mfc0 v0,taglo + sw v1,cacheerrorRegTable(k0) + sw v0,tagloRegTable(k0) + mfc0 v1,taghi + mfc0 v0,errorepc + sw v1,taghiRegTable(k0) + sw v0,errorepcRegTable(k0) + li k0,CACHE_EXCEPTION + bne k0,k1,10f // check if parity exception + la k0,Monitor // Set address where to return + li t0,KSEG1_BASE // convert it to non cached + or k0,k0,t0 // + mtc0 k0,errorepc // set in errorepc + li sp, RAM_TEST_STACK_ADDRESS | KSEG1_BASE + andi a0,k1,0x3 // pass caller source in a0 just 2 bits. + eret // jump to the monitor and leave exception level +10: + la k0,Monitor // Set address where to + mtc0 k0,epc // return from the exception. + li k0,0x3 + beq k0,k1,10f // if k1=3 do not change sp + andi a0,k1,0x3 // pass caller source in a0 just 2 bits. + li sp,RAM_TEST_STACK_ADDRESS // set the stack pointer. + eret // jump to the monitor and leave exception level +10: j Monitor + + .end MonitorExceptionHandler +/*++ +ARC_STATUS +FwInvoke( + IN ULONG ExecAddr, + IN ULONG StackAddr, + IN ULONG Argc, + IN PCHAR Argv[], + IN PCHAR Envp[] + ) + + +Routine Description: + + This routine invokes a loaded program. + +Arguments: + + ExecAddr - Supplies the address of the routine to call. + + StackAddr - Supplies the address to which the stack pointer is set. + + Argc, Argv, Envp - Supply the arguments and endvironment to pass to + Loaded program. + + The stack pointer is saved in register s0 so that when the loaded + program returns, the old stack pointer can be restored. + + In addition, the value stored in InvokeSavedSp is read and if zero, + this is the first loaded program, thus the current stack pointer + is the firmware stack pointer and it is saved in order to + be able to restore the Firmware stack pointer when a loaded program + calls ReturnFromMain. + +Return Value: + + ESUCCESS is returned if the address is valid. + EFAULT indicates an invalid addres. + +--*/ + +{ + NESTED_ENTRY(FwInvoke,0x20,zero) + + subu sp,sp,0x20 // allocate room in the stack. + sw ra,0x1C(sp) // save ra + sw s0,0x18(sp) // save s0 + move v1,a0 // save address of routine to call + andi v0,v1,0x3 // check for alignment. + bne v0,zero,20f // if not aligned return error. + li v0,6 // set EFAULT = 6 a return value. + move a0,a2 // move argc to first argument + move s0,sp // save stack pointer in s0 + lw a2,0x30(sp) // load Envp argument into second. + move sp,a1 // set new stack pointer. + subu sp,sp,0x10 // make room for arguments. + jal v1 // call program + move a1,a3 // move argv to right argument +// +// If loaded program returns, s0 has the previous stack pointer. +// + move sp,s0 // set old stack pointer. + move v0,zero // set ESUCCESS as return value. + lw ra,0x1C(sp) // restore ra + lw s0,0x18(sp) // restore s0 +20: + j ra // return to caller + addiu sp,sp,0x20 // restore sp. + .end FwInvoke + + + SBTTL("FwExecute") +/*++ + +Routine Description: + + This routine is the entry point for the Execute service. + + It behaves in two different ways depending on where it is + called from: + + 1) If it's called from the Firmware it saves the stack pointer + in a fixed location and then saves all the saved registers + in the stack. This is the stack that will be used to restore + the saved state when returning to the firmware. + + 2) If called from a loaded program the program to be loaded + and executed can overwrite the current program and it's + stack, therefore a temporary stack is set. + +Arguments: + + a0 IN PCHAR Path, + a1 IN ULONG Argc, + a2 IN PCHAR Argv[], + a3 IN PCHAR Envp[] + +Return Value: + + ARC_STATUS returned by FwPrivateExecute. + Always returns to the Firmware. + +--*/ + LEAF_ENTRY(FwExecute) + la t0, FwSavedSp // load address where to save Fw SP + lw t1, 0(t0) // read saved stack + beq t1, zero,CallFromFw // if zero first call from Fw. + nop +// +// A loaded program wants to be replaced by another program +// therefore the current stack and state will be trashed and a +// new temporary stack needs to be set. +// + la t0, FwTemporaryStack // load address of Fw temporary stack + lw sp, 0(t0) // load Tmp Stack value. + jal FwPrivateExecute // go to do the job + nop +// +// if the program returns it's caller is gone, therefore +// we restore the initiali fw stack and returned to the +// firmware instead. +// + la t0, FwSavedSp // get address of saved stack + lw sp, 0(t0) // restore saved stack. + b RestoreFwState // go to restore state + nop + +CallFromFw: + subu sp,sp,0x30 // make room in the stack + sw sp, 0(t0) // save new stack + sw ra, 0x4(sp) // save also return address + sw s0, 0x8(sp) // save state that must be preserved. + sw s1, 0xC(sp) + sw s2, 0x10(sp) + sw s3, 0x14(sp) + sw s4, 0x18(sp) + sw s5, 0x1C(sp) + sw s6, 0x20(sp) + sw s7, 0x24(sp) + sw s8, 0x28(sp) + jal FwPrivateExecute // go to do the job + sw gp, 0x2C(sp) // save global pointer + +RestoreFwState: + lw ra, 0x4(sp) // restore ra + lw s0, 0x8(sp) // restore Fw state + lw s1, 0xC(sp) + lw s2, 0x10(sp) + lw s3, 0x14(sp) + lw s4, 0x18(sp) + lw s5, 0x1C(sp) + lw s6, 0x20(sp) + lw s7, 0x24(sp) + lw s8, 0x28(sp) + lw gp, 0x2C(sp) + j ra // return to Firmware. + addu sp,sp,0x30 // restore sp. + + .end FwExecute + + + SBTTL("Termination Functions") +/*++ + +Routine Description: + + This routine implements the Firmware ReturnFromMain + termination function. + +Arguments: + + None. + +Return Value: + + returns to where the program was called from. + +--*/ + ALTERNATE_ENTRY(FwReturnFromMain) + la t0,FwSavedSp // get address where SP was saved + lw sp,0(t0) // set old stack pointer. + b RestoreFwState + move v0,zero // set ESUCCESS as return value. + + .end FwReturnFromMain + +#endif // defined(JAZZ) && defined(R4000) |