NT4/private/ntos/nthals/halr98b/mips/cacherr.s
2020-09-30 17:12:29 +02:00

1436 lines
44 KiB
ArmAsm

// "@(#) 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<<PSR_DE)
mtc0 t4, psr
nop
nop
nop
.set reorder
and t4, t1, CHERR_EE # sysad parity error?
bnez t4, sysad_log
and t4, t1, CHERR_EC # primary cache error?
bnez t4, sche_log
and t4, t1, CHERR_ER # p-inst cache error?
bnez t4, dche_log
/*
* primary instruction cache parity error
*/
and t0, t1, CHERR_PIDX # K1(p) address
// sll t0, t0,CHERR_PSHFT
// sll t0, t0,12
and t4, t1, CHERR_SIDX2
or t0, t4
or t0, KSEG0_BASE
.set noreorder
cache 4, 0(t0) # I-cache index load tag
nop
nop
nop
mfc0 a2, taglo
mfc0 a3, ecc
.set reorder
sw t0, CheAdd_p(a0) # save cache address
sw a2, TagLo_p(a0) # save TagLo
sw a3, ECC_p(a0) # save ECC
and t4, t1, CHERR_ES # external reference?
bnez t4, iche_log_ex # then degrade error
and t4, t1, CHERR_EB # also occured data error?
bnez t4, iche_log_eb # then fatal error
and t4, t1, CHERR_ET # tag error?
bnez t4, iche_log_tag # then fatal error
and t4, t1, CHERR_ED # data error?
bnez t4, iche_log_dat # then degrade error
// li t4, FATAL_ERR # else fatal error
// sw t4, (a1)
li v0, ICHE_UNKNOWN
j iche_log_end
iche_log_dat:
// # li t4, RECOVER_ERR
// # sw t4, (a1)
li v0, ICHE_DAT
j iche_log_end
iche_log_tag:
// # li t4, FATAL_ERR
// # sw t4, (a1)
li v0, ICHE_TAG
j iche_log_end
iche_log_eb:
// li t4, FATAL_ERR
sw t4, (a1)
li v0, ICHE_EB
j iche_log_end
iche_log_ex:
// # li t4, RECOVER_ERR
// # sw t4, (a1)
li v0, ICHE_EX
iche_log_end:
.set noreorder
mtc0 zero,taglo
nop
cache 8, 0(t0) //# I-cache index store tag(invalid)
cache 20,0(t0) //# I-cache fill
cache 8, 0(t0) //# I-cache index store tag(invalid)
.set reorder
j che_log_end
/*
* primary data cache parity error
*/
dche_log:
and t0, t1, CHERR_SIDX2 //# K1(p) address
or t0, KSEG0_BASE
dche_log_loop:
.set noreorder
cache 5, 0(t0) //# D-cache index load tag
nop
nop
nop
mfc0 a2, taglo
mfc0 a3, ecc
.set reorder
sw t0, CheAdd_p(a0) //# save cache address
sw a2, TagLo_p(a0) //# save TagLo
sw a3, ECC_p(a0) //# save ECC
and t4, t1, CHERR_ET //# tag error?
beqz t4, dche_log_dat //# else data error
//#
//# Tag field error
//#
jal tag_parity_chk //# check tag parity
bnez v0, dche_tag_parity
add t0, 0x1000 //# check next PIDX
bltu t0, 0x80004000, dche_log_loop
//# less than 16K then loop
// li t4, FATAL_ERR # else fatal error
// sw t4, (a1)
li v0, DCHE_TAG_UNKNOW
j che_log_end
dche_tag_parity:
and t4, t1, CHERR_ES //# external reference?
bnez t4, dche_tag_ex //# then fatal error
and t4, a2, R4CT_PSTAT_MASK //# dirty?
beq t4, R4CT_PSTAT_DRE, dche_tag_dirty
beqz t4, dche_tag_clean
and t4, a2, R4CT_PTAG_MASK //# k1(s) address
sll t4, 4
and t5, t1, CHERR_SIDX2
or t4, t5
and t4, CHERR_SIDX
or t4, KSEG0_BASE
.set noreorder
cache 7, 0(t4) //# S-cache index load tag
nop
nop
nop
mfc0 t5, taglo
mfc0 t6, ecc
.set reorder
sw t4, CheAdd_s(a0) //# save cache address
sw t5, TagLo_s(a0) //# save TagLo
sw t6, ECC_s(a0) //# save ECC
and t7, t5, R4CT_SSTAT_MASK //# dirty?
beq t7, R4CT_SSTAT_DRE, dche_tag_dirty
dche_tag_clean:
// li t4, RECOVER_ERR
// sw t4, (a1)
li v0, DCHE_TAG_CLEAN
j dche_log_end
dche_tag_dirty:
// li t4, FATAL_ERR
// sw t4, (a1)
li v0, DCHE_TAG_DIRTY
j dche_log_end
dche_tag_ex:
// li t4, FATAL_ERR
// sw t4, (a1)
li v0, DCHE_TAG_EX
j dche_log_end
//#
//# Data field error
// #
dche_log_dat:
and t4, t1, CHERR_ED //# DATA error?
bnez t4, dche_dat //# then data error
// li t4, FATAL_ERR //# else fatal error
// sw t4, (a1)
li v0, DCHE_UNKNOWN
j che_log_end
dche_dat:
and t4, t1, CHERR_ES //# external reference?
beqz t4, dche_dat_chk //# else data error check
// li t4, FATAL_ERR //# then fatal error
// sw t4, (a1)
li v0, DCHE_DAT_EX
j che_log_end
dche_dat_chk:
/* For NT
and t4, a2, R4CT_PSTAT_MASK //# invalid?
beqz t4, dche_dat_next
move t8, a2 //# save TagLo
and t3, a2, R4CT_PTAG_MASK //# xkphs cached address
DSLL32 (T3, T3, 0)
DSRL (T3, T3, 28)
and t4, t1, CHERR_SIDX2
or t3, t4
li t4, XKPHYSEGMENT_HI_CCS
DSLL32 (T4, T4, 0)
or t3, t4
LD (A2, 0, T3) # load erronious data
SD (T3, xkphs_share, A0)
SD (A2, data_s, A0)
# jal dat_parity_chk # check data parity
move a2, t8 # resotore TagLo
# bnez v0, dche_dat_parity
.set noreorder
cache 1, 0(t0) # D-cache index writevack invalidate
lw zero, (t0) # D-cache dummy load
mtc0 zero, C0_TAGLO
nop
cache 9, 0(t0) # D-cache index store tag(invalid)
.set reorder
dche_dat_next:
add t0, 0x1000 # check next PIDX
bltu t0, 0x80004000, dche_log_loop
# less than 16K then loop
li t4, FATAL_ERR # all D-cache error is fatal
sw t4, (a1)
*/
li v0, DCHE_DAT_DIRTY
j che_log_end
/* comment out 1993.11.12
li t4, FATAL_ERR # else fatal error
sw t4, (a1)
li v0, DCHE_DAT_UNKNOW
j che_log_end
dche_dat_parity:
and t4, a2, R4CT_PSTAT_MASK # dirty?
beq t4, R4CT_PSTAT_DRE, dche_dat_dirty
bnez t4, dche_dat_dirty
dche_dat_clean:
li t4, RECOVER_ERR
sw t4, (a1)
li v0, DCHE_DAT_CLEAN
j dche_log_end
dche_dat_dirty:
li t4, FATAL_ERR
sw t4, (a1)
li v0, DCHE_DAT_DIRTY
*/
dche_log_end:
.set noreorder
mtc0 zero,taglo
nop
cache 9, 0(t0) # D-cache index store tag(invalid)
lw zero, (t0) # D-cache dummy load
cache 9, 0(t0) # D-cache index store tag(invalid)
.set reorder
j che_log_end
/*
* secondary cache error
*/
sche_log:
and t2, t1, CHERR_PIDX # K1(p) address
// sll t2, t2,CHERR_PSHFT
sll t2, t2,12
and t4, t1, CHERR_SIDX2
or t2, t4
or t2, KSEG0_BASE
sw t2, CheAdd_p(a0) # save cache address
and t4, t1, CHERR_EI # store miss error?
beqz t4, sche_log_tag # else tag error
.set noreorder
mtc0 zero, taglo
nop
cache 9, 0(t2) # D-cache index store tag(invalid)
.set reorder
sche_log_tag:
and t0, t1, CHERR_SIDX # K1(s) address
or t0, KSEG0_BASE
.set noreorder
cache 7, 0(t0) # S-cache index load tag
nop
nop
nop
mfc0 a2, taglo
mfc0 a3, ecc
.set reorder
sw t0, CheAdd_s(a0) # save cache address
sw a2, TagLo_s(a0) # save TagLo
sw a3, ECC_s(a0) # save ECC
and t4, t1, CHERR_ET # tag error?
beqz t4, sche_log_dat # else data error
// #
// # Tag field error
// #
move k0,v1
jal tag_ecc_chk //# check tag ecc
sw v1, tag_synd_s(a0)
move v1,k0
sw a2, Good_TagLo_s(a0)
beq v0, SCHE_TAG_1BIT, sche_tag_1bit
beq v0, SCHE_TAG_UNKNOW, sche_tag_noerr
sche_tag_2bit:
and t2, ~63 # 64byte boundary
.set noreorder
mtc0 zero, taglo
nop
cache 9, 0(t2) # D-cache index store tag(invalid)
cache 9, 16(t2)
cache 9, 32(t2)
cache 9, 48(t2)
cache 11, 0(t0) # S-cache index store tag(invalid)
.set reorder
// li t4, FATAL_ERR
j che_log_end
sche_tag_1bit:
.set noreorder
mtc0 a2, taglo
nop
cache 11, 0(t0) # S-cache index store tag(modify)
.set reorder
sche_tag_noerr:
and t4, t1, CHERR_ED # data error?
beqz t4, che_log_end # else end
sche_log_dat:
and t4, t1, CHERR_ED # data error?
bnez t4, sche_dat_0
// li t4, FATAL_ERR # else fatal error
// sw t4, (a1)
li v0, SCHE_UNKNOWN
j che_log_end
sche_dat_0:
and t4, t1, CHERR_ES # external reference?
// *tmp*
// beqz t4, sche_dat_1
// li t4, FATAL_ERR # then fatal error
// sw t4, (a1)
// li v0, SCHE_DAT_EX
li v0, SCHE_DAT_UNKNOW
j sche_log_end
/*
sche_dat_1:
and t4, a2, R4CT_SSTAT_MASK # dirty?
bne t4, R4CT_SSTAT_INV, sche_dat_chk
li t4, FATAL_ERR # then fatal error
sw t4, (a1)
li v0, SCHE_DAT_INV
j sche_log_end
sche_dat_chk:
move t8, a2 # save TagLo
and t3, a2, R4CT_STAG_MASK # xkphs cached address
DSLL32 (T3, T3, 0)
DSRL (T3, T3, 28)
and t4, t1, CHERR_SIDX
or t3, t4
li t4, XKPHYSEGMENT_HI_CCS
DSLL32 (T4, T4, 0)
or t3, t4
LD (A2, 0, T3) # load erronious data
SD (T3, xkphs_share, A0)
SD (A2, data_s, A0)
jal dat_ecc_chk # check data ecc
sw v1, data_synd_s(a0)
SD (A2, Good_data_s, A0)
sw a3, Good_ECC_s(a0)
move v1, a2 # save good data
move a2, t8 # resotore TagLo
beq v0, SCHE_DAT_2BIT_C, sche_dat_2bit
beq v0, SCHE_DAT_UNKNOW, sche_dat_unknown
SD (V1, 0, T3) # modified data
j sche_log_end
sche_dat_2bit:
and t4, a2, R4CT_SSTAT_MASK # dirty?
beq t4, R4CT_SSTAT_DRE, sche_dat_dirty
sche_dat_clean:
lw zero, (t0) # dummy read
li t4, RECOVER_ERR
sw t4, (a1)
j sche_log_end
sche_dat_dirty:
li v0, SCHE_DAT_2BIT_D
SD (V1, 0, T3) # rewrite error data
sche_dat_unknown:
li t4, FATAL_ERR
sw t4, (a1)
*/
sche_log_end:
and t2, ~63 # 64byte boundary
.set noreorder
cache 1, 0(t2) # D-cache index write back invalidate
cache 1, 16(t2)
cache 1, 32(t2)
cache 1, 48(t2)
cache 3, 0(t0) # S-cache index write back invalidate
.set reorder
j che_log_end
/*
* System address data parity error
*/
sysad_log:
// li t4, FATAL_ERR
// sw t4, (a1)
li v0, SYSAD_PARITY
che_log_end:
//For Log Function areg
move t0,a0
move a0,v1
/* lw a2,EPC_cpu(t0)
lw a1,CHERR_cpu(t0)
*/
move a2,v0
j HalpCacheErrorLog
//tmp lw t5, Status(a0) # load Status
/*
.set noreorder
mfc0 t4, cacheerr
mtc0 t5, psr
nop
nop
.set reorder
// tmp
and t4, CHERR_EW # cache error in chelog?
beqz t4, che_log_end2
li t4, FATAL_ERR
sw t4, (a1)
li v0, CHER_IN_CHER
che_log_end2:
j t9 # return
*/
// END(che_log)
//
// R10000 log
//
t5clog:
// Get Log data.
.set noreorder
move v1,a0
move a0,t1 # a0 = data address
move t8,a2 # t8 = ErrorEpc
move t7,a3 # t7 = Status
mfc0 t6,config # t6 = Config
mfc0 t5,prid # t5 = Prid
move t1,a1 # t1 = cache error state
or t4,t7,( 1 << PSR_ERL )
mtc0 t4,psr
dmfc0 t3,branchdiag
// mfps t2,$0
// mfpc t0,$0
move t2,zero
move t0,zero
.set reorder
// Set log data.
sw t8,R10_ErrEPC(a0) # save ErrEPC
sw t7,R10_Status(a0) # save Status
sw t6,R10_Config(a0) # save Config
sw t5,R10_PRid(a0) # save Prid
sw t1,R10_CacheEr(a0) # save CacheErr
sw t3,R10_BrDiag_Hi(a0) # save BranchDiag
srl t4,t3,16
srl t4,t4,16
sw t4,R10_BrDiag_Lo(a0)
sw t2,R10_PC_Ctrl(a0) # save PC Control
sw t0,R10_PC_Count(a0) # save PC Count
li t0,KSEG0_BASE # t0 = cache address
li t4,R10CHE_KIND_MASK
and t4,t1,t4
// I-cache error
li v0,R10_ICHE
li t5,R10CHE_KIND_I
beq t4,t5,t5_iche_log # I-cache parity error?
// D-cache error
li v0,R10_DCHE
li t5,R10CHE_KIND_D
beq t4,t5,t5_dche_log # D-cache parity error?
// S-cache error
li v0,R10_SCHE_2BIT
li t5,R10CHE_KIND_S
beq t4,t5,t5_sche_log # S-cache ECC error?
// SysAd error
li v0,R10_SYSAD_PARITY
// li t4,R10_FATAL_ERR
// sw t4,(a1)
and t4,t1,(R10CHE_SA | R10CHE_SC | R10CHE_SR)
bne t4,zero,t5_log_end # Sys I/F fatal error
t5_sche_log:
// Make cache addr
and t4,t1,R10CHE_SIDX_BLK
or t0,t4
and t4,t1,(R10CHE_D_WAY1 | R10CHE_TA_WAY1)
sne t4,0
or t0,t4 # t0 = cache way address
// TagHi & TagLo
.set noreorder
cache IndexLoadTag_S, 0(t0) # load tag
mfc0 t4,taghi
mfc0 t5,taglo
.set reorder
sw t0,R10_CheAdd(a0) # save cache address
sw t4,R10_TagHi(a0) # save TagHi
sw t5,R10_TagLo(a0) # save TagLo
// Cache data & ECC
addu t3,t0,64 # t3 = cacne address increment
addu t7,a0,64 # t7 = data save address increment
addu t8,a0,32 # t8 = ECC save address increment
load_Scache_loop:
subu t3,8 # new cache address
subu t7,8 # new data save address
subu t8,4 # new ECC save address
.set noreorder
cache IndexLoadData_S,0(t3) # load data
mfc0 t4,taghi
mfc0 t5,taglo
mfc0 t6,ecc
.set reorder
sw t4,R10_Cache_data0_Hi(t7) # save data high
sw t5,R10_Cache_data0_Lo(t7) # save data low
sw t6,R10_ECC0(t8) # save ECC
bne t3,t0,load_Scache_loop # 8 times
.set noreorder
cache IndexWriteBack_S,0(t0)
.set reorder
// li t4,R10_FATAL_ERR
// sw t4,(a1)
j t5_log_end
// I-cache
t5_iche_log:
// Make cache addr
and t4, t1, R10CHE_PIDX_BLK
or t0, t4
and t4, t1, (R10CHE_D_WAY1 | R10CHE_TA_WAY1 | R10CHE_TS_WAY1)
sne t4, 0
or t0, t4 # t0 = cache way address
// TagHi & TagLo
.set noreorder
cache IndexLoadTag_I, 0(t0) # load tag
mfc0 t4,taghi
mfc0 t5,taglo
.set reorder
sw t0,R10_CheAdd(a0) # save cache address
sw t4,R10_TagHi(a0) # save TagHi
sw t5,R10_TagLo(a0) # save TagLo
// Cache data & ECC
addu t3,t0,64 # t3 = cacne address increment
addu t7,a0,64 # t7 = data save address increment
addu t8,a0,32 # t8 = ECC save address increment
load_Icache_loop:
subu t3,4 # new cache address
subu t7,4 # new data save address
subu t8,2 # new ECC save address
.set noreorder
cache IndexLoadData_I,0(t3) # load data
mfc0 t4,taghi
mfc0 t5,taglo
mfc0 t6,ecc
.set reorder
sw t5,R10_Cache_data0_Hi(t7) # save data low
sll t4,8
or t6,t4
sh t6,R10_ECC0(t8) # save ECC
bne t3,t0,load_Icache_loop # 16 times
// Cache invalidate
.set noreorder
cache IndexInvalidate_I, 0(t0)
.set reorder
// li t4,NORMAL_ERR
// sw t4,(a1)
j t5_log_end
// D-cache
t5_dche_log:
// Make cache addr
and t4,t1,R10CHE_PIDX_DW
or t0,t4
and t4,t1,(R10CHE_D_WAY1|R10CHE_TA_WAY1|R10CHE_TS_WAY1|R10CHE_TM_WAY1)
sne t4,0
or t0,t4 # t0 = cache way address
// TagHi & TagLo
.set noreorder
cache IndexLoadTag_D,0(t0) # load tag
mfc0 t4,taghi
mfc0 t5,taglo
.set reorder
sw t0,R10_CheAdd(a0) # save cache address
sw t4,R10_TagHi(a0) # save TagHi
sw t5,R10_TagLo(a0) # save TagLo
// Cache data & ECC
and t0,0xffffffe1 # 32 bytes boundary block
addu t3,t0,32 # t3 = cacne address increment
addu t7,a0,64 # t7 = data save address increment
addu t8,a0,32 # t8 = ECC save address increment
load_Dcache_loop:
subu t3,4 # new cache address
subu t7,8 # new data save address
subu t8,4 # new ECC save address
.set noreorder
cache IndexLoadData_D,0(t3) # load data
mfc0 t5,taglo
mfc0 t6,ecc
.set reorder
sw t5,R10_Cache_data0_Lo(t7) # save data low
sw t6,R10_ECC0(t8) # save ECC
bne t3,t0,load_Dcache_loop # 8 times
.set noreorder
cache IndexWriteBack_D,0(t0)
.set reorder
// li t4,FATAL_ERR
// sw t4,(a1)
t5_log_end:
.set noreorder
lw t5,R10_Status(a0) # save Status
mfc0 t4,cacheerr
mtc0 t5,psr
nop
nop
.set reorder
and t4,R10CHE_EW # cache error in chelog?
beqz t4,t5_che_log_end
li v0,R10_CHER_IN_CHER
// li t4,FATAL_ERR
// sw t4,(a1)
t5_che_log_end:
move a1,a0
move a2,v0
move a0,v1
j HalpCacheErrorLog
.end HalpCacheErrorRoutine
/*********************************
* cache psued failure
*
* a0 = error code (argument)
********************************/
/*
//LEAF(psued_che)
LEAF_ENTRY(psude_che)
.set noreorder
li t0, PSUED_ADDRESS # error address
lw t1, (t0)
mfc0 t4, psr # save SR
sw t1, (t0)
li t6, 1
or t5, t4, (SR_CE | SR_DE)
mtc0 t6, ecc # ECC error
mtc0 t5, psr # set CE,DE bit
.set reorder
beqz a0, sche_yellow
li t1, 0xbadfaced
sw t1,(t0) # D-cache parity error
j psued_end
sche_yellow:
.set noreorder
cache 1, (t0) # S-cache 2bit error
nop
psued_end:
mtc0 C0_SR,t4 # restore sr
j ra
nop
.set reorder
END(psued_che)
*/
.set at
.set reorder
//
// ****** temp ******
/*********************************
* 32bit tag parity check
*
* v0 = return code (return value)
* 0 -- no error
* 1 -- error
*
* a0 = log field address (argument) : not used and not broken
* a1 = error code address (argument) : not used and not broken
* a2 = check data (argument)
* t0 = cache virtual address : not used and not broken
* t1 = Cache error reg : not used and not broken
* t2 = TagLo reg : not used and not broken
* t3 = ECC reg : not used and not broken
* t4 - t7 temprary data
********************************/
LEAF_ENTRY(tag_parity_chk)
.set reorder
li t4, 1 # target check bit
move v0, zero # Hparity bit and return value
ptag_chk_loop:
and t5, a2, t4
sne t5, 0
xor v0, t5 # calcurate parity
sll t4, 1
bnez t4, ptag_chk_loop # loop 31 times
j ra
// END(tag_parity_chk)
.end tag_parity_chk
/*********************************
* 64bit data parity check
*
* v0 = return code (return value)
* 0 -- no error
* 1 -- error
*
* a0 = log field address (argument) : not used and not broken
* a1 = error code address (argument) : not used and not broken
* a2 = 64bit data (argument)
* a3 = 8bit check data (argument)
* t0 = cache virtual address : not used and not broken
* t1 = Cache error reg : not used and not broken
* t2 = TagLo reg : not used and not broken
* t3 = ECC reg : not used and not broken
* t4 - t7 temprary data
********************************/
#if 0
LEAF(dat_parity_chk)
.set reorder
li t4, 1 # target check bit
li t5, 1 # target parity bit
li t6, 8 # byte counter
move v0, zero # Hparity bit and return value
pdat_chk_loop:
and t7, a2, t4
sne t7, 0
xor v0, t7 # calcurate parity
DSLL (T4, T4, 1)
subu t6, 1 # if 1byte check end?
bnez t6, pdat_chk_skip # else skip
and t7, a3, t5 # then check parity bit
sne t7, 0
xor v0, t7 # calcurate parity
xor v0, 1 # odd parity, not even 1993.11.7
sll t5, 1
li t6, 8 # reload byte counter
beqz v0, pdat_chk_skip # if no parity error then continue
j ra # else error return
pdat_chk_skip:
bnez t4, pdat_chk_loop # loop 63 times
j ra
END(dat_parity_chk)
#endif
/*********************************
* 2nd cache tag ECC check
*
* v0 = return code (return value)
* 0x20 -- SCHE_TAG_1BIT
* 0x21 -- SCHE_TAG_2BIT
* 0x23 -- SCHE_TAG_UNKNOW
* v1 = tag syndrome (return value)
*
* a0 = log field address (argument) : not used and not broken
* a1 = error code address (argument) : not used and not broken
* a2 = 2nd Tag erronious data (argument, return value)
* t0 = cache virtual address : not used and not broken
* t1 = Cache error reg : not used and not broken
* t2 = TagLo reg : not used and not broken
* t3 = ECC reg : not used and not broken
* t4 - t7 temprary data
********************************/
LEAF_ENTRY(tag_ecc_chk)
.set reorder
li t4, 1 # target check bit
la t5, tag_synd # tag syndrome data
move v1, zero # tag syndrome and return value
// # make syndrome data
tag_ecc_loop1:
and t6, a2, t4
beqz t6, tag_ecc_skip0
lbu t7, (t5) # make syndrome
xor v1, t7 #
tag_ecc_skip0:
sll t4, 1
addu t5, 1
bnez t4, tag_ecc_loop1 # loop 31 times
bnez v1, tag_ecc_err # if no error
li v0, SCHE_TAG_UNKNOW # then unknown error
j ra
// # modify data
tag_ecc_err:
li t4, 1 # target check bit
la t5, tag_synd # tag syndrome data
tag_ecc_loop2:
lbu t7, (t5) # 1bit error
beq v1, t7, tag_ecc_1bit # then 1bit error
sll t4, 1
addu t5, 1
bnez t4, tag_ecc_loop2 # loop 31 times
li v0, SCHE_TAG_2BIT # 2bit error
j ra
tag_ecc_1bit:
xor a2, t4 # modified data
li v0, SCHE_TAG_1BIT # 1bit error
j ra
tag_synd:
.byte 0x01 # ECC 0 (bit 25)
.byte 0x02 # ECC 1 (bit 26)
.byte 0x04 # ECC 2 (bit 27)
.byte 0x08 # ECC 3 (bit 28)
.byte 0x10 # ECC 4 (bit 29)
.byte 0x20 # ECC 5 (bit 30)
.byte 0x40 # ECC 6 (bit 31)
.byte 0x45 # Pidx 0 (bit 19)
.byte 0x29 # Pidx 1 (bit 20)
.byte 0x51 # Pidx 2 (bit 21)
.byte 0x13 # CS 0 (bit 22)
.byte 0x49 # CS 1 (bit 23)
.byte 0x25 # CS 2 (bit 24)
.byte 0x07 # STag 00 (bit 00)
.byte 0x16 # STag 01 (bit 01)
.byte 0x26 # STag 02 (bit 02)
.byte 0x46 # STag 03 (bit 03)
.byte 0x0d # STag 04 (bit 04)
.byte 0x0e # STag 05 (bit 05)
.byte 0x1c # STag 06 (bit 06)
.byte 0x4c # STag 07 (bit 07)
.byte 0x31 # STag 08 (bit 08)
.byte 0x32 # STag 09 (bit 09)
.byte 0x38 # STag 10 (bit 10)
.byte 0x70 # STag 11 (bit 11)
.byte 0x61 # STag 12 (bit 12)
.byte 0x62 # STag 13 (bit 13)
.byte 0x64 # STag 14 (bit 14)
.byte 0x68 # STag 15 (bit 15)
.byte 0x0b # STag 16 (bit 16)
.byte 0x15 # STag 17 (bit 17)
.byte 0x23 # STag 18 (bit 18)
// END(tag_ecc_chk)
.end tag_ecc_chk
#if 0
/*********************************
* 2nd cache 64bit data ECC check
*
* v0 = return code (return value)
* 0x26 -- SCHE_DAT_1BIT
* 0x27 -- SCHE_DAT_2BIT_C
* 0x29 -- SCHE_DAT_UNKNOW
* v1 = data syndrome (return value)
*
* a0 = log field address (argument) : not used and not broken
* a1 = error code address (argument) : not used and not broken
* a2 = 2nd 64bit data erronious data (argument, return value)
* a3 = 8bit ECC data (argument, return value)
* t0 = cache virtual address : not used and not broken
* t1 = Cache error reg : not used and not broken
* t2 = TagLo reg : not used and not broken
* t3 = ECC reg : not used and not broken
* t4 - t7 temprary data
********************************/
LEAF(dat_ecc_chk)
.set reorder
li t4, 1 # target check bit
la t5, dat_synd # data syndrome address
move v1, zero # data syndrome and return value
# make syndrome data
dat_ecc_loop1:
and t6, a2, t4
beqz t6, dat_ecc_skip0
lbu t7, (t5) # make syndrome of data
xor v1, t7 #
dat_ecc_skip0:
addu t5, 1
DSLL (T4, T4, 1)
bnez t4, dat_ecc_loop1 # loop 63 times
li t4, 1 # target check bit
dat_ecc_loop2:
and t6, a3, t4
beqz t6, dat_ecc_skip1
lbu t7, (t5) # make syndrome of data
xor v1, t7 #
dat_ecc_skip1:
sll t4, 1
addu t5, 1
bne t4, 0x100, dat_ecc_loop2 # loop 7 times
bnez v1, dat_ecc_err # if error
li v0, SCHE_DAT_UNKNOW # else unknown error
j ra
# modify data
dat_ecc_err:
li t4, 1 # target check bit
la t5, dat_synd # tag syndrome data
dat_ecc_loop3:
lbu t7, (t5) # 1bit error
beq v1, t7, dat_ecc_1bit # then 1bit error
DSLL (T4, T4, 1)
addu t5, 1
bnez t4, dat_ecc_loop3 # loop 63 times
li t4, 1 # target check bit
dat_ecc_loop4:
lbu t7, (t5) # 1bit error
beq v1, t7, dat_ecc_1bit2 # then 1bit error
sll t4, 1
addu t5, 1
bne t4, 0x100, dat_ecc_loop4 # loop 7 times
li v0, SCHE_DAT_2BIT_C # 2bit error
j ra
dat_ecc_1bit2:
xor a3, t4 # modified ECC
j dat_ecc_1bitend
dat_ecc_1bit:
xor a2, t4 # modified data
dat_ecc_1bitend:
li v0, SCHE_DAT_1BIT # 1bit error
j ra
dat_synd:
.byte 0x13 # Data 00 (bit 00)
.byte 0x23 # Data 01 (bit 01)
.byte 0x43 # Data 02 (bit 02)
.byte 0x83 # Data 03 (bit 03)
.byte 0x2f # Data 04 (bit 04)
.byte 0xf1 # Data 05 (bit 05)
.byte 0x0d # Data 06 (bit 06)
.byte 0x07 # Data 07 (bit 07)
.byte 0xd0 # Data 08 (bit 08)
.byte 0x70 # Data 09 (bit 09)
.byte 0x4f # Data 10 (bit 10)
.byte 0xf8 # Data 11 (bit 11)
.byte 0x61 # Data 12 (bit 12)
.byte 0x62 # Data 13 (bit 13)
.byte 0x64 # Data 14 (bit 14)
.byte 0x68 # Data 15 (bit 15)
.byte 0x1c # Data 16 (bit 16)
.byte 0x2c # Data 17 (bit 17)
.byte 0x4c # Data 18 (bit 18)
.byte 0x8c # Data 19 (bit 19)
.byte 0x15 # Data 20 (bit 20)
.byte 0x25 # Data 21 (bit 21)
.byte 0x45 # Data 22 (bit 22)
.byte 0x85 # Data 23 (bit 23)
.byte 0x19 # Data 24 (bit 24)
.byte 0x29 # Data 25 (bit 25)
.byte 0x49 # Data 26 (bit 26)
.byte 0x89 # Data 27 (bit 27)
.byte 0x1a # Data 28 (bit 28)
.byte 0x2a # Data 29 (bit 29)
.byte 0x4a # Data 30 (bit 30)
.byte 0x8a # Data 31 (bit 31)
.byte 0x51 # Data 32 (bit 32)
.byte 0x52 # Data 33 (bit 33)
.byte 0x54 # Data 34 (bit 34)
.byte 0x58 # Data 35 (bit 35)
.byte 0x91 # Data 36 (bit 36)
.byte 0x92 # Data 37 (bit 37)
.byte 0x94 # Data 38 (bit 38)
.byte 0x98 # Data 39 (bit 39)
.byte 0xa1 # Data 40 (bit 40)
.byte 0xa2 # Data 41 (bit 41)
.byte 0xa4 # Data 42 (bit 42)
.byte 0xa8 # Data 43 (bit 43)
.byte 0x31 # Data 44 (bit 44)
.byte 0x32 # Data 45 (bit 45)
.byte 0x34 # Data 46 (bit 46)
.byte 0x38 # Data 47 (bit 47)
.byte 0x16 # Data 48 (bit 48)
.byte 0x26 # Data 49 (bit 49)
.byte 0x46 # Data 50 (bit 50)
.byte 0x86 # Data 51 (bit 51)
.byte 0x1f # Data 52 (bit 52)
.byte 0xf2 # Data 53 (bit 53)
.byte 0x0b # Data 54 (bit 54)
.byte 0x0e # Data 55 (bit 55)
.byte 0xb0 # Data 56 (bit 56)
.byte 0xe0 # Data 57 (bit 57)
.byte 0x8f # Data 58 (bit 58)
.byte 0xf4 # Data 59 (bit 59)
.byte 0xc1 # Data 60 (bit 60)
.byte 0xc2 # Data 61 (bit 61)
.byte 0xc4 # Data 62 (bit 62)
.byte 0xc8 # Data 63 (bit 63)
.byte 0x01 # ECC 0 (bit 0)
.byte 0x02 # ECC 1 (bit 1)
.byte 0x04 # ECC 2 (bit 2)
.byte 0x08 # ECC 3 (bit 3)
.byte 0x10 # ECC 4 (bit 4)
.byte 0x20 # ECC 5 (bit 5)
.byte 0x40 # ECC 6 (bit 6)
.byte 0x80 # ECC 7 (bit 7)
END(dat_ecc_chk)
#endif