diff options
Diffstat (limited to 'private/ntos/nthals/halsnip/mips/cacherr.s')
-rw-r--r-- | private/ntos/nthals/halsnip/mips/cacherr.s | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/private/ntos/nthals/halsnip/mips/cacherr.s b/private/ntos/nthals/halsnip/mips/cacherr.s new file mode 100644 index 000000000..c0ea29908 --- /dev/null +++ b/private/ntos/nthals/halsnip/mips/cacherr.s @@ -0,0 +1,645 @@ +//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/cacherr.s,v 1.2 1996/02/23 17:55:12 pierre Exp $") +// TITLE("Cache Error Handling") +//++ +// +// Copyright (c) 1993 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. +// +// No correction is done. We only try to get the physical address +// that causes this exception +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + .globl HalpCacheErrFirst + .globl HalpErrCacheMsg // cache error + .globl HalpParityErrMsg // parity error + .globl HalpAddrErrMsg // no addr found + .globl HalpComputeNum // compute memory sip number + .globl HalpKeBugCheck0 + .globl HalpKeBugCheck1 + .globl HalpKeBugCheck2 + .globl HalpKeBugCheck3 + .globl HalpKeBugCheck4 + .globl HalpBugCheckNumber + +#define CACHE_ERR_ER 0x80000000 +#define CACHE_ERR_EC 0x40000000 +#define CACHE_ERR_ED 0x20000000 +#define CACHE_ERR_ET 0x10000000 +#define CACHE_ERR_ES 0x08000000 +#define CACHE_ERR_EE 0x04000000 +#define CACHE_ERR_EB 0x02000000 +#define CACHE_ERR_EI 0x01000000 +#define CACHE_ERR_SIDX 0x003ffff8 +#define CACHE_ERR_PIDX 0x00000007 +#define PIDX_PD_MASK 0x00001000 // cache size 8k + +#define HALP_OPCODE_MASK 0xfc000000 +#define HALP_OPCODE_SHIFT 24 // because we test opcode number on 8 bits +#define HALP_RT1_REG 0x001f0000 +#define HALP_RT1_SHIFT 16 +#define HALP_RT2_REG 0x03e00000 +#define HALP_RT2_SHIFT 21 + +#define HALP_SWC1 0xe4 // +#define HALP_SDC1 0xf4 // +#define HALP_LWC1 0xc4 // +#define HALP_LDC1 0xd4 // +#define HALP_LB 0x80 // +#define HALP_LH 0x82 // +#define HALP_LW 0x8c // +#define HALP_LD 0xdc // +#define HALP_LBU 0x90 // +#define HALP_LHU 0x94 // +#define HALP_SB 0xa0 // +#define HALP_SH 0xa4 // +#define HALP_SW 0xac // +#define HALP_SD 0xfc // +#define HALP_LWL 0x88 // +#define HALP_LWR 0x98 // +#define HALP_LDL 0x68 // +#define HALP_LDR 0x6c // +#define HALP_LWU 0x9c // +#define HALP_SDL 0xb0 // +#define HALP_SDR 0xb4 // +#define HALP_LL 0xc0 // +#define HALP_LLD 0xd0 // +#define HALP_SC 0xe0 // +#define HALP_SCD 0xf0 // +// +// Define local save area for register state. +// + + .data +SavedAt:.space 4 // saved registers +SavedV0:.space 4 // +SavedV1:.space 4 // +SavedA0:.space 4 // +SavedA1:.space 4 // +SavedA2:.space 4 // +SavedA3:.space 4 // +SavedT0:.space 4 // +SavedT1:.space 4 // +SavedT2:.space 4 // +SavedT3:.space 4 // +SavedT4:.space 4 // +SavedT5:.space 4 // +SavedT6:.space 4 // +SavedT7:.space 4 // +SavedS0:.space 4 // +SavedS1:.space 4 // +SavedS2:.space 4 // +SavedS3:.space 4 // +SavedS4:.space 4 // +SavedS5:.space 4 // +SavedS6:.space 4 // +SavedS7:.space 4 // +SavedT8:.space 4 // +SavedT9:.space 4 // +SavedK0:.space 4 // +SavedK1:.space 4 // +SavedGP:.space 4 // +SavedSP:.space 4 // +SavedS8:.space 4 // +SavedRA:.space 4 // +SavedErrorEpc:.space 4 // +SavedCacheError:.space 4 // + +//++ +// +// VOID +// HalpCacheErrorRoutine ( +// VOID +// ) +// +// Routine Description: +// +// This function is entered from the cache error vector executing +// in KSEG1 and with finished with a fatal system error : +// +// Msg Hal : CACHE ERROR - PARITY ERROR - ADDR IN ERROR NOT FOUND +// KeBugCheckEx : +// a0 = 0x80 Hardware malfunction +// a1 = 18 (parity pb) or 19 (cache error) +// a2 = physical address in error (or 0x00) +// a3 = sim number +// a4 = cacheerror register contents +// +// +// N.B. No state has been saved when this routine is entered. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + .struct 0 + + .struct 0 +CiArgs0:.space 4 // saved arguments +CiArgs1:.space 4 // saved arguments +CiArgs2:.space 4 // saved arguments +CiRa: .space 4 // saved return address +CiFrameLength: // + + NESTED_ENTRY(HalpCacheErrorRoutine, CiFrameLength, zero) + + + subu sp,sp,CiFrameLength // allocate stack frame + sw ra,CiRa(sp) // save return address + + PROLOGUE_END + +// +// Save volatile registers needed to fix cache error. +// + + .set noreorder + +// +// Protection to avoid to execute twice in multipro +// (modif of psr doesn't seem very effective) +// + + la k0,HalpCacheErrFirst + li k1,KSEG1_BASE // convert address of KSEG1 address + or k1,k0,k1 // + lw k0,0(k1) + nop + beq k0,zero,1f + nop + +// cache error during cache error routine + lw ra,CiRa(sp) // save return address + addu sp,sp,CiFrameLength // allocate stack frame + eret // hope we don't need k0 and k1... + nop + +1: add k0,k0,0x01 + sw k0,0(k1) + +// +// Save all the registers +// + + la k0,SavedAt // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + .set noat + sw AT,0(k0) // save registers AT - a3 + .set at + sw v0,4(k0) // + sw v1,8(k0) // + sw a0,12(k0) // + sw a1,16(k0) // + sw a2,20(k0) // + sw a3,24(k0) // + sw t0,28(k0) // + sw t1,32(k0) // + sw t2,36(k0) // + sw t3,40(k0) // + sw t4,44(k0) // + sw t5,48(k0) // + sw t6,52(k0) // + sw t7,56(k0) // + sw s0,60(k0) // + sw s1,64(k0) // + sw s2,68(k0) // + sw s3,72(k0) // + sw s4,76(k0) // + sw s5,80(k0) // + sw s6,84(k0) // + sw s7,88(k0) // + sw t8,92(k0) // + sw t9,96(k0) // + sw s8,100(k0) // + sw k0,104(k0) // + sw k1,108(k0) // + sw gp,112(k0) // + sw sp,116(k0) // + sw s8,120(k0) // + sw ra,124(k0) // + + mfc0 a1,cacheerr // get cache error state + nop + nop + nop + nop + nop + nop + mfc0 a0,errorepc // get error address + nop + nop + nop + nop + nop + nop + la k0,SavedErrorEpc // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + sw a0,0(k0) // save errorepc register + sw a1,4(k0) // save cache error register +// +// Disable ECC and parity detection (HalpCacheFirstErr will help...) +// + + mfc0 k0,psr // get current processor state + nop + nop + nop + nop + nop + or k0,k0,0x00010000 // disable ECC and Parity detection + and k0,k0,0xfffffffe // disable interrupt + mtc0 k0,psr + and k0,k0,0xffff00e0 + mtc0 k0,psr + + +// Analysis of cacheerror register + + la k0,SavedCacheError // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + lw t0,0(k0) // restore cache error register in t0 + + and t1,t0,CACHE_ERR_EE // parity error + bne t1,zero,ParityError + nop + +// +// Cache error message +// + + la a0,HalpErrCacheMsg + and a0,a0,0x1fffffff + or a0,a0,0xa0000000 + la t0,HalDisplayString + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + nop + + la k0,SavedCacheError // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + lw t0,0(k0) // restore cache error register in t0 + + and t1,t0,CACHE_ERR_SIDX // grab low bits of PAddr + lw t2,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + subu t2,t2,1 + not t2 + and t1,t2 // t1=PAddre(21..scache_block_size); SCache index +// lw t2,KiPcr + PcSecondLevelDcacheSize(zero) // get 2nd size +// subu t2,t2,1 +// and t1,t2 // t1=PAddre(21..scache_block_size); SCache index + + and t5,t0,CACHE_ERR_PIDX + sll t5,t5,0xc // align PIDX (bits 15:13) + and t2,t1,~(PIDX_PD_MASK) // suppress PIDX bits for VAddr + or t2,t5 // t2=VAddr(15..scache_block_size);PCache base index + + or t1,0x80000000 // SCache index with K0SEG address + or t2,0x80000000 // PCache base index with K0SEG address + + and t5,t0,CACHE_ERR_EC // Cache level of the error (0=primary, 1=secondary) + bne zero,t5,3f // if EC=0, Primary Cache Parity Error + nop + +1: // primary cache + + // int error + and t5,t0,CACHE_ERR_ER // data or instruction flag + bne zero,t5,2f // if ER=1 Data error + nop + + move a2,t2 + // primary cache - inst + cache INDEX_LOAD_TAG_I,0(t2) + + nop + mfc0 a3,taglo + b 5f + nop + +2: // primary cache - data + move a2,t2 + cache INDEX_LOAD_TAG_D,0(t2) + + nop + mfc0 a3,taglo + b 5f + nop + +3: // secondary cache - inst/data + move a2,t1 + cache INDEX_LOAD_TAG_SD,0(t1) + + nop + mfc0 a3,taglo +5: + +// maybe a3 will be the erroneous physical address... + + li a0,0x80 // harware error + la k0,SavedErrorEpc // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + li a1,19 // restore error epc register + lw a2,4(k0) // restore cache error register + la t1,HalpKeBugCheck0 + sw a0,0(t1) + la t1,HalpKeBugCheck1 + sw a1,0(t1) + la t1,HalpKeBugCheck2 + sw a2,0(t1) + la t1,HalpKeBugCheck3 + sw a3,0(t1) + la t1,HalpKeBugCheck4 + sw zero,0(t1) + la t1,HalpBugCheckNumber + sw a1,0(t1) + la t0,KeBugCheckEx + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + sw zero,0x10(sp) + lw ra,CiRa(sp) // save return address + addu sp,sp,CiFrameLength // allocate stack frame + eret + nop + +ParityError: + +// +// cacheerr contents are not usable if parity error. +// Then we must disassemble the errorepc code, get the used register +// and get the contents of this register which must cause the error. +// + +// +// Parity Error Msg +// + + la a0,HalpParityErrMsg + and a0,a0,0x1fffffff + or a0,a0,0xa0000000 + la t0,HalDisplayString + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + nop + +// +// disasm +// + la k0,SavedErrorEpc // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + lw a0,0(k0) + li a2,0x00 // init for one loop + move t0,a0 + +10: lw a0,0(a0) // instruction + move a1,a0 // instruction saved in a1 + li a3,HALP_OPCODE_MASK + and a0,a0,a3 + srl a0,a0,HALP_OPCODE_SHIFT + li a2,0x00 + beq a0,HALP_SWC1,8f + nop + beq a0,HALP_SDC1,8f + nop + beq a0,HALP_LWC1,8f + nop + beq a0,HALP_LDC1,8f + nop + beq a0,HALP_LB,8f + nop + beq a0,HALP_LH,8f + nop + beq a0,HALP_LW,8f + nop + beq a0,HALP_LD,8f + nop + beq a0,HALP_LBU,8f + nop + beq a0,HALP_LHU,8f + nop + beq a0,HALP_SB,8f + nop + beq a0,HALP_SH,8f + nop + beq a0,HALP_SW,8f + nop + beq a0,HALP_SD,8f + nop + beq a0,HALP_LWL,8f + nop + beq a0,HALP_LWR,8f + nop + beq a0,HALP_LDL,8f + nop + beq a0,HALP_LDR,8f + nop + beq a0,HALP_LWU,8f + nop + beq a0,HALP_SDL,8f + nop + beq a0,HALP_SDR,8f + nop + beq a0,HALP_LWU,8f + nop + beq a0,HALP_SDL,8f + nop + beq a0,HALP_SDR,8f + nop + beq a0,HALP_LL,8f + nop + beq a0,HALP_SC,8f + nop + beq a0,HALP_SCD,8f + nop + move a0,t0 + addu a0,a0,4 + beq a2,zero,10b // try the next instruction (case of branch...) + addu a2,a2,1 + + beq zero,zero,NotFoundAddr + +8: // a1 = inst en erreur + + move a2,a1 + + li a3,HALP_RT2_REG + and a2,a2,a3 + srl a3,a2,HALP_RT2_SHIFT + + subu a3,1 // reg at has 1 as number + sll a3,a3,0x2 // *4 + + la k0,SavedAt // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + addu k0,k0,a3 + lw a3,0(k0) // contents of the register +// +// Try To find the physical address +// a3 = virtual address +// + + move a0,a3 + srl a0,a0,30 // two upper bits + li a2,0x2 // binary 10 + beq a0,a2,FoundAddr // KSEG0 or KSEG1 addr + nop +// mapped address => try to find it in the TLB + move a0,a3 + mfc0 t1,entryhi // get current PID and VPN2 + srl t2,a0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t2,t2,ENTRYHI_VPN2 // + and t1,t1,PID_MASK << ENTRYHI_PID // isolate current PID + or t2,t2,t1 // merge PID with VPN2 of virtual address + mtc0 t2,entryhi // set VPN2 and PID for probe + nop // 3 cycle hazzard + nop // + nop // + tlbp // probe for entry in TB + nop // 2 cycle hazzard + nop // + mfc0 t3,index // read result of probe + nop + bltz t3,NotFoundAddr // if ltz, entry is not in TB + sll a0,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift VPN<12> into sign + tlbr // read entry from TB + nop // 3 cycle hazzard + nop // + nop // + bltz a0,11f // if ltz, check second PTE + mfc0 t2,entrylo1 // get second PTE for probe + mfc0 t2,entrylo0 // get first PTE for probe +11: mtc0 t1,entryhi // restore current PID + mtc0 zero,pagemask // restore page mask register +// t2 = entrylo + srl t2,t2,ENTRYLO_PFN + sll t2,t2,PAGE_SHIFT + li a2,PAGE_SIZE + subu a2,a2,1 + and a3,a3,a2 + or a3,a3,t2 + +FoundAddr: +// a3 = Physical addr + li a2,0x1fffffff + and a3,a3,a2 // 3 upper bits deleted + la k0,SavedErrorEpc // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + lw a1,0(k0) // load error epc register + lw a2,4(k0) // load cache error register + + // compute sip num + sw a3,CiArgs0(sp) + sw a1,CiArgs1(sp) + sw a2,CiArgs2(sp) + move a0,a3 + la t0,HalpComputeNum + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // compute sip num + nop + lw a3,CiArgs2(sp) + sw a3,0x10(sp) + li a1,18 + lw a2,CiArgs0(sp) +ShowMsg: + li a0,0x80 + + la t1,HalpKeBugCheck0 + sw a0,0(t1) + la t1,HalpKeBugCheck1 + sw a1,0(t1) + la t1,HalpKeBugCheck2 + sw a2,0(t1) + la t1,HalpKeBugCheck3 + sw v0,0(t1) + la t1,HalpKeBugCheck4 + sw a3,0(t1) + la t1,HalpBugCheckNumber + sw a1,0(t1) + la t0,KeBugCheckEx + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + move a3,v0 // sip num + + lw ra,CiRa(sp) // save return address + addu sp,sp,CiFrameLength // allocate stack frame + eret // + +NotFoundAddr: + + la a0,HalpAddrErrMsg + and a0,a0,0x1fffffff + or a0,a0,0xa0000000 + la t0,HalDisplayString + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + nop + + move a3,a1 + li a0,0x80 + la k0,SavedErrorEpc // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + li a1,18 + li a2,0x00 + lw a3,4(k0) + sw a3,0x10(sp) + la t1,HalpKeBugCheck0 + sw a0,0(t1) + la t1,HalpKeBugCheck1 + sw a1,0(t1) + la t1,HalpKeBugCheck2 + sw a2,0(t1) + la t1,HalpKeBugCheck3 + sw v0,0(t1) + la t1,HalpKeBugCheck4 + sw a3,0(t1) + la t1,HalpBugCheckNumber + sw a1,0(t1) + la t0,KeBugCheckEx + li k1,KSEG1_BASE // convert address of KSEG1 address + or t0,t0,k1 // + jal t0 // + li a3,0xff + + lw ra,CiRa(sp) // save return address + addu sp,sp,CiFrameLength // allocate stack frame + eret // + + .set reorder + + .end HalpCacheErrorRoutine |