1
0
Files
irix-657m-src/stand/arcs/IP21prom/pod_cache.s
2022-09-29 17:59:04 +03:00

1795 lines
57 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* IP21prom/pod_cache.s
*
*/
#include "ml.h"
#include <sys/regdef.h>
#include <asm.h>
#include <sys/sbd.h>
#include <sys/EVEREST/evdiag.h>
#include <sys/cpu.h>
#include "pod.h"
#include "pod_failure.h"
#include "prom_leds.h"
#include "ip21prom.h"
/*
* Module Name Description
* ---------------------------------------------------------
* dcache_addr dcache address pattern test
* dcache_data dcache data pattern test
* dcache_tag dcache tag ram test
* flush_SAQueue
* get_dcacheline get dcache line size
* get_dcachesize get dcache size
* get_icacheline get icache line size
* get_icachesize get icache size
* pon_fix_dcache_parity fix dcache parity
* pon_invalidate_IDcaches invalidate I&D cache
* pon_invalidate_dcache invalidate dcache
* gcache_invalidate invalidate gcache
* gcache_check check tag and data rams of gcache
* pon_setup_stack_in_dcache set dcache to exclusive for stack
* pon_validate_scache_d validate scache map to dcache
* read_scachesize get scache size
*/
#define K0_SAVE $f14
#define K1_SAVE $f15
#define AT_SAVE $f16
#define RA_SAVE $f17
#define A0_SAVE $f18
#define T3_SAVE $f19
#define TA0_SAVE $f20
#define A1_SAVE $f21
#define SP_SAVE $f22
#define V0_SAVE $f23
#define T1_SAVE $f24
#define GP_SAVE $f25
#define T9_SAVE $f26
#define T8_SAVE $f27
#define BTAG_ST_WRITE 0x1f000
#define BTAG_ST_READ 0x0
#define PTAG_ST_WRITE 0xfc00000000
#define PTAG_ST_READ 0xf000
#define GCACHE_BYTES_TO_LINES_SHIFT 11
#define GCACHE_NUM_BYTES_IN_LINE 512
#define DUMP_SET_INFO(base, offset1, line_offset_reg) \
dli t0, base; \
li t1, offset1; \
daddu t0, t0, t1; \
daddu t0, t0, line_offset_reg; \
ld t0, 0(t0); \
DEBUG_REG(t0)
#define DUMP_LINE_INFO(base, line) \
li t2, line; \
dsll t2, 3; \
DUMP_SET_INFO(base, 0, t2); \
DUMP_SET_INFO(base, 0x10000, t2); \
DUMP_SET_INFO(base, 0x20000, t2); \
DUMP_SET_INFO(base, 0x30000, t2);
#define SC_TAGRAM_ADDR_INIT_FOR_SET(reg1, reg2, reg3, reg4, set_reg, bit_reg, scr_reg) \
dli reg1, BB_BUSTAG_ADDR; \
dli reg2, BB_PTAG_E_ADDR; \
dli reg3, BB_BUSTAG_ST; \
dli reg4, BB_PTAG_E_ST; \
li scr_reg, 0x10000; \
dmult scr_reg, set_reg; \
mflo scr_reg; \
daddu reg1, scr_reg; \
daddu reg2, scr_reg; \
daddu reg3, scr_reg; \
daddu reg4, scr_reg; \
dsll scr_reg, bit_reg, 14; \
or reg1, reg1, scr_reg; \
or reg2, reg2, scr_reg; \
or reg3, reg3, scr_reg; \
or reg4, reg4, scr_reg
#define SC_TAGRAM_ADDR_NEXT_LINE(bustag_reg, proctag_reg, busstate_reg, procstate_reg, scr_reg) \
li scr_reg, 8; \
daddu bustag_reg, bustag_reg, scr_reg; \
daddu proctag_reg, proctag_reg, scr_reg; \
daddu busstate_reg, busstate_reg, scr_reg; \
daddu procstate_reg, procstate_reg, scr_reg
/* read_scachesize(), which this macro calls, uses t0, t1, v0, ra */
#if 0
#define SC_GET_NUM_LINES_IN_GCACHE(result_reg) \
/* read Gcache size. Default GCache size is 4MB */ ; \
/* 4M gcache = 4 sets of 2048 (2K) lines of 512 bytes each */ ; \
/* 8M gcache = 4 sets of 4096 (4k) lines of 512 bytes each */ ; \
/* 16M gcache = 4 sets of 8192 (8k) lines of 512 bytes each */ ; \
DMTC1(k0, K0_SAVE); \
DMTC1(k1, K1_SAVE); \
jal read_scachesize; \
nop; \
DMFC1(k0, K0_SAVE); \
DMFC1(k1, K1_SAVE); \
dsrl result_reg, v0, GCACHE_BYTES_TO_LINES_SHIFT
#endif
#define SC_GET_NUM_LINES_IN_GCACHE(result_reg) \
li result_reg, 2048
#define SC_TAG_BITS(result_reg, addr_reg, scr_reg) \
dli scr_reg, 0xfffff00000; \
and result_reg, addr_reg, scr_reg
#define SC_TAG_BITS_WITH_ADDR_BITS(result_reg, addr_reg, loc_reg, scr_reg) \
dli scr_reg, 0xfffff00000; \
and result_reg, addr_reg, scr_reg; \
li scr_reg, 0xffffffffffcfffff; \
and result_reg, result_reg, scr_reg; \
li scr_reg, 0xc000; \
and scr_reg, loc_reg, scr_reg; \
dsll scr_reg, 6; \
or result_reg, result_reg, scr_reg
#define SC_STATE_BITS(result_reg, addr_reg, scr_reg) \
dli scr_reg, 0xfff; \
and result_reg, addr_reg, scr_reg
#define GCACHE_CHECK_TAGS(tag_init, tag_inc, state_init, state_inc, num_sets, start_set, bits_15_14) \
dli a0, tag_init; \
dli a1, tag_inc; \
dli a2, state_init; \
dli a3, state_inc; \
li t2, num_sets; \
li t3, start_set; \
li v0, bits_15_14; \
li v1, 1; \
jal gcache_check_tags; \
nop
#define GCACHE_SET_TAGS(tag_init, tag_inc, state_init, state_inc, num_sets, start_set, bits_15_14) \
dli a0, tag_init; \
dli a1, tag_inc; \
dli a2, state_init; \
dli a3, state_inc; \
li t2, num_sets; \
li t3, start_set; \
li v0, bits_15_14; \
li v1, 0; \
jal gcache_check_tags; \
nop
/* ******************************************************************************
* gcache_check
*
* This is the highest level routine for checking the gcache. It checks both
* the G$ tag rams and data rams. It is called by both the master and slaves.
* ******************************************************************************/
#if 0
LEAF (gcache_check)
dli t0, BB_BUSTAG_ADDR
li t1, 0x170000
dadd t0, t1
DMTC1(t0, GP_SAVE)
li v0, 1
j gcache_print_tag_error_and_return
END(gcache_check)
#endif
LEAF(gcache_check)
.set noreorder
DMTC1(ra, AT_SAVE)
li a0, 0
jal gcache_check_tag_addr
nop
li a0, 0
jal gcache_check_tag_data
nop
li a0, 0
jal gcache_check_data
nop
/*
* Invalidate sets 0, 1, and 2, and then turn off FORCE SET 3 and turn
* on bit 0 of the set allow register, putting us into a mode that is
* "FORCE SET 0". Call gcache_invalidate again in FORCE SET 0 mode so
* that we invalidate the entries in set 3 that did not get invalidated
* when we did the first series of invalidates because we were running
* in set 3. Both times when I call gcache_invalidate I call it twice
* in a row. The idea is that the first time we run it we are not running
* fully in the gcache, so there are some entries that do not get invalidated
* (because of our code section). The second time we are running fully from
* the gcache. However, I think this is overkill and I don't believe
* we really need the second one in each series. The first time we
* invalidate, even if we leave some junk in set 3, that is ok because when
* we go into FORCE SET 0, we will invalidate again and this time the junk
* in set 3 will get cleaned up. But I'm leaving the double calls just
* in case I have missed something.
*/
jal gcache_invalidate
nop
jal gcache_invalidate
nop
dli t1, BB_STARTUP_CTRL
li a0, 1
sd a0, 0(t1)
dli t1, BB_SET_ALLOW
li a0, 0x1
sd a0, 0(t1) # set allow set 0
jal gcache_invalidate
nop
jal gcache_invalidate
nop
GCACHE_SET_TAGS(0x41fc00000, 0x0, BTAG_ST_INIT, 0, 0x1, 0x0, 0x0)
GCACHE_SET_TAGS(0x418000000, 0x0, BTAG_ST_INIT, 0, 0x1, 0x1, 0x0)
GCACHE_SET_TAGS(0x418100000, 0x0, BTAG_ST_INIT, 0, 0x1, 0x2, 0x1)
li a0, 1
jal gcache_check_tag_addr
nop
li a0, 1
jal gcache_check_tag_data
nop
li a0, 1
jal gcache_check_data
nop
jal gcache_invalidate
nop
jal gcache_invalidate
nop
/* Put us back into FORCE SET 3, re-invalidate gcache */
dli t1, BB_STARTUP_CTRL
li a0, 3
sd a0, 0(t1)
dli t1, BB_SET_ALLOW
li a0, 0x8
sd a0, 0(t1) # set allow set 0
jal gcache_invalidate
nop
DMFC1(ra, AT_SAVE)
li v0, 0
j ra
nop
END(gcache_check)
/* ******************************************************************************
* gcache_invalidate
*
* This routine initializes the gcache tag and state rams, such that all
* entries are invalid. The tags are set like this:
* set 0 set 1 set 2 set 3
* 0x1cc 0x1dc 0x1ec 0x1fc
*
* Since the execution of the code and the writing of the tags will knock
* out of the gcache, there will be a couple of entries that are not intitialized
* as shown above. But this still achieves the desired effect of getting the
* gcache into a known state.
* ******************************************************************************/
LEAF(gcache_invalidate)
.set noreorder
DMTC1(ra, RA_SAVE)
GCACHE_SET_TAGS(0x802a000000, 0x0, BTAG_ST_INIT, 0x0, 0x1, 0x0, 0x0)
GCACHE_SET_TAGS(0x802b000000, 0x0, BTAG_ST_INIT, 0x0, 0x1, 0x1, 0x0)
GCACHE_SET_TAGS(0x802c000000, 0x0, BTAG_ST_INIT, 0x0, 0x1, 0x2, 0x0)
GCACHE_SET_TAGS(0x802d000000, 0x0, BTAG_ST_INIT, 0x0, 0x1, 0x3, 0x0)
DMFC1(ra, RA_SAVE)
j ra
nop
END(gcache_invalidate)
/* ******************************************************************************
* gcache_check_tag_addr
* Test the gcache tag addressing to make sure we can address each tag correctly
* from CC local register space.
* ******************************************************************************/
LEAF(gcache_check_tag_addr)
.set noreorder
DMTC1(ra, RA_SAVE)
beq a0, r0, gcache_check_tag_addr_set_0_1_2
nop
gache_check_tag_addr_set_3:
GCACHE_CHECK_TAGS(0x0, 0xe000400000, 0x0, 0x1, 0x1, 0x3, 0x0)
beq v0, r0, gcache_check_tag_addr_pass_set_3
nop
j gcache_check_tag_addr_fail_set_3
nop
gcache_check_tag_addr_set_0_1_2:
GCACHE_CHECK_TAGS(0x0, 0xe000400000, 0x0, 0x1, 0x3, 0x0, 0x0)
beq v0, r0, gcache_check_tag_addr_pass_set_0_1_2
nop
j gcache_check_tag_addr_fail_set_0_1_2
gcache_check_tag_addr_fail_set_3:
ERROR_MSG("\r\nGcache TAG ADDR test for set 3 FAILED\r\n")
j gcache_check_tag_addr_fail_info
nop
gcache_check_tag_addr_fail_set_0_1_2:
ERROR_MSG("\r\nGcache TAG ADDR test for set 0, 1, or 2 FAILED\r\n")
gcache_check_tag_addr_fail_info:
ERROR_MSG_FPREG(" line index: ", T1_SAVE)
ERROR_MSG_FPREG(" set index: ", T3_SAVE)
ERROR_MSG_FPREG(" address: ", GP_SAVE)
ERROR_MSG_FPREG(" expected data: ", T9_SAVE)
ERROR_MSG_FPREG(" actual data: ", T8_SAVE)
li v0, EVDIAG_SCACHE_TAG
DMFC1(ra, RA_SAVE)
j gcache_print_tag_error_and_return
nop
gcache_check_tag_addr_pass_set_3:
PASS_MSG("\Gcache TAG ADDR test for set 3 PASSED\r\n")
j gcache_check_tag_addr_pass_return
nop
gcache_check_tag_addr_pass_set_0_1_2:
PASS_MSG("\Gcache TAG ADDR test for sets 0, 1, 2 PASSED\r\n")
gcache_check_tag_addr_pass_return:
DMFC1(ra, RA_SAVE)
j ra
nop
END(gcache_check_tag_addr)
/* ******************************************************************************
* gcache_check_tag_data
* Test the gcache tag data rams to make sure that no bits are stuck at 0,
* stuck at 1, or stuck together.
* ******************************************************************************/
LEAF(gcache_check_tag_data)
.set noreorder
DMTC1(ra, RA_SAVE)
beq a0, r0, gcache_check_tag_data_set_0_1_2
nop
gcache_check_tag_data_set_3:
GCACHE_CHECK_TAGS(0xaaaaaaaaaaaaaaaa, 0x0, 0xaaaaaaaaaaaaaaaa, 0x0, 0x1, 0x3, 0x0)
bne v0, r0, gcache_check_tag_data_fail_set_3
nop
GCACHE_CHECK_TAGS(0x5555555555555555, 0x0, 0x5555555555555555, 0x0, 0x1, 0x3, 0x0)
beq v0, r0, gcache_check_tag_data_pass_set_3
nop
gcache_check_tag_data_set_0_1_2:
GCACHE_CHECK_TAGS(0xaaaaaaaaaaaaaaaa, 0x0, 0xaaaaaaaaaaaaaaaa, 0x0, 0x3, 0x0, 0x0)
bne v0, r0, gcache_check_tag_data_fail_set_0_1_2
nop
GCACHE_CHECK_TAGS(0x5555555555555555, 0x0, 0x5555555555555555, 0x0, 0x3, 0x0, 0x0)
beq v0, r0, gcache_check_tag_data_pass_set_0_1_2
nop
gcache_check_tag_data_fail_set_3:
ERROR_MSG("\r\nGcache TAG DATA test for set 3 FAILED\r\n")
gcache_check_tag_data_fail_set_0_1_2:
ERROR_MSG("\r\nGcache TAG DATA test for set 0, 1, or 2 FAILED\r\n")
gcache_check_tag_data_fail_info:
ERROR_MSG_FPREG(" line index: ", T1_SAVE)
ERROR_MSG_FPREG(" set index: ", T3_SAVE)
ERROR_MSG_FPREG(" address: ", GP_SAVE)
ERROR_MSG_FPREG(" expected data: ", T9_SAVE)
ERROR_MSG_FPREG(" actual data: ", T8_SAVE)
li v0, EVDIAG_SCACHE_TAG
DMFC1(ra, RA_SAVE)
j gcache_print_tag_error_and_return
nop
gcache_check_tag_data_pass_set_3:
PASS_MSG("\Gcache TAG DATA test for set 3 PASSED\r\n")
j gcache_check_tag_data_pass_return
nop
gcache_check_tag_data_pass_set_0_1_2:
PASS_MSG("\Gcache TAG DATA test for sets 0, 1, 2 PASSED\r\n")
gcache_check_tag_data_pass_return:
DMFC1(ra, RA_SAVE)
j ra
nop
END(gcache_check_tag_data)
/* ******************************************************************************
* gcache_check_data
* Test the gcache data rams to make sure that no bits are stuck at 0,
* stuck at 1, or stuck together.
* ******************************************************************************/
LEAF(gcache_check_data)
.set noreorder
DMTC1(ra, RA_SAVE)
DMTC1(a0, A0_SAVE) /* be careful that gcache_check_data() doesn't use A0_SAVE! */
/* *****************************************************************************
* Set up the gcache so that all lines in set 0 have a tag of 0xf0000, all lines
* in set 1 have a tag of 0xf0004, all lines in set 2 have a tag of 0xf0008.
* After calling GCACHE_SET_TAGS() to set up the tags and state, call
* gcache_set_vsyn to fix up the virtual synonm bits in the state.
* *****************************************************************************/
beq a0, r0, gcache_check_data_set_0_1_2
nop
gcache_check_data_set_3:
GCACHE_SET_TAGS(0xf000c00000, 0x0, BTAG_ST_EXCL, 0x0, 0x1, 0x3, 0x0)
li t2, 1 # do one set
li t3, 3 # start with set 3
jal gcache_set_vsyn
nop
li t2, 1 # do one set
li t3, 3 # start with set 3
j gcache_check_data_common_code
nop
gcache_check_data_set_0_1_2:
GCACHE_SET_TAGS(0xf000000000, 0x0, BTAG_ST_EXCL, 0x0, 0x1, 0x0, 0x0)
GCACHE_SET_TAGS(0xf000400000, 0x0, BTAG_ST_EXCL, 0x0, 0x1, 0x1, 0x0)
GCACHE_SET_TAGS(0xf000800000, 0x0, BTAG_ST_EXCL, 0x0, 0x1, 0x2, 0x0)
li t2, 3 # do 3 sets
li t3, 0 # start with st 0
jal gcache_set_vsyn
nop
li t2, 3 # do 3 sets
li t3, 0 # start with st 0
gcache_check_data_common_code:
SC_GET_NUM_LINES_IN_GCACHE(t0) # t0 = num of lines(2048)
li t8, GCACHE_NUM_BYTES_IN_LINE #(512)
dmult t8, t0
mflo t0 # t0 = number of bytes to cycle through
# last one we want to store to
/* *****************************************************************************
* This code contains a loop within a loop. The outer loop stores a data value to
* each double word ina single gcache set, starting at double word 0x0, going
* up to address 2048 lines * 512 bytes/line = 0x100000.
* The outer loop, the inner loop once for each of sets 0, 1, 2.
*
* set0 set1 set2
* data addr data addr data addr
* 0x0 -> 0x0 0x400000 -> 0x400000 0x800000 -> 0x800000
* 0x8 -> 0x8 0x400008 -> 0x400008 0x800008 -> 0x800008
* 0x10 -> 0x10 0x400010 -> 0x400010 0x800010 -> 0x800010
* ... ... ...
*******************************************************************************/
1:
dsll t9, t3, 22 # t9 = tag for this set
dli t8, 0xa80000f000000000
or t9, t9, t8
li a0, 0
2: /* store into set(s) */
or gp, t9, a0
sd gp, 0(gp)
daddiu a0, 8
nop
blt a0, t0, 2b
nop
daddiu t3, 1
blt t3, t2, 1b # do outer loop for sets 0, 1, 2
nop
/* *****************************************************************************
* The code below contains a loop within a loop. The inner loop runs through each
* double word in a single set of the gcache, reading from it and comparing it
* to the value that we stored in the above loop.
* The outer loop executes the inner loop once for each set.
*******************************************************************************/
DMFC1(a0, A0_SAVE)
beq a0, r0, gcache_read_data_set_0_1_2
nop
j gcache_read_data_set_3
nop
gcache_read_data_set_0_1_2:
li t2, 3 # do 3 sets
li t3, 0 # start with st 0
j gcache_read_data_common_code
nop
gcache_read_data_set_3:
li t2, 1 # do one set
li t3, 3 # start with set 3
gcache_read_data_common_code:
4:
dsll t9, t3, 22 # t9 = tag for this set
dli t8, 0xa80000f000000000
or t9, t9, t8
li a0, 0
5:
or gp, t9, a0
daddiu a0, 8
ld a1, 0(gp)
bne gp, a1, 99f
nop
blt a0, t0, 5b
nop
daddiu t3, 1
blt t3, t2, 4b # do outer loop for sets 0, 1, 2
nop
DMFC1(a0, A0_SAVE)
beq a0, r0, gcache_check_data_passed_set_0_1_2
nop
gcache_check_data_passed_set_3:
PASS_MSG("\Gcache RAM DATA test for set 3 PASSED\r\n")
j gcache_check_data_passed_common_code
nop
gcache_check_data_passed_set_0_1_2:
PASS_MSG("\Gcache RAM DATA test for sets 0, 1, 2 PASSED\r\n")
gcache_check_data_passed_common_code:
li v0, 0
DMFC1(ra, RA_SAVE)
j ra
nop
99:
DMTC1(t3, T3_SAVE)
DMTC1(gp, GP_SAVE)
DMTC1(a1, A1_SAVE)
DMFC1(a0, A0_SAVE)
beq a0, r0, gcache_check_data_failed_set_0_1_2
nop
gcache_check_data_failed_set_3:
ERROR_MSG("Gcache RAM DATA test for set 3 FAILED\r\n")
j gcache_check_data_failed_common_code
nop
gcache_check_data_failed_set_0_1_2:
ERROR_MSG("Gcache RAM DATA test for set 0, 1, or 2 FAILED\r\n")
gcache_check_data_failed_common_code:
ERROR_MSG_FPREG(" set index: ", T3_SAVE)
ERROR_MSG_FPREG(" address: ", GP_SAVE)
ERROR_MSG_FPREG(" expected data: ", GP_SAVE)
ERROR_MSG_FPREG(" actual data: ", A1_SAVE)
li v0, EVDIAG_SCACHE_DATA
DMFC1(ra, RA_SAVE)
j gcache_print_data_error_and_return
nop
END(gcache_check_data)
/* ******************************************************************************
* gcache_check_tags
* This routine writes the bus tags, proc tags, bus state, and proc state
* tag rams and reads the values back to check that they are correct. Currently
* this routine does this for only sets 0, 1, and 2. We are running in force
* set 3 mode, so this means that any gcache misses we take will replace set 3,
* and will not interfere in any way with our checking of sets 0, 1, and 2.
*
* This routine takes four arguments:
* a0: tag init value
* This value is used to calculate the value written to the bus/proc
* tags. This value is written to the bus tag for line 0, then we add
* the tag_increment_value to it and write this new value to the proc tag for
* line 0. Then we increment by the tag_increment_value again, and write the
* new value to the bus tag for line 1, etc. When we write the tags, bits
* 21:20 of the data written is actually taken from bits 15:14 of the tag
* address. We write to the tag the value we computed into a0, but when we
* later check the tags we make the assumption that bits 21:20 were taken from
* 15:14 of the tag address, so we are checking with a value that is slightly
* different than the value we wrote.
* a1: tag increment value
* a2: state init value
* This value is used to calculate the value written to the bus/proc
* state. This value is written to the bus state for line 0, then we add
* the state__increment_value to it and write this new value to the proc state for
* line 0. Then we increment by the state_increment_value again, and write the
* new value to the bus state for line 1, etc. Since only bits 11:0 of the
* bus state are bits we want to write with values, the increment value is added
* to a2 modulo 0xfff, so that only bits 11:0 change. Bits 16:12 are always
* written with '1's because these bits are write enables for bits 11:0.
* In the case of the proc state, we have a similar situation except that the
* data we write must be shifted left 22 bits.
* a3: state increment value
* t2: number of sets to initialize, starting at set specified by t3
* t3: first set to initialize
* v1: specifies whether we should only set the tags, or whether we should
* set them and then read them back to confirm they contain the right values.
* 0 specifies set them, only. 1 specifies set them and then check the
* values.
* Note, all the of argument registers were chosen carefully to avoid conflicting
* with registers t0, t1, v0, ra, which SC_GET_NUM_LINES_IN_GCACHE() changes!
*
* Register Conventions
* a0 = argument - tag init value (data stored in bus/proc tags)
* a1 = argument - tag increment value
* a2 = argument - state init value (data stored in bus/proc state)
* a3 = argument - state increment value
* ta0 = bus tag address
* ta1 = proc tag address
* ta2 = bus state address
* ta3 = proc state address
* t0 = num of lines in gcache
* t1 = gcache line index
* t2 = argument - num of sets to initialize
* t3 = argument - first set to initialize
* t8 = scratch. Holds actual value in loop 2, and in error code
* t9 = scratch. Holds expected value in loop 2, and in error code
*
* v1 = argument - 0 to set tags, 1 to set and then read back and check their values
* gp = scratch
* ra = return address
* Note: this routine saves ra in SP_SAVE so that the routines that call
* this routien can use SP_RA to save their ra.
* ******************************************************************************/
LEAF(gcache_check_tags)
.set noreorder
DMTC1(ra, SP_SAVE)
DMTC1(v0, V0_SAVE)
SC_GET_NUM_LINES_IN_GCACHE(t0) # t0 = num of lines
DMFC1(v0, V0_SAVE)
/* *****************************************************************************
* Loop 1 is an outer loop that contains loops 2 and 3. We execute loop 1 once
* for each of the three sets: 0, 1, 2. Inside loop 1 we execute loop 2 for
* each line in the gcache, and then we execute loop 3 for each line in the
* gcache. Loop 2 writes values to the gcache tagram for the set we are
* working on and loop 3 reads back the tagram values and checks that they
* are correct.
*******************************************************************************/
1:
# ta0,ta1,ta2,ta3 = BB_BUSTAG_ADDR,BB_PTAG_E_ADDR,BB_BUSTAG_ST,BB_PTAG_E_ST
SC_TAGRAM_ADDR_INIT_FOR_SET(ta0, ta1, ta2, ta3, t3, v0, gp)
li t1, 0 # t1 = line index
andi a2, 0xfff # a2 = state init value, only 11:0 valid
/* *****************************************************************************
* Loop 2 runs through all lines in the gcache, for a single set, setting the
* bus tags, proc tags, bus state, proc state based on arguments a1, a1, a2, a3.
*******************************************************************************/
2:
sd a0, (ta0) # write gcache bus tag
daddu a0, a1 # increment tag by 1
sd a0, (ta1) # write gcache proc tag
daddu a0, a1 # increment tag by 1
li gp, 0x1f000 # bus state 'state write enable'
or t8, gp, a2
sd t8, (ta2) # write gcache bus state
daddu a2, a3 # increment state value by 1
andi a2, 0xfff # unnecessary?
dsll a2, 22
dli gp, 0x7c00000000 # proc state 'state write enable'
or t8, gp, a2
sd t8, (ta3) # write gcache proc state
dsrl a2, 22
daddu a2, a3 # increment state value by 1
andi a2, 0xfff # unnecessary?
SC_TAGRAM_ADDR_NEXT_LINE(ta0, ta1, ta2, ta3, gp)
daddiu t1, 1
bltu t1, t0, 2b
nop
/* **** Loop 2 END ******************************************************/
beq v1, r0, 4f # if argument v1 is 0, don't do check
nop
/* *****************************************************************************
* Loop 3 runs through all lines in the gcache, for a single set, and reads
* the bus tags, proc tags, bus state, proc state. For each datum read, it
* checks that the value is equal to the data that we stored in Loop 1.
*******************************************************************************/
SC_TAGRAM_ADDR_INIT_FOR_SET(ta0, ta1, ta2, ta3, t3, v0, gp)
li t1, 0 # t1 = line index
dmult t0, a1
mflo t8
dsll t8, 1
dsub a0, t8 # a0 = start data for bus/proc tags
dmult t0, a3
mflo t8
dsll t8, 1
dsub a2, t8 # a2 = start data for bus/proc state
3: /* **** Loop 3 LOOP *****************************************************/
ld t8, 0(ta0) # read bus tag
SC_TAG_BITS(t8, t8, gp)
SC_TAG_BITS_WITH_ADDR_BITS(t9, a0, ta0, gp)
bne t8, t9, 99f # branch on error
move gp, ta0
daddu a0, a1
ld t8, 0(ta1) # read even proc tag
SC_TAG_BITS(t8, t8, gp)
SC_TAG_BITS_WITH_ADDR_BITS(t9, a0, ta1, gp)
bne t8, t9, 99f # branch on error
move gp, ta1
daddu ta1, ta1, 0x80000 # read odd proc tag
ld t8, 0(ta1)
SC_TAG_BITS(t8, t8, gp)
SC_TAG_BITS_WITH_ADDR_BITS(t9, a0, ta1, gp)
bne t8, t9, 99f # branch on error
move gp, ta1
dsub ta1, ta1, 0x80000
daddu a0, a1
ld t8, 0(ta2)
SC_STATE_BITS(t8, t8, gp)
SC_STATE_BITS(t9, a2, gp)
bne t8, t9, 99f
move gp, ta2
daddu a2, a3
ld t8, 0(ta3)
SC_STATE_BITS(t8, t8, gp)
SC_STATE_BITS(t9, a2, gp)
bne t8, t9, 99f
move gp, ta3
daddu ta3, ta3, 0x80000 # read odd proc tag state
ld t8, 0(ta3)
SC_STATE_BITS(t8, t8, gp)
SC_STATE_BITS(t9, a2, gp)
bne t8, t9, 99f # branch on error
move gp, ta3
dsubu ta3, ta3, 0x80000
daddu a2, a3
SC_TAGRAM_ADDR_NEXT_LINE(ta0, ta1, ta2, ta3, gp)
daddu t1, 1
bltu t1, t0, 3b # loop through each line in gcache
nop
/* **** Loop 3 END ******************************************************/
4:
daddiu t3, 1
blt t3, t2, 1b # do outer loop for sets 0, 1, 2
nop
/* **** Loop 1 END ******************************************************/
li v0, 0
DMFC1(ra, SP_SAVE)
j ra
nop
99:
DMTC1(t1, T1_SAVE)
DMTC1(t3, T3_SAVE)
DMTC1(gp, GP_SAVE)
DMTC1(t9, T9_SAVE)
DMTC1(t8, T8_SAVE)
li v0, EVDIAG_SCACHE_TAG
DMFC1(ra, SP_SAVE)
j ra
nop
END(gcache_check_tags)
/* *****************************************************************************
* gcache_set_vsyn
*
* This routine is used by gcache_check_data to fix up the virtual synonym bits
* of the G$ bus and processor state. All it does is go through every tag in
* the g$, read the state value and replace the virtual synonm bits of the
* value read with new virtual synonym bits. The new virtual synonm bits
* are chosen by using the address corresponding to the address of the
* first double word of the line. For example:
* line address vsyn
* 0 0x0 0
* 1 0x200 0
* 2 0x400 0
* ... ... ...
* 8 0x1000 1
* 15 0x1e00 1
* ... ... ...
* 16 0x2000 2
* ... ... ...
*
* This routine takes two arguments:
* t2: number of sets to initialize (does not change during execution)
* t3: first set index (gets changed during execution)
*********************************************************************************/
LEAF(gcache_set_vsyn)
.set noreorder
DMTC1(ra, SP_SAVE)
SC_GET_NUM_LINES_IN_GCACHE(t0) # t0 = num of lines
/* *****************************************************************************
* Loop 1 is an outer loop that contains loop 2. We execute loop 1 once
* for each of the three sets: 0, 1, 2. We execute loop 2 once for each line
* in the gcache. Loop 2 reads the bus tag state bits, OR's in the virtual
* synonym, then writes them back. Then it does the same for the proc tag state
* bits. The virtual syno
*******************************************************************************/
li v0, 0x1f000 # bus state 'state write enable'
dli v1, 0x7c00000000 # proc state 'state write enable'
1:
li a0, 0
# ta0,ta1,ta2,ta3 = BB_BUSTAG_ADDR,BB_PTAG_E_ADDR,BB_BUSTAG_ST,BB_PTAG_E_ST
SC_TAGRAM_ADDR_INIT_FOR_SET(ta0, ta1, ta2, ta3, t3, a0, gp)
li t1, 0 # t1 = line index
2: /* **** Loop 1 LOOP *****************************************************/
dsll t9, t1, 9
andi t9, t9, 0xf000
dsrl t9, t9, 4 # r9 contains virtual synonym in bits 11:8
ld t8, (ta2)
andi t8, t8, 0xf0ff
or t8, t8, t9
or t8, t8, v0 # Make bus state dirty & vsyn bits writable!
sd t8, (ta2)
ld t8, (ta3)
andi t8, t8, 0xf0ff
or t8, t8, t9
dsll t8, t8, 22
or t8, t8, v1 # Make tag state dirty & vsyn bits writable!
sd t8, (ta3)
SC_TAGRAM_ADDR_NEXT_LINE(ta0, ta1, ta2, ta3, gp)
daddiu t1, t1, 1
bltu t1, t0, 2b
nop
/* **** Loop 1 END ******************************************************/
daddiu t3, 1
blt t3, t2, 1b # do outer loop for sets 0, 1, 2
nop
/* **** Loop 0 END ******************************************************/
li v0, 0
DMFC1(ra, SP_SAVE)
j ra
nop
END(gcache_set_vsyn)
/* ******************************************************************************
* gcache_print_tag_error_and_return
*
* This routine is called from the gcache checking routines after they have
* printed out all of their detailed information about a gcache check that
* failed. This routine prints out a more general message telling what type
* of failure it was (bus tag, processor even tag, processor odd tag), what
* chip, what cpu number, and what slot. It assumes that at entry ra
* contains the return address, v0 contains the return code, and GP_SAVE contais
* the address of the failing location in the tagram. Currently this routine
* is called with a 'j', rather than a 'jalr'. So, if x() calls y() and
* y() calls gcache_print_tag_error_and_return(), when we return from
* gcache_print_tag_error_and_retur() we return to routine x.
******************************************************************************/
LEAF(gcache_print_tag_error_and_return)
.set noreorder
DMTC1(ra, RA_SAVE) # save ra so we don't overwrite it during printing
DMTC1(v0, V0_SAVE) # save v0 so we don't overwrite it during printing
EV_GET_SPNUM(ta0, ta1) # t0 = slot, t1 = proc number
DMFC1(gp, GP_SAVE) # gp contains the address that failed
DMTC1(ta0, TA0_SAVE) # print macro takes FP reg as arg, so save slot in fpreg
li a0, 0x00100000
and a4, a0, gp
bne a4, r0, print_proc
nop
print_bus:
bne ta1, r0, print_bus_cpu1
nop
print_bus_cpu0:
ERROR_MSG_FPREG("*** Bus tag failure on chip #N9K7, cpu 0, slot ", TA0_SAVE)
j print_done
nop
print_bus_cpu1:
ERROR_MSG_FPREG("*** Bus tag failure on chip #N9K7, cpu 1, slot ", TA0_SAVE)
j print_done
nop
print_proc:
li a0, 0x00080000
and a4, a0, gp
bne a4, r0, print_proc_odd
nop
print_proc_even:
bne ta1, r0, print_proc_even_cpu1
nop
print_proc_even_cpu0:
ERROR_MSG_FPREG("*** Processor even tag failure on chip #JOH7, cpu 0, slot ", TA0_SAVE)
j print_done
nop
print_proc_even_cpu1:
ERROR_MSG_FPREG("*** Processor even tag failure on chip #JOH7, cpu 1, slot ", TA0_SAVE)
j print_done
nop
print_proc_odd:
bne ta1, r0, print_proc_odd_cpu1
nop
print_proc_odd_cpu0:
ERROR_MSG_FPREG("*** Processor odd tag failure on chip #JOJ5, cpu 0, slot ", TA0_SAVE)
j print_done
nop
print_proc_odd_cpu1:
ERROR_MSG_FPREG("*** Processor odd tag failure on chip #JOJ5, cpu 1, slot ", TA0_SAVE)
j print_done
nop
print_done:
DMFC1(ra, RA_SAVE)
DMFC1(v0, V0_SAVE)
j ra
nop
END(gcache_print_tag_error_and_return)
/* pon_validate_scache_d
* Initialize GCache Tag and State RAMs where D-cache mapped to dirty
* exclusive.
* GCached should be in a state like pon_initialize_scache. i.e. everything
* invalid and set 3 tags are those of BOOT PROM addresses.
*
* The registers being used and their usage are as follows:
*
* t0: loop count
* t1: offset for each index
* t2: base address of bus tag state
* t3: base address of proc tag state
* ta0: bus tag state to write
* ta1: proc tag state to write
* ta2: bus/proc tag tag-addr to write
* ta3: address of bus tag addr
* v1: address of proc tag addr
*
* SAQs should not have any pending cached-write to G-cache when this
* routine is called.
* (flush_SAQueue can be called prior to pon_initialize_scache to flush
* pending G-cache write's if any in SAQs.)
*/
#define GTAG_TG_DC (((POD_STACKADDR >> 20) & 0xfffff) << 20)
#define BTAG_ST_DC_EX (((0xf000 & POD_STACKADDR) >> 4) | 0x1f0aa)
#define PTAG_ST_DC_DE (((0xf000 & POD_STACKADDR) << 18) | 0xfc2a800000)
/* Shift right by 6 b/c we shift right by 9 to get the g$ index, then
shift left by 3 to multiply the g$ index by 8 to get index into
tag ram
*/
#define GTAG_DC_S_OFF (((POD_STACKADDR & 0xfc000) >> 6) | 0x30000)
/* this GTAG_DC_S_OFF is set3 with virtual synonym 1100 mmeory
mapped address, every 128 entries increment one v.s value, ie.
advance 0300 address, we use 16K page size, each scache tag has
2048 entries, virtual M. value range from 0-15, */
LEAF(pon_validate_scache_d)
.set noreorder
dli t0, CC_ADDR(0x1fc0f000)
ld t1, 0(t0)
ld t1, 0(t0)
li t0, 32
li t1, GTAG_DC_S_OFF # Start index of G-cache tag to mapped D-cache
dli t2, BB_BUSTAG_ADDR # bus tag address base
dli t3, BB_PTAG_E_ADDR # proc tag address base
dli t8, BB_BUSTAG_ST # bus tag state base
dli t9, BB_PTAG_E_ST # proc tag state base
dli ta0, BTAG_ST_DC_EX # bus tag state to map dcache exclusive
# sectors state exclusive
dli ta1, PTAG_ST_DC_DE # proc tag state to map dcache dirty exclusive'
#dli ta2, GTAG_TG_DC # bus/proc tag tag-addr to map dcache
dli ta2, POD_STACKADDR # bus/proc tag tag-addr to map dcache
dli a0, POD_STACKADDR
dli a1, 0xfc2a800000
dli a2, 0x1f0aa
1:
daddu ta3, t2, t1 # address of bus tag addr
daddu v1, t3, t1 # address of proc tag addr
sd ta2, 0(ta3) # write to bus tag addr
sd ta2, 0(v1) # write to proc tag addr (even & odd)
daddu ta3, t8, t1 # address of bus tag state
daddu v1, t9, t1 # address of proc tag state
sd ta0, 0(ta3) # write to bus tag state
sd ta1, 0(v1) # write to proc tag state
addi t0, -1
daddiu a0, 0x200 # scache line size
and a3, a0, 0xf000 # recompute bus virtual synonym
dsrl a3, 4
or ta0, a3, a2
and a3, a0, 0xf000 # recompute processor virtual synonym
dsll a3, 18
or ta1, a3, a1
daddu ta2, 0x200
bgt t0, zero, 1b # Done with all 32 entries (mapped into 16KB)?
addi t1, t1, 8 # (BD) next index of G-cache tag to mapped D-cache
j ra
nop
.set reorder
END(pon_validate_scache_d)
/*
* pon_fix_dcache_parity()
* put dcache into useful state for power-on diagnostics or
* for running pon command monitor.
* Secondary (G-cache) tags where D-cache mapped are set to dirty exclusive
* (D-cache may not be mapped to addresses congrurent to BOOT PROM.)
* all PD tags have correct parity.
* all PD lines marked exclusive.
* all PD data is initialized with correct parity.
* Do so without causing bus cycles.
* Does not use a stack. Cannot be called from C, since it does
* not respect register conventions.
* Note that this routine is level-1 in the calling chain.
*/
LEAF(pon_fix_dcache_parity)
.set noreorder
move Ra_save1,ra
# mark each line exclusive using TFP store-tag
jal pon_setup_stack_in_dcache
nop
# mark each line exclusive in G-cache
jal pon_validate_scache_d
nop
# now, since all lines valid and exclusive (ensuring no memory
# fetches as long as we hit both caches), initialize the data
# in order calculate correct parity and set the WB bit for each
# line. First, get dcache size.
# Because the data is bogus, set SR to ignore parity/ecc errors.
jal get_dcachesize
nop
DMFC0(t3, C0_SR)
dli t1, POD_SR
DMTC0(t1, C0_SR)
# store to each line, t2 has loop termination
dli t1, POD_STACKADDR
daddu t2, t1, v0 # t2 is loop termination
# (stack address + length)
1:
sd zero,0(t1)
daddi t1, 8 # increment to next doubleword
bltu t1, t2, 1b
DMTC0(t3, C0_SR)
j Ra_save1 # Jump to saved return address
nop
END(pon_fix_dcache_parity)
/* Two icaches line, each instruction takes 4 bytes, 16 instructions
takes 64 bytes. Each icache line takes 32 bytes.
Two icache lines operation add 0xffff to register,ie, signed
extended become add -1 to the register, after 32 icache lines
operation we add substract 256 from the register */
#define TWO_LINES_TCODE \
addiu ta2, s5, 0x0001; \
addiu s5, ta2, 0x0002; \
addiu ta2, s5, 0x0004; \
addiu s5, ta2, 0x0008; \
addiu ta2, s5, 0x0010; \
addiu s5, ta2, 0x0020; \
addiu ta2, s5, 0x0040; \
addiu s5, ta2, 0x0080; \
addiu ta2, s5, 0x0100; \
addiu s5, ta2, 0x0200; \
addiu ta2, s5, 0x0400; \
addiu s5, ta2, 0x0800; \
addiu ta2, s5, 0x1000; \
addiu s5, ta2, 0x2000; \
addiu ta2, s5, 0x4000; \
addiu s5, ta2, 0x8000
/* Four icache lines per gcache line (128 bytes) */
#define FOUR_LINES_TCODE \
TWO_LINES_TCODE; \
TWO_LINES_TCODE
/* 32 icache lines per 1k */
#define THIRTYTWO_LINES_TCODE \
FOUR_LINES_TCODE; FOUR_LINES_TCODE; \
FOUR_LINES_TCODE; FOUR_LINES_TCODE; \
FOUR_LINES_TCODE; FOUR_LINES_TCODE; \
FOUR_LINES_TCODE; FOUR_LINES_TCODE \
#define ICACHE_LINE_CODE \
addu zero, zero, zero; /* 0 */ \
addu zero, zero, zero; /* 4 */ \
addu zero, zero, zero; /* 8 */ \
addu zero, zero, zero; /* 12 */ \
addu zero, zero, zero; /* 16 */ \
addu zero, zero, zero; /* 20 */ \
addu zero, zero, zero; /* 24 */ \
addu zero, zero, zero /* 28 */
/* Four icache lines per gcache line (128 bytes) */
#define FOUR_LINES_CODE \
ICACHE_LINE_CODE; \
ICACHE_LINE_CODE; \
ICACHE_LINE_CODE; \
ICACHE_LINE_CODE \
/* 32 icache lines per 1k */
#define THIRTYTWO_LINES_CODE \
FOUR_LINES_CODE; FOUR_LINES_CODE; \
FOUR_LINES_CODE; FOUR_LINES_CODE; \
FOUR_LINES_CODE; FOUR_LINES_CODE; \
FOUR_LINES_CODE; FOUR_LINES_CODE \
/* Initialize DCache by invalidating it. DCache is 16KB, with 32Byte line,
* 28 bits Tag + 1 bit Exclusive + 8 bits Valid + 32 Bytes Data
* Need two consecutive writes to half-line boundaries to clear Valid bits
* for each line.
*/
LEAF(pon_invalidate_dcache)
.set noreorder
move t3, ra
li v1, 16 # size of the half of Dcache line
jal get_dcachesize
nop
# v1: half line size, v0: cache size to be initialized
dli t1,POD_STACKADDR # Starting address for initializing
# Dcache
daddu t2, t1, v0 # t2: loop terminator
# for each cache line:
# mark it invalid
1:
DMTC0(t1,C0_BADVADDR)
DMTC0(zero,C0_DCACHE) # clear all (4) Valid bits
dctw # write to the Dcache Tag
ssnop; ssnop; ssnop # pipeline hazard prevention
.set reorder
daddu t1, v1 # increment to next half-line
bltu t1, t2, 1b # t2 is termination count
move v0, zero
j t3
END(pon_invalidate_dcache)
LEAF(pon_invalidate_IDcaches)
.set noreorder
.align 5 # first invalidate the icache
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 2k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 4k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 6k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 8k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 10k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 12k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 14k */
THIRTYTWO_LINES_CODE; THIRTYTWO_LINES_CODE /* 16k */
j pon_invalidate_dcache # now go do the dcache
nop
END(pon_invalidate_IDcaches)
/*
* pon_test_Icaches
* icache is 16KB, 512 cache lines, each line with 32 bytes.
* icache test before Chandra mode.
* use r10 (ta2) and r21 (s5), their binary representations (01010 and
* 10101) are opposites.
*
*/
LEAF(pon_test_Icaches)
.set noreorder
move t3, ra
dli ta2, 0
dli s5, 0
.align 5 # first invalidate the icache
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 2k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 4k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 6k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 8k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 10k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 12k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 14k */
THIRTYTWO_LINES_TCODE; THIRTYTWO_LINES_TCODE /* 16k */
dli ta2, 0xffffffffffffff00
bne s5, ta2, icache_fail
nop
j t3
nop
icache_fail:
j flash_cc_leds
ori a0, zero, FLED_ICACHE_FAIL
j t3
nop
END(pon_test_Icaches)
/*
* dcache_tag
* basic dcache tag ram test
*/
/* #define DC_TAG_ADDRESS CC_ADDR(0x1fcfc000) */
#define DC_TAG_ADDR_START CC_ADDR(0x1cc00000)
#ifdef SABLE
#define DC_TAG_ADDR_END CC_ADDR(0x1cc0ffff)
#else
#define DC_TAG_ADDR_END CC_ADDR(0x1cc3ffff)
#endif
#define VALID_EX_BIT_MASK 0x780000000000800
LEAF(dcache_tag)
.set noreorder
move Ra_save1, ra
/*
li v1, 16 # size of the half of Dcache line
# each cache tagram entry contains
# 4 64 bit data
jal get_dcachesize # 16k bytes
nop
*/
# for each cache line in cache tag ram fill up the tag
# with various tag patterns and do cache tag write
# do this for whole 16kB Dcache tag
.set noreorder
1:
dli t1, DC_TAG_ADDR_START
dli t2, DC_TAG_ADDR_END
2:
DMTC0(t1,C0_BADVADDR)
dli s5, 0x7777777777777777
dli s4, 0xfffffff000
and s5, s4
dli s4, VALID_EX_BIT_MASK
or s5, s4
DMTC0(s5, C0_DCACHE)
dctw # Dcache Tag Write
ssnop; ssnop; ssnop # pipeline hazard prevention
daddu t1, 0x10 # increment to next half-line
# increment by 16
bltu t1, t2, 2b # t2 is termination count
ssnop
nop
# for each cache line in cache tag ram do cache tag
# read and compare the result, do this for whole
# 16KB cache tag
dli t1,DC_TAG_ADDR_START # Starting address DC tag ram
dli t2, DC_TAG_ADDR_END
3:
DMTC0(t1,C0_BADVADDR)
dctr # Dcache Tag Read
ssnop;ssnop
DMFC0(t3, C0_DCACHE) # Read from Dcache register
bne t3, s5, 99f
ssnop
daddu t1, 0x10 # increment to next half-line
# increment by 16
bltu t1, t2, 3b # t2 is termination count
ssnop
nop
.set reorder
# done with no error
dla a0, dcache_tag_pass # dcache tagram pass msg
jal pod_puts
move v0, zero # zero retn -> no error
j Ra_save1 # Jump to saved ra
99:
.set noreorder
dla a0, dcache_tag_fail # dcache tagram fail msg
jal pod_puts
nop
move a0,t1
jal pod_puthex # output dcache tag entry
nop
dla a0, crlf
jal pod_puts
nop
.set reorder
li v0, EVDIAG_DCACHE_TAG
j Ra_save1 # Jump to saved ra
END(dcache_tag)
.data
dcache_tag_pass:
.asciiz "\Dcache tag test pass \r\n"
dcache_tag_fail:
.asciiz "\Dcache tag test failed at entry "
tag_pattern:
.word 0xaaaaaaaa, 0x55555555, 0, 0xffffffff
.text
/* Initialize Store Address Queue by issuing (SAQ_DEPTH) Even and
* (SAQ_DEPTH) Odd uncached-writes to two even and odd aligned
* local registers - 2 unused local CC register addresses used
*/
LEAF(flush_SAQueue)
.set noreorder
dli t0, SAQ_INIT_ADDRESS # address to start (writing) at
li t1, SAQ_DEPTH # number of entries in the queue
1:
sd zero, 0(t0) # write (even) 8 bytes
sd zero, 8(t0) # write (odd) 8 bytes
addi t1, -1
bnez t1, 1b
nop
j ra
nop
.set reorder
END(flush_SAQueue)
/*
* Return the line size of the primary dcache
*/
LEAF(get_dcacheline)
.set noreorder
DMFC0(v0, C0_CONFIG)
.set reorder
and v0, CONFIG_DB
beq v0, zero, 1f
li v0, 32
j ra
1:
li v0, 16
j ra
END(get_dcacheline)
/*
* return the size of the primary data cache
*/
LEAF(get_dcachesize)
.set noreorder
DMFC0(t0,C0_CONFIG)
and t0,CONFIG_DC
srl t0,CONFIG_DC_SHFT
addi t0,MIN_CACH_POW2
li v0,1
sll v0,t0
j ra
nop
END(get_dcachesize)
/*
* Return the line size of the primary icache
*/
LEAF(get_icacheline)
.set noreorder
DMFC0(v0, C0_CONFIG)
and v0, CONFIG_IB
beq v0, zero, 1f
li v0, 16 #this is reversed as Everest
j ra
nop
1:
li v0, 32
j ra
nop
END(get_icacheline)
/*
* return the size of the primary instruction cache
*/
LEAF(get_icachesize)
.set noreorder
DMFC0(t0,C0_CONFIG)
and t0,CONFIG_IC
srl t0,CONFIG_IC_SHFT
/* TFP encodes chip revision number in IC field for some revs of
* chip.
*/
DMFC0(t2,C0_PRID)
andi t2, t2, 0xff
bne t2, zero, 1f # if revision non-zero, no encoding
nop
/* We've hit encoded case (PRID == 0)
*/
beq t0, zero, 1f # let encode of zero
li t0, 0x04 # be a 32K icache
li t0, 0x03 # all others be 16K icache
1: addi t0,MIN_CACH_POW2-1
li v0,1
sll v0,t0
j ra
nop
END(get_icachesize)
/*
* check_scachesize
* return the size of the secondary cache
*
* Assume the gcache tag ram size options are 1,2,4,8,& 16 MB.
* By loading the following data in the order shown:
*
* Write Read Read Read Read Read
* Addr: Data: 16MB 8MB 4MB 2MB 1MB
* index
* 0 f f 7 3 1 0
* 512 e e 6 2 0 0
* 1024 d d 5 1 1 0
* 1536 c c 4 0 0 0
* 2048 b b 3 3 1 0
* 2560 a a 2 2 0 0
* 3072 9 9 1 1 1 0
* 3584 8 8 0 0 0 0
* 4096 7 7 7 3 1 0
* 4608 6 6 6 2 0 0
* 5120 5 5 5 1 1 0
* 5632 4 4 4 0 0 0
* 6144 3 3 3 3 1 0
* 6656 2 2 2 2 0 0
* 7168 1 1 1 1 1 0
* 7680 0 0 0 0 0 0
*
* If the data is then read back (after all data has been written) it
* should match one of the patterns in the five read columns. The
* column it matches gives the size of the cache.
* we need to check the bus tag ram, odd tag ram and even tag ram
* and make sure they are consistent.
*
* v0: return scache size
*/
LEAF(check_scachesize)
.set noreorder
move s3, ra
#if SABLE
j s3
li v0, 4 # 4MB (BDSLOT)
#endif
dli t0, 0x9000000018080000 # uncacheable addr
ld t1, 0(t0)
ld t1, 0(t0)
/* Max GCache tag ram size is 16MB. */
li t0, 0x1fff # 8192 entries,indeces loop terminator,max 16MB
li t1, 0 # t1 indicates which index
li s5, 512 # 512 entries for one value
li s6, 16 # 16 possible values
1:
dli v0, BB_BUSTAG_ADDR # bus tag address base
dli v1, BB_PTAG_E_ADDR # proc tag address base
dli t8, BB_BUSTAG_ST # bus tag state base
dli t9, BB_PTAG_E_ST # proc tag state base
dli a1, BTAG_ST_WRITE # set dirty enable, virtual synonym
# enable and state exclusive
dli a2, PTAG_ST_WRITE # proc tag state init value
dla s1, tag_value
lw ta0, 0(s1)
and ta0, 0xfffff00000 # data to be written into set 0 of bus & proc
# tag addr. (i.e. start from set 0)
2:
sll t2, t1, 3 # shift index count into appropriate position
or t3, v0, t2 # address of bus tag addr.
or ta1, v1, t2 # address of proc tag addr.
or ta2, t8, t2 # address of bus tag state
or ta3, t9, t2 # address of proc tag state
/* 4 write operations */
sd ta0, 0(t3) # write into bus tag addr.
sd ta0, 0(ta1) # write into proc tag addr.
sd a1, 0(ta2) # write into bus tag state
sd a2, 0(ta3) # write into proc tag state
subu s5, 1
daddu t1, 1
bnez s5, 2b
nop
daddiu s1, 4
lw ta0, 0(s1)
and ta0, 0xfffff00000 # data to be written into set 0 of bus & proc
li s5, 512
subu s6, 1
bnez s6, 2b
nop
# now read back the data and compare the value for addr index 0
# if read back 0xf, report 16mb
# if read back 0x7, report 8mb
# if read back 0x3, report 4mb
# if read back 0x1, report 2mb
# if read back 0x0, report 1mb
dli t0, BB_BUSTAG_ADDR
ld a0, 0(t0) # read back from bus tag ram
srl a0, 20
daddiu a0, 1 # gcache bus tag ram size
dli t0, BB_PTAG_E_ADDR
ld a1, 0(t0) # read back from even tag ram
srl a1, 20
daddiu a1, 1 # gcache even tag ram size
# read back fom odd ram tag
dli t0, BB_PTAG_O_ADDR
ld a2, 0(t0) # read back from odd tag ram
srl a2, 20
daddiu a2, 1 # gcache odd tag ram size
# compare 3 tag ram size, they must be the same, if not
# report error
bne a0, a1, 99f
nop
bne a0, a2, 99f
nop
bne a1, a2, 99f
nop
# check scache tag size is 1,2,4,8,or 16 only
dla t0, scache_tag_size
li t2, 5
20:
lw t1, 0(t0)
bne a0, t1, 30f
nop
li t2, 1
move v0, a0
j s3
nop
30:
daddiu t0, 4
subu t2, 1
bltz t2, 98f
nop
bnez t2, 20b
nop
j s3
98:
jal flash_cc_leds
li a0, FLED_SCACHE_SIZE_WRONG # BDSLOT
99:
jal flash_cc_leds
li a0, FLED_SCACHE_SIZE_INCONSISTENT # BDSLOT
END(check_scachesize)
.data
tag_value:
.word 0xf00000,0xe00000,0xd00000,0xc00000,0xb00000,0xa00000,0x900000
.word 0x800000,0x700000,0x600000,0x500000,0x400000, 0x300000,0x200000
.word 0x100000,0
scache_tag_size:
.word 1,2,4,8,16
.text
/*
* return the size of the secondary cache as stored in the gcache size
* register
*/
LEAF(read_scachesize)
#ifdef SABLE
li v0, 0x10000
j ra
nop
#endif
.set noreorder
EV_GET_SPNUM(t0, t1) # t0 gets slot
# t1 gets proc. number
EV_GET_PROCREG(t0, t1, EV_CACHE_SZ, t0)
andi t0, 0x1f
li t1, 16 # make sure it's in the range 1-16
ble t0, zero, 99f
nop
bgt t0, t1, 99f
nop
sll v0, t0, 20 # 1 - 1MB, 2 - 2MB, 4 - 4MB etc
b 1f
nop
99:
li t0, 4 # default to 4 mb
sll v0, t0, 20 # 1 - 1MB, 2 - 2MB, 4 - 4MB etc
1:
j ra
nop
.set reorder
END(read_scachesize)
/* pon_setup_stack_in_dcache: set all PD lines to exclusive
* state, with addrs beginning at POD_STACKADDR and rising
* contiguously for 'dcachesize'. All further cached-write
* within this range will now write-through without genernating
* a D-cache miss op to G-pipe. When G-pipe is properly
* initialized with exclusive states for all lines, no memory
* op will be generated by G-pipe.
*/
#define DCACHE_EXCLUSIVE 0x0780000000000800
LEAF(pon_setup_stack_in_dcache)
.set noreorder
move t3, ra
li v1, 16 # size of the half of Dcache line
jal get_dcachesize
nop
# v1: half line size, v0: cache size to be initialized
dli t1,POD_STACKADDR # Starting address for initializing
# Dcache
daddu t2, t1, v0 # t2: loop terminator
dli ta0,DCACHE_EXCLUSIVE # ta0: Mask to set dcache line valid exclusive
# for each cache line:
# mark all word exclusive
1:
or ta1, t1, ta0 # Set all valid (4) and exclusive (1) bits
DMTC0(t1,C0_BADVADDR)
DMTC0(ta1,C0_DCACHE) # Setup D-cache register
dctw # write to the Dcache Tag
ssnop; ssnop; ssnop # pipeline hazard prevention
.set reorder
daddu t1, v1 # increment to next half-line
bltu t1, t2, 1b # t2 is termination count
j t3
END(pon_setup_stack_in_dcache)
/* ******************************************************************************
* gcache_print_data_error_and_return
*
* This routine is called from the gcache_check_data routines after they have
* printed out all of their detailed information about a gcache data ram
* check that failed. This routine prints out a specific SIMM location failure
* High Odd, High Even, Low Odd or Low Even).
* When bit 3 of physical address set 0, it's even SIMM. When bit 3 of
* physical address set 1, it's odd SIMM. If the data low 32 bit doesn't
* match it's LOW SIMM, if the data hight 32 bit doesn't match it's HIGH
* SIMM. Following are the actual SIMM module location on the board.
*
* CPU0 CPU1
* ------------
* Odd Low SIMM location N6H1 G6H1
* Odd High SIMM Location N6G7 G6G7
* Even Low SIMM Location N6F9 G6G9
* Even High SIMM Location N6G3 G6G3
*
******************************************************************************/
LEAF(gcache_print_data_error_and_return)
.set noreorder
DMTC1(ra, RA_SAVE) # save ra so we don't overwrite it during printing
DMTC1(v0, V0_SAVE) # save v0 so we don't overwrite it during printing
EV_GET_SPNUM(ta0, ta1) # ta0 = slot, ta1 = proc number
DMFC1(gp, GP_SAVE) # gp contains the address that failed
DMFC1(s5, A1_SAVE) # s5 contains the actual data read back
li a0, 8 # check bit 3 of physical address.
and s6, a0, gp
bne s6, r0, odd_simm # bit 3 set to 1, it's in odd SIMM
nop
even_simm:
and s6, gp, 0xffffffff # check low 32 bit data match
and t3, s5, 0xffffffff
bne s6, t3, even_low_simm_fail
nop
4:
dli s6, 0xffffffff00000000
and s6, gp, s6 # check high 32 bit data match
and t3, s5, s6
bne s6, t3, even_high_simm_fail
nop
j print_done2
odd_simm:
and s6, gp, 0xffffffff # check low 32 bit data match
and t3, s5, 0xffffffff
bne s6, t3, odd_low_simm_fail
nop
5:
dli s6, 0xffffffff00000000
and s6, gp, s6 # check high 32 bit data match
and t3, s5, s6
bne s6, t3, odd_high_simm_fail
nop
j print_done2
odd_low_simm_fail:
bne ta1, r0, odd_low_cpu1
nop
odd_low_cpu0:
ERROR_MSG("*** Odd Low SIMM failure on cpu0 location N6H1\r\n")
b 5b
nop
odd_low_cpu1:
ERROR_MSG("*** Odd Low SIMM failure on cpu1 location G6H1\r\n")
b 5b
nop
odd_high_simm_fail:
bne ta1, r0, odd_high_cpu1
nop
odd_high_cpu0:
ERROR_MSG("*** Odd High SIMM failure on cpu0 location N6G7\r\n")
j print_done2
odd_high_cpu1:
ERROR_MSG("*** Odd High SIMM failure on cpu1 location G6G7\r\n")
j print_done2
even_low_simm_fail:
bne ta1, r0, even_low_cpu1
nop
even_low_cpu0:
ERROR_MSG("*** Even Low SIMM failure on cpu0 location N6F9\r\n")
b 4b
nop
even_low_cpu1:
ERROR_MSG("*** Even Low SIMM failure on cpu1 location G6G9\r\n")
b 4b
nop
even_high_simm_fail:
bne ta1, r0, even_high_cpu1
nop
even_high_cpu0:
ERROR_MSG("*** Even High SIMM failure on cpu0 location N6G3\r\n" )
j print_done2
even_high_cpu1:
ERROR_MSG("*** Even High SIMM failure on cpu1 location G6G3\r\n")
j print_done2
print_done2:
DMFC1(ra, RA_SAVE)
DMFC1(v0, V0_SAVE)
j ra
nop
END(gcache_print_data_error_and_return)