// "@(#) NEC cacherr.s 1.2 94/10/17 11:02:44" // TITLE("Cache Error Handling") //++ // // Copyright (c) 1993-1994 Microsoft Corporation // // Module Name: // // cacherr.s // // Abstract: // // This module implements cache error handling. It is entered in KSEG1 // directly from the cache error vector wiht ERL set in the processor // state. // // N.B. All the code in this routine MUST run in KSEG1 and reference // data only in KSEG1 until which time as any cache errors have // been corrected. // // N.B. This routine is NOT COMPLETE. All cache errors result in a // soft reset. // // Environment: // // Kernel mode only. // // Revision History: // //-- #include "halmips.h" #include "cacherr.h" // // Define local save area for register state. // .data SavedAt:.space 4 // saved integer register at - a3 SavedV0:.space 4 // SavedV1:.space 4 // SavedA0:.space 4 // SavedA1:.space 4 // SavedA2:.space 4 // SavedA3:.space 4 // SBTTL("Cache Error Handling") //++ // // VOID // HalpCacheErrorRoutine ( // VOID // ) // // Routine Description: // // This function is entered from the cache error vector executing // in KSEG1. If the error is a single bit ECC error in the second // level data cache or the error is in the primary instruction cache, // then the error is corrected and execution is continued. Otherwise, // a fatal system error has occured and control is transfered to the // soft reset vector. // // N.B. No state has been saved when this routine is entered. // // Arguments: // // None. // // Return Value: // // None. // //-- LEAF_ENTRY(HalpCacheErrorRoutine) // // Save volatile registers needed to fix cache error. // .set noreorder .set noat //K001 // la k0,SavedAt // get address of register save area // li k1,KSEG1_BASE // convert address of KSEG1 address // or k0,k0,k1 // // sw AT,0(k0) // save registers AT - a3 // sw v0,4(k0) // // sw v1,8(k0) // // sw a0,12(k0) // // sw a1,16(k0) // // sw a2,20(k0) // li k1,0xb9800310 // Get CPU# lw k0,0x0(k1) li k1,0x0f000000 and k0,k0,k1 srl k0,k0,24 li k1,0x4 sub k0,k0,k1 mtc0 k0,lladdr nop nop nop nop li k1,0xd sll k0,k0,k1 la k1,HalpCacheErrorStack add k0,k0,k1 add k0,k0,0x2000 li k1,KSEG1_BASE or k0,k0,k1 subu k0,k0,TrapFrameLength #if !defined(NT_40) sw sp,TrIntSp(k0) // save integer register sp move sp,k0 // set new stack pointer cfc1 k1,fsr // get floating status register sw gp,TrIntGp(sp) // save integer register gp sw s8,TrIntS8(sp) // save integer register s8 sw k1,TrFsr(sp) // save current FSR mfc0 k0,psr nop nop nop sw k0,TrPsr(sp) // save processor state sw ra,TrIntRa(sp) // save integer register ra move s8,sp sw AT,TrIntAt(s8) // save assembler temporary register sw v0,TrIntV0(s8) // save integer register v0 sw v1,TrIntV1(s8) // save integer register v1 sw a0,TrIntA0(s8) // save integer registers a0 - a3 sw a1,TrIntA1(s8) // sw a2,TrIntA2(s8) // sw a3,TrIntA3(s8) // sw t0,TrIntT0(s8) // save integer registers t0 - t2 sw t1,TrIntT1(s8) // sw t2,TrIntT2(s8) // sw t3,TrIntT3(s8) // save integer register t3 - t9 sw t4,TrIntT4(s8) // sw t5,TrIntT5(s8) // sw t6,TrIntT6(s8) // sw t7,TrIntT7(s8) // sw t8,TrIntT8(s8) // sw t9,TrIntT9(s8) // mflo t3 // get multiplier/quotient lo and hi mfhi t4 // sw t3,TrIntLo(s8) // save multiplier/quotient lo and hi sw t4,TrIntHi(s8) // mfc0 a2,errorepc nop nop nop sw a2,TrFir(s8) // save exception PC #else sd sp,TrXIntSp(k0) // save integer register sp move sp,k0 // set new stack pointer cfc1 k1,fsr // get floating status register sd gp,TrXIntGp(sp) // save integer register gp sd s8,TrXIntS8(sp) // save integer register s8 sw k1,TrFsr(sp) // save current FSR mfc0 k0,psr nop nop nop sw k0,TrPsr(sp) // save processor state sd ra,TrXIntRa(sp) // save integer register ra move s8,sp sd AT,TrXIntAt(s8) // save assembler temporary register sd v0,TrXIntV0(s8) // save integer register v0 sd v1,TrXIntV1(s8) // save integer register v1 sd a0,TrXIntA0(s8) // save integer registers a0 - a3 sd a1,TrXIntA1(s8) // sd a2,TrXIntA2(s8) // sd a3,TrXIntA3(s8) // sd t0,TrXIntT0(s8) // save integer registers t0 - t2 sd t1,TrXIntT1(s8) // sd t2,TrXIntT2(s8) // sd t3,TrXIntT3(s8) // save integer register t3 - t7 sd t4,TrXIntT4(s8) // sd t5,TrXIntT5(s8) // sd t6,TrXIntT6(s8) // sd t7,TrXIntT7(s8) // sd s0,TrXIntS0(s8) // save integer registers s0 - s7 sd s1,TrXIntS1(s8) // sd s2,TrXIntS2(s8) // sd s3,TrXIntS3(s8) // sd s4,TrXIntS4(s8) // sd s5,TrXIntS5(s8) // sd s6,TrXIntS6(s8) // sd s7,TrXIntS7(s8) // sd t8,TrXIntT8(s8) // save integer registers t8 - t9 sd t9,TrXIntT9(s8) // mflo t3 // get multiplier/quotient lo and hi mfhi t4 // sd t3,TrXIntLo(s8) // save multiplier/quotient lo and hi sd t4,TrXIntHi(s8) // mfc0 a2,errorepc nop nop nop sw a2,TrFir(s8) // save exception PC #endif move a3,k0 // // Get the current processor state and cache error register, and check // if the error can be corrected. // mfc0 a0,lladdr nop nop nop li t1,0x1 // Log Format For FW sll t3,t1,a0 li t1,0xb9800388 // NVRAM enable li t0,0x00040000 sw t0,0x0(t1) li t0,0xbf09fd64 // NVRAM log For FW lw t1,0x0(t0) or t3,t1,t3 sb t3,0x0(t0) #if 0 li t1,0xb9800388 // NVRAM disable li t0,0x04040000 sw t0,0x0(t1) #endif mfc0 a1,cacheerr // get cache error state nop nop nop la t1,HalpCacheErrorHwLog li t2,KSEG1_BASE or t1,t1,t2 // // Check CPU // // li a1,0x00000000 mfc0 t2,prid nop nop nop nop and t2,t2,0xff00 // isolate processor id xor t2,t2,0x0900 // check if r10000 processor beq zero,t2,t5clog // if eq, r10000 processor // // R4400 log // addi t2,t1,0x20 .set at .set reorder // // ****** temp ****** // // The following code is temporary and will be removed when full cache // error support is included. // // ****** temp ****** // // K001 For cacheErrorLog // jal HalpCacheErrorLog // nop // // b SoftReset // ****** all error soft rest /******************************** * cache error routine * * v0 = return code (return value) * * a0 = log field address (argument) * a1 = error code address (argument) * a2 = TagLo reg * a3 = ECC reg * t0 = cache virtual address * t1 = Cache error reg * t2 = d-cache virtual address for s-cache * t3 = xkphs address * t4 - t7 temprary data * t8 = a2(TagLo) save * t9 = return address ********************************/ //LEAF(che_log) .set noreorder // DMFC0 (T8, D_ERROREPC) move v1,a0 // CPU # move a0,t2 // Data addr move t2,a1 move a1,t1 // Header addr move t1,t2 // CacheError REg move t8,a2 // Error Epc // mfc0 t7, C0_SR move t7,a3 // PSR mfc0 t6, config mfc0 t5, prid // Log sw t8,EPC_cpu(a0) sw t7,Psr_cpu(a0) sw t6,CFG_cpu(a0) sw t5,PRID_cpu(a0) sw t1,CHERR_cpu(a0) // mfc0 t1, C0_CACHEERR // or t4, t7, (SR_DE | SR_KX | SR_ERL) or t4,t7,(0x1<