diff options
Diffstat (limited to 'libgloss/mips/boot')
-rw-r--r-- | libgloss/mips/boot/corecheck_predef.S | 227 | ||||
-rw-r--r-- | libgloss/mips/boot/init_caches.S | 178 | ||||
-rw-r--r-- | libgloss/mips/boot/init_caches_predef.S | 183 | ||||
-rw-r--r-- | libgloss/mips/boot/init_cm3l2.S | 137 | ||||
-rw-r--r-- | libgloss/mips/boot/init_cm3l2_predef.S | 117 | ||||
-rw-r--r-- | libgloss/mips/boot/init_cp0.S | 105 | ||||
-rw-r--r-- | libgloss/mips/boot/init_cp0_predef.S | 131 | ||||
-rw-r--r-- | libgloss/mips/boot/init_l23caches.S | 141 | ||||
-rw-r--r-- | libgloss/mips/boot/init_l23caches_predef.S | 161 | ||||
-rw-r--r-- | libgloss/mips/boot/init_tlb.S | 348 | ||||
-rw-r--r-- | libgloss/mips/boot/init_tlb_predef.S | 149 | ||||
-rw-r--r-- | libgloss/mips/boot/predef.h | 153 | ||||
-rw-r--r-- | libgloss/mips/boot/reset.S | 233 | ||||
-rw-r--r-- | libgloss/mips/boot/reset_predef.S | 261 |
14 files changed, 2524 insertions, 0 deletions
diff --git a/libgloss/mips/boot/corecheck_predef.S b/libgloss/mips/boot/corecheck_predef.S new file mode 100644 index 0000000..62f1b2c --- /dev/null +++ b/libgloss/mips/boot/corecheck_predef.S @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* Config 0 has some RO fields. */ +#if defined (C0_CONFIG0_VALUE) +#define C0_CONFIG0_RO (CFG0_M | CFG0_AT_MASK | CFG0_AR_MASK | \ + CFG0_MT_MASK | CFG0_VI) +#define C0_CONFIG0_EXP (C0_CONFIG0_RO & C0_CONFIG0_VALUE) +#endif + +/* Config 1 has no RW fields. */ +#if defined(C0_CONFIG1_VALUE) +#define C0_CONFIG1_RO (0xffffffff) +#define C0_CONFIG1_EXP (C0_CONFIG1_RO & C0_CONFIG1_VALUE) +#endif + +/* Config 2 has 2 RW fields. */ +#if defined(C0_CONFIG2_VALUE) +#define C0_CONFIG2_RO ~(CFG2_TU_MASK | CFG2_SU_MASK) +#define C0_CONFIG2_EXP (C0_CONFIG2_RO & C0_CONFIG2_VALUE) +#endif + +/* Config 3 has only 1 R/W bit (microMIPS on exception) */ +#if defined(C0_CONFIG3_VALUE) +#define C0_CONFIG3_RO (~CFG3_IOE) +#define C0_CONFIG3_EXP (C0_CONFIG3_RO & C0_CONFIG3_VALUE) +#endif + + +/* Config 4 has only 1 field R/W (FTLB page size) */ +#if defined(C0_CONFIG4_VALUE) +#define C0_CONFIG4_RO (~CFG4_FTLBPS_MASK) +#define C0_CONFIG4_EXP (C0_CONFIG4_RO & C0_CONFIG4_VALUE) +#endif + +/* Config 5 has only a few fields and some of them are RO. */ +#if defined(C0_CONFIG5_VALUE) +#define C0_CONFIG5_RO (CFG5_MVH | CFG5_LLB | CFG5_MRP | CFG5_NF) +#define C0_CONFIG5_EXP (C0_CONFIG5_RO & C0_CONFIG5_VALUE) +#endif + +#if defined(C0_CMGCRBASE_VALUE) +#define C0_CMGCRBASE_ADDR ((C0_CMGCRBASE_VALUE << 4) | (0xb << 28)) +#define C0_CMGCRBASE_RO (0xffffffff) +#define C0_CMGCRBASE_EXP C0_CMGCRBASE_VALUE +#endif + +/* GCR L2 config has REG_EXISTS and L2 config as readonly nozero fields. */ +#if defined(GCR_L2_CONFIG) +#define GCR_L2_CONFIG_RO ((1<<31) | ((1<<16) - 1)) +#define GCR_L2_CONFIG_EXP GCR_L2_CONFIG_VALUE +#endif + +LEAF(__core_check) + /* + * Compare the expected value to the RO fields + * of the config register + */ +#if defined(C0_CONFIG0_VALUE) + li t0, C0_CONFIG0_EXP + li t1, C0_CONFIG0_RO + mfc0 t3, C0_CONFIG + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG1_VALUE) + li t0, C0_CONFIG1_EXP + li t1, C0_CONFIG1_RO + mfc0 t3, C0_CONFIG1 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG2_VALUE) + li t0, C0_CONFIG2_EXP + li t1, C0_CONFIG2_RO + mfc0 t3, C0_CONFIG2 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG3_VALUE) + li t0, C0_CONFIG3_EXP + li t1, C0_CONFIG3_RO + mfc0 t3, C0_CONFIG3 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG4_VALUE) + li t0, C0_CONFIG4_EXP + li t1, C0_CONFIG4_RO + mfc0 t3, C0_CONFIG4 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG5_VALUE) + li t0, C0_CONFIG5_EXP + li t1, C0_CONFIG5_RO + mfc0 t3, C0_CONFIG5 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CMGCRBASE_VALUE) + li t0, C0_CMGCRBASE_EXP + li t1, C0_CMGCRBASE_RO + mfc0 t3, C0_CMGCRBASE + and t2, t1, t3 + bne t2, t0, 1f +#if defined(GCR_L2_CONFIG_VALUE) + li t0, GCR_L2_CONFIG_EXP + li t1, GCR_L2_CONFIG_RO + li t2, C0_CMGCRBASE_ADDR + lw t3, GCR_L2_CONFIG(t2) + and t2, t1, t3 + bne t2, t0, 1f +#endif +#endif + +#if defined(C0_WATCHHI_VALUE) + mfc0 t0, C0_WATCHHI, 0 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI1_VALUE) + mfc0 t0, C0_WATCHHI, 1 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI1_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI2_VALUE) + mfc0 t0, C0_WATCHHI, 2 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI2_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI3_VALUE) + mfc0 t0, C0_WATCHHI, 3 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI3_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI4_VALUE) + mfc0 t0, C0_WATCHHI, 4 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI4_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI5_VALUE) + mfc0 t0, C0_WATCHHI, 5 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI5_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI6_VALUE) + mfc0 t0, C0_WATCHHI, 6 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI6_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + + b 2f +1: + /* Incorrect config supplied, report a boot failure through UHI */ + li t9, 23 + /* Reason - Predef config incorrect */ + li a0, 2 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + +2: + jr ra + +END(__core_check) diff --git a/libgloss/mips/boot/init_caches.S b/libgloss/mips/boot/init_caches.S new file mode 100644 index 0000000..fb5ef11 --- /dev/null +++ b/libgloss/mips/boot/init_caches.S @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + +#define LINE_SIZE vt0 +#define SET_SIZE vt1 +#define ASSOC a0 +#define TOTAL_BYTES a1 +#define CURR_ADDR1 a2 +#define CURR_ADDR2 a3 +#define END_ADDR t0 +#define CONFIG t1 +#define CONFIG1 t2 +#define TEMP t3 + + .set noat + +/* + * init_icache invalidates all instruction cache entries + */ + +LEAF(__init_icache) + mfc0 CONFIG1, C0_CONFIG1 + + ext LINE_SIZE, CONFIG1, CFG1_IL_SHIFT, 3 + + /* Skip ahead if No I$ */ + li TEMP, 2 + beqz LINE_SIZE, $Ldone_icache + sllv LINE_SIZE, TEMP, LINE_SIZE /* Now have true I$ line size in bytes */ + + ext SET_SIZE, CONFIG1, CFG1_IS_SHIFT, 3 + addiu SET_SIZE, SET_SIZE, 1 /* Rotate to account for 7 == 32 sets */ + andi SET_SIZE, SET_SIZE, 7 /* Mask down to 3-bit */ + li TEMP, 32 + sllv SET_SIZE, TEMP, SET_SIZE /* I$ Sets per way */ + + // Config1IA == I$ Assoc - 1 + ext ASSOC, CONFIG1, CFG1_IA_SHIFT, 3 + addiu ASSOC, ASSOC, 1 + + mul SET_SIZE, SET_SIZE, ASSOC /* Total number of sets */ + mul TOTAL_BYTES, SET_SIZE, LINE_SIZE /* Total number of bytes */ + + li CURR_ADDR2, 0x80000000 /* Get a KSeg0 address for cacheops */ + subu CURR_ADDR2, CURR_ADDR2, LINE_SIZE /* Pre-bias the addresses as the loop */ + subu CURR_ADDR1, CURR_ADDR2, LINE_SIZE /* increments them first */ + + addu END_ADDR, CURR_ADDR1, TOTAL_BYTES /* END_ADDR is last line to invalidate */ + sll LINE_SIZE, LINE_SIZE, 1 /* Double line size as we process two */ + /* per loop */ + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + +$Lnext_icache_tag: + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ + addu CURR_ADDR1, LINE_SIZE + addu CURR_ADDR2, LINE_SIZE + cache Index_Store_Tag_I, 0(CURR_ADDR1) + cache Index_Store_Tag_I, 0(CURR_ADDR2) + bne CURR_ADDR1, END_ADDR, $Lnext_icache_tag + +$Ldone_icache: + jr ra +END(__init_icache) + +/* + * init_dcache invalidates all data cache entries + */ + +LEAF(__init_dcache) + mfc0 CONFIG1, C0_CONFIG1 + ext LINE_SIZE, CONFIG1, CFG1_DL_SHIFT, 3 + + /* Skip ahead if No D$ */ + li TEMP, 2 + beqz LINE_SIZE, $Ldone_dcache + + sllv LINE_SIZE, TEMP, LINE_SIZE /* Now have true D$ line size in bytes */ + + ext SET_SIZE, CONFIG1, CFG1_DS_SHIFT, 3 + addiu SET_SIZE, SET_SIZE, 1 /* Rotate to account for 7 == 32 sets */ + andi SET_SIZE, SET_SIZE, 7 /* Mask down to 3-bit */ + li TEMP, 32 + sllv SET_SIZE, TEMP, SET_SIZE /* D$ Sets per way */ + + /* Config1.DA == D$ Assoc - 1 */ + ext ASSOC, CONFIG1, CFG1_DA_SHIFT, 3 + addiu ASSOC, 1 + + mul SET_SIZE, SET_SIZE, ASSOC /* Get total number of sets */ + mul TOTAL_BYTES, SET_SIZE, LINE_SIZE /* Total number of bytes */ + + li CURR_ADDR2, 0x80000000 /* Get a KSeg0 address for cacheops */ + subu CURR_ADDR2, CURR_ADDR2, LINE_SIZE /* Pre-bias the addresses as the loop */ + subu CURR_ADDR1, CURR_ADDR2, LINE_SIZE /* increments them first */ + + addu END_ADDR, CURR_ADDR1, TOTAL_BYTES /* END_ADDR is last line to invalidate */ + sll LINE_SIZE, LINE_SIZE, 1 /* Double line size as we process two */ + /* per loop*/ + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + mtc0 zero, C0_TAGLO, 2 + mtc0 zero, C0_TAGHI, 2 + +$Lnext_dcache_tag: + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ + addu CURR_ADDR1, LINE_SIZE + addu CURR_ADDR2, LINE_SIZE + cache Index_Store_Tag_D, 0(CURR_ADDR1) + cache Index_Store_Tag_D, 0(CURR_ADDR2) + bne CURR_ADDR1, END_ADDR, $Lnext_dcache_tag + +$Ldone_dcache: + jr ra + +END(__init_dcache) + +/* + * __change_k0_cca essentially turns the cache on + */ + +LEAF(__change_k0_cca) + /* + * NOTE! This code must be executed in KSEG1 (not KSEG0 uncached) + * Set CCA for kseg0 to cacheable + */ + mfc0 CONFIG, C0_CONFIG + li TEMP, CFG_C_NONCOHERENT + +$Lset_kseg0_cca: + ins CONFIG, TEMP, 0, 3 + mtc0 CONFIG, C0_CONFIG + MIPS_JRHB (ra) + +END(__change_k0_cca) diff --git a/libgloss/mips/boot/init_caches_predef.S b/libgloss/mips/boot/init_caches_predef.S new file mode 100644 index 0000000..27e82b0 --- /dev/null +++ b/libgloss/mips/boot/init_caches_predef.S @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* + * Depending on the range of the displacement field of the CACHE instruction + * we can do multiple cacheops per iteration. With a cache present there + * is a guarantee of 32 lines minimum so a power of 2 less than or equal + * to 32 means there is no remainder after the loop. + * The maximum number of lines per iteration is the range of the CACHE + * displacement divided by the line_size. We cap this at 8 as a sensible + * bound. + */ + +#if __mips_isa_rev < 6 +/* MicroMIPS Release 3 has a 12-bit displacement for CACHE */ +# define ILINES_PER_ITER 8 +# define DLINES_PER_ITER 8 +#else +/* MIPS Release 6 has a 9-bit signed displacement for CACHE */ +#if ILINE_SIZE == 128 +# define ILINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define ILINES_PER_ITER 8 +#endif +#if DLINE_SIZE == 128 +# define DLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define DLINES_PER_ITER 8 +#endif +#endif + +/* + * Start off pointing to one block below where we want to invalidate the cache + * as the pointer is moved on at the start of the loop. Also offset the start + * address for each set of cache lines so that the positive and negative + * displacements from the CACHE ops can be used. + */ + +#define ICACHE_START (0x80000000 - (ILINE_SIZE * ILINES_PER_ITER / 2)) +#define ICACHE_END (0x80000000 + ITOTAL_BYTES - (ILINE_SIZE * ILINES_PER_ITER / 2)) +#define DCACHE_START (0x80000000 - (DLINE_SIZE * DLINES_PER_ITER / 2)) +#define DCACHE_END (0x80000000 + DTOTAL_BYTES - (DLINE_SIZE * DLINES_PER_ITER / 2)) + +#define CURRENT_ADDR a0 +#define END_ADDR a1 +#define CONFIG a2 +#define TEMP a3 + + .set noat + +/* + * init_icache invalidates all instruction cache entries + */ +#if defined(ILINE_ENC) && ILINE_ENC != 0 +LEAF(__init_icache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, ICACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, ICACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_icache_tag: + addu CURRENT_ADDR, (ILINE_SIZE * ILINES_PER_ITER) + cache Index_Store_Tag_I, (ILINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*1)(CURRENT_ADDR) +#if ILINES_PER_ITER == 8 + cache Index_Store_Tag_I, (ILINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_icache_tag + +$Ldone_icache: + jr ra +END(__init_icache) + +#endif // ILINE_ENC != 0 + +/* + * init_dcache invalidates all data cache entries + */ + +#if defined(DLINE_ENC) && DLINE_ENC != 0 +LEAF(__init_dcache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, DCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, DCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + mtc0 zero, C0_TAGLO, 2 + mtc0 zero, C0_TAGHI, 2 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_dcache_tag: + addu CURRENT_ADDR, (DLINE_SIZE * DLINES_PER_ITER) + cache Index_Store_Tag_D, (DLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*1)(CURRENT_ADDR) +#if DLINES_PER_ITER == 8 + cache Index_Store_Tag_D, (DLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_dcache_tag + +$Ldone_dcache: + jr ra + +END(__init_dcache) +#endif // DLINE_ENC != 0 + +/* + * __change_k0_cca essentially turns the cache on + */ + +#if ILINE_ENC != 0 || DLINE_ENC != 0 +LEAF(__change_k0_cca) + /* + * NOTE! This code must be executed in KSEG1 (not KSEG0 uncached) + * Set CCA for kseg0 to cacheable + */ + mfc0 CONFIG, C0_CONFIG + li TEMP, CFG_C_NONCOHERENT + +$Lset_kseg0_cca: + ins CONFIG, TEMP, 0, 3 + mtc0 CONFIG, C0_CONFIG + MIPS_JRHB (ra) + +END(__change_k0_cca) +#endif // ILINE_ENC != 0 || DLINE_ENC != 0 diff --git a/libgloss/mips/boot/init_cm3l2.S b/libgloss/mips/boot/init_cm3l2.S new file mode 100644 index 0000000..4ac9b0b --- /dev/null +++ b/libgloss/mips/boot/init_cm3l2.S @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> + +MIPS_NOMIPS16 + +#define CM3_BASE t8 +LEAF(__init_l23cache) + /* Check for memory mapped L2 cache config */ + mfc0 t0, C0_CONFIG3 + ext t1, t0, CFG3_M_SHIFT, 1 + beqz t1, err + + mfc0 t0, C0_CONFIG4 + ext t1, t0, CFG4_M_SHIFT, 1 + beqz t1, err + + mfc0 t0, C0_CONFIG5 + ext t1, t0, CFG5_L2C_SHIFT, 1 + bnez t1, disable_cache +err: + /* + * CM3 L2 code supplied but we have a Config2 L2 setup + * Report a Boot failure through UHI + */ + li t9, 23 + /* Reason - L2 cache config */ + li a0, 1 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + jr ra + +disable_cache: + /* Read CMGCRBase to find CMGCR_BASE_ADDR */ + PTR_MFC0 t1,C0_CMGCRBASE + sll t1, t1, CMGCR_BASE_ADDR_LSHIFT + li CM3_BASE, 0xa0000000 /* Make it virtual */ + or CM3_BASE, CM3_BASE, t1 + + /* Disable L2 cache by setting it to bypass mode */ + PTR_L a0, GCR_L2_CONFIG(CM3_BASE) + li a2, 1 + ins a0, a2, GCR_L2_BYPASS_SHIFT, GCR_L2_BYPASS_BITS + PTR_S a0, GCR_L2_CONFIG(CM3_BASE) + sync +ret: + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + /* Read CMGCRBase to find CMGCR_BASE_ADDR */ + PTR_MFC0 t3,C0_CMGCRBASE + sll t3, t3, CMGCR_BASE_ADDR_LSHIFT + li CM3_BASE, 0xa0000000 /* Make it virtual */ + or CM3_BASE, CM3_BASE, t3 + + /* Read GCR_L2_CONFIG */ + move t2, a0 + ext t3, t2, GCR_L2_SL_SHIFT, GCR_L2_SL_BITS + beqz t3, done_cm3l2cache # No L2 cache + + /* Unusual case, hardware cache initialization support & init finished. */ + PTR_L t1, GCR_L2_RAM_CONFIG(CM3_BASE) + ext t0, t1, GCR_L2_RAM_HCIS_SHIFT, (GCR_L2_RAM_HCID_BITS +\ + GCR_L2_RAM_HCIS_BITS) + li t1, 3 + beq t0, t1, done_cm3l2cache + + li a2, 2 + sllv a1, a2, t3 /* Now have L2 line size */ + + ext a0, t2, GCR_L2_SS_SHIFT, GCR_L2_SS_BITS + li a2, 64 + sllv a0, a2, a0 /* Now have L2 sets/way */ + + ext t3, t2, GCR_L2_SA_SHIFT, GCR_L2_SA_BITS + addiu t3, t3, 1 /* Set associativity */ + mul a0, t3, a0 /* Get total number of sets */ + + sw zero, GCR_TAG_ADDR(CM3_BASE) + sw zero, (GCR_TAG_ADDR+4)(CM3_BASE) + sw zero, GCR_TAG_STATE(CM3_BASE) + sw zero, (GCR_TAG_STATE+4)(CM3_BASE) + sw zero, GCR_TAG_DATA(CM3_BASE) + sw zero, (GCR_TAG_DATA+4)(CM3_BASE) + sw zero, GCR_TAG_ECC(CM3_BASE) + sw zero, (GCR_TAG_ECC+4)(CM3_BASE) + sync + + li a2, 0x80000000 + +next_cm3l2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_cm3l2cache_tag + +done_cm3l2cache: + move a2, zero + PTR_L t0, GCR_L2_CONFIG(CM3_BASE) + ins t0, a2, GCR_L2_BYPASS_SHIFT, GCR_L2_BYPASS_BITS + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + + jr ra +END(__init_l23cache_cached) diff --git a/libgloss/mips/boot/init_cm3l2_predef.S b/libgloss/mips/boot/init_cm3l2_predef.S new file mode 100644 index 0000000..83be64b --- /dev/null +++ b/libgloss/mips/boot/init_cm3l2_predef.S @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> +#include "predef.h" + +MIPS_NOMIPS16 + +#define CM3_BASE a3 + +# ifndef C0_CMGCRBASE_VALUE +# error "Static CM3 cache initialization decisions require C0_CMGCRBASE_VALUE" +# else +# define C0_CMGCRBASE_ADDR ((C0_CMGCRBASE_VALUE << 4) | (0xa << 28)) +# ifndef GCR_L2_CONFIG_VALUE +# error "Static CM3 cache initialization decisions require GCR_L2_CONFIG_VALUE" +# endif +# endif + +#undef SLINE_ENC +#undef SSET_ENC +#undef SASSOC_ENC +#undef SLINE_SIZE +#undef SSET_SIZE +#undef SASSOC + +#define SLINE_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SL_MASK) >> GCR_L2_CFG_SL_SHIFT) +#define SSET_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SS_MASK) >> GCR_L2_CFG_SS_SHIFT) +#define SASSOC_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SA_MASK) >> GCR_L2_CFG_SA_SHIFT) +#define SLINE_SIZE (2 << SLINE_ENC) +#define SSET_SIZE (64 << SSET_ENC) +#define SASSOC (SASSOC_ENC + 1) + + +LEAF(__init_l23cache) + li CM3_BASE, C0_CMGCRBASE_ADDR + /* Disable L2 cache */ + /* Reg exists, L2 cache does TAG/DATA ECC. */ + /* LRU is updated on store tag operation */ + li t0, GCR_L2_CONFIG_VALUE | GCR_L2_BYPASS_MASK + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + sync + + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + li CM3_BASE, C0_CMGCRBASE_ADDR + +#if SLINE_ENC != 0 + /* Unusual case, hardware cache initialization support & init finished. */ + PTR_L t1, GCR_L2_RAM_CONFIG(CM3_BASE) + ext t0, t1, GCR_L2_RAM_HCIS_SHIFT, (GCR_L2_RAM_HCID_BITS +\ + GCR_L2_RAM_HCIS_BITS) + li t1, 3 + beq t0, t1, done_cm3l2cache + + /* Compute L2 cache size */ + li a1, SLINE_SIZE + li a0, SSET_SIZE * SASSOC + + sw zero, GCR_TAG_ADDR(CM3_BASE) + sw zero, (GCR_TAG_ADDR+4)(CM3_BASE) + sw zero, GCR_TAG_STATE(CM3_BASE) + sw zero, (GCR_TAG_STATE+4)(CM3_BASE) + sw zero, GCR_TAG_DATA(CM3_BASE) + sw zero, (GCR_TAG_DATA+4)(CM3_BASE) + sw zero, GCR_TAG_ECC(CM3_BASE) + sw zero, (GCR_TAG_ECC+4)(CM3_BASE) + sync + + li a2, 0x80000000 + +next_cm3l2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_cm3l2cache_tag +#endif /* SLINE_ENC != 0 */ + +done_cm3l2cache: + li t0, GCR_L2_CONFIG_VALUE + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + sync + + jr ra +END(__init_l23cache_cached) diff --git a/libgloss/mips/boot/init_cp0.S b/libgloss/mips/boot/init_cp0.S new file mode 100644 index 0000000..15ac1c8 --- /dev/null +++ b/libgloss/mips/boot/init_cp0.S @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + + .set noat + +LEAF(__init_cp0) + + /* Initialize Status */ + li t1, SR_ERL | SR_BEV + mtc0 t1, C0_STATUS + + /* Initialize Watch registers if implemented */ + mfc0 t0, C0_CONFIG1 + ext t1, t0, CFG1_WR_SHIFT, 1 + beqz t1, $Ldone_wr + li t1, WATCHHI_I | WATCHHI_R | WATCHHI_W + + /* Clear Watch Status bits and disable watch exceptions */ + mtc0 t1, C0_WATCHHI + mfc0 t0, C0_WATCHHI + mtc0 zero, C0_WATCHLO + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 1 + mfc0 t0, C0_WATCHHI, 1 + mtc0 zero, C0_WATCHLO, 1 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 2 + mfc0 t0, C0_WATCHHI, 2 + mtc0 zero, C0_WATCHLO, 2 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 3 + mfc0 t0, C0_WATCHHI, 3 + mtc0 zero, C0_WATCHLO, 3 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 4 + mfc0 t0, C0_WATCHHI, 4 + mtc0 zero, C0_WATCHLO, 4 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 5 + mfc0 t0, C0_WATCHHI, 5 + mtc0 zero, C0_WATCHLO, 5 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 6 + mfc0 t0, C0_WATCHHI, 6 + mtc0 zero, C0_WATCHLO, 6 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 7 + mfc0 t0, C0_WATCHHI, 7 + mtc0 zero, C0_WATCHLO, 7 + +$Ldone_wr: + /* + * Clear WP bit to avoid watch exception upon user code entry, IV, + * and software interrupts. + */ + mtc0 zero, C0_CAUSE + + /* + * Clear timer interrupt. (Count was cleared at the reset vector to + * allow timing boot.) + */ + mtc0 zero, C0_COMPARE + + jr ra +END(__init_cp0) diff --git a/libgloss/mips/boot/init_cp0_predef.S b/libgloss/mips/boot/init_cp0_predef.S new file mode 100644 index 0000000..abc1888 --- /dev/null +++ b/libgloss/mips/boot/init_cp0_predef.S @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + + .set noat + +LEAF(__init_cp0) + + /* Initialize Status */ + li t1, SR_BEV | SR_ERL + mtc0 t1, C0_STATUS + +#if (C0_CONFIG1_VALUE & CFG1_WR) != 0 + li t1, WATCHHI_I | WATCHHI_R | WATCHHI_W + + /* Clear Watch Status bits and disable watch exceptions */ + mtc0 t1, C0_WATCHHI + mtc0 zero, C0_WATCHLO + +# ifndef C0_WATCHHI_VALUE +# error "C0_WATCHHI_VALUE is required" +# endif + +# if (C0_WATCHHI_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 1 + mtc0 zero, C0_WATCHLO, 1 + +# ifndef C0_WATCHHI1_VALUE +# error "C0_WATCHHI1_VALUE is required" +# endif + +# if (C0_WATCHHI1_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 2 + mtc0 zero, C0_WATCHLO, 2 + +# ifndef C0_WATCHHI2_VALUE +# error "C0_WATCHHI2_VALUE is required" +# endif + +# if (C0_WATCHHI2_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 3 + mtc0 zero, C0_WATCHLO, 3 + +# ifndef C0_WATCHHI3_VALUE +# error "C0_WATCHHI3_VALUE is required" +# endif + +# if (C0_WATCHHI3_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 4 + mtc0 zero, C0_WATCHLO, 4 + +# ifndef C0_WATCHHI4_VALUE +# error "C0_WATCHHI4_VALUE is required" +# endif + +# if (C0_WATCHHI4_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 5 + mtc0 zero, C0_WATCHLO, 5 + +# ifndef C0_WATCHHI5_VALUE +# error "C0_WATCHHI5_VALUE is required" +# endif + +# if (C0_WATCHHI5_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 6 + mtc0 zero, C0_WATCHLO, 6 + +# ifndef C0_WATCHHI6_VALUE +# error "C0_WATCHHI6_VALUE is required" +# endif + +# if (C0_WATCHHI6_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 7 + mtc0 zero, C0_WATCHLO, 7 + +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + + /* + * Clear WP bit to avoid watch exception upon user code entry, IV, and + * software interrupts. + */ + mtc0 zero, C0_CAUSE + + /* + * Clear timer interrupt. (Count was cleared at the reset vector to + * allow timing boot.) + */ + mtc0 zero, C0_COMPARE + + jr ra +END(__init_cp0) diff --git a/libgloss/mips/boot/init_l23caches.S b/libgloss/mips/boot/init_l23caches.S new file mode 100644 index 0000000..3b3ffed --- /dev/null +++ b/libgloss/mips/boot/init_l23caches.S @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + .set noat + +LEAF(__init_l23cache) + /* L2 Cache initialization routine */ + /* Check for memory mapped L2 cache config */ + mfc0 a3, C0_CONFIG3 + ext a3, a3, CFG3_M_SHIFT, 1 + beqz a3, l23_init + mfc0 a3, C0_CONFIG4 + ext a3, a3, CFG4_M_SHIFT, 1 + beqz a3, l23_init + mfc0 a3, C0_CONFIG5 + ext a3, a3, CFG5_L2C_SHIFT, 1 + beqz a3, l23_init + + /* + * No CM3 code supplied but we have a memory mapped L2 configuration + * Report a Boot failure through UHI + */ + li t9, 23 + /* Reason - L2 cache config */ + li a0, 1 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + b done_l3cache + +l23_init: + /* Check L2 cache size */ + mfc0 t0, C0_CONFIG2 + + /* Isolate L2$ Line Size */ + ext t1, t0, CFG2_SL_SHIFT, CFG2_SL_BITS + + /* Skip ahead if No L2$ */ + beqz t1, done_l2cache + + li a2, 2 + sllv a1, a2, t1 /* Decode L2$ line size in bytes */ + + /* Isolate L2$ Sets per Way */ + ext a0, t0, CFG2_SS_SHIFT, CFG2_SS_BITS + li a2, 64 + sllv a0, a2, a0 /* L2$ Sets per way */ + + /* Isolate L2$ Associativity */ + ext t1, t0, CFG2_SA_SHIFT, CFG2_SA_BITS + addiu t1, t1, 1 + + mul a0, a0, t1 /* Get total number of sets */ + +l2cache_init: + li a2, 0x80000000 /* Get a KSeg0 address for cacheops */ + + /* Clear L23TagLo/L23TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * L2$ Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +next_L2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_L2cache_tag + +done_l2cache: + /* Isolate L3$ Line Size */ + ext t1, t0, CFG2_TL_SHIFT, CFG2_TL_BITS + + /* Skip ahead if No L3$ */ + beqz t1, done_l3cache + + li a2, 2 + sllv a1, a2, t1 /* Decode L3$ line size in bytes */ + + /* Isolate L3$ Sets per Way */ + ext a0, t0, CFG2_TS_SHIFT, CFG2_TS_BITS + li a2, 64 + sllv a0, a2, a0 /* Decode L3 Sets per way */ + + /* Isolate L3$ Associativity */ + ext t1, t0, CFG2_TA_SHIFT, CFG2_TA_BITS + addiu t1, t1, 1 /* Decode L3 associativity (number of sets) */ + mul a0, a0, t1 /* Compute total number of sets */ + +l3cache_init: + li a2, 0x80000000 /* Get a KSeg0 address for cacheops */ + + /* Clear L23Tag register */ + mtc0 zero, C0_TAGLO, 4 + + /* + * L3$ Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +next_L3cache_tag: + cache Index_Store_Tag_T, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_L3cache_tag + +done_l3cache: + jr ra +END(__init_l23cache) diff --git a/libgloss/mips/boot/init_l23caches_predef.S b/libgloss/mips/boot/init_l23caches_predef.S new file mode 100644 index 0000000..d21c69f --- /dev/null +++ b/libgloss/mips/boot/init_l23caches_predef.S @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* + * Depending on the range of the displacement field of the CACHE instruction + * we can do multiple cacheops per iteration. With a cache present there + * is a guarantee of 32 lines minimum so a power of 2 less than or equal + * to 32 means there is no remainder after the loop. + * The maximum number of lines per iteration is the range of the CACHE + * displacement divided by the line_size. We cap this at 8 as a sensible + * bound. + */ + +#if __mips_isa_rev < 6 +/* MicroMIPS Release 3 has a 12-bit displacement for CACHE */ +# define SLINES_PER_ITER 8 +# define TLINES_PER_ITER 8 +#else +/* MIPS Release 6 has a 9-bit signed displacement for CACHE */ +#if SLINE_SIZE == 128 +# define SLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define SLINES_PER_ITER 8 +#endif +#if TLINE_SIZE == 128 +# define TLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define TLINES_PER_ITER 8 +#endif +#endif + +#ifdef MEM_MAPPED_L2C +# error MEM_MAPPED_L2C used with Config L2 code +#endif + +/* + * Start off pointing to one block below where we want to invalidate the cache + * as the pointer is moved on at the start of the loop. Also offset the start + * address for each set of cache lines so that the positive and negative + * displacements from the CACHE ops can be used. + */ + +#define SCACHE_START (0x80000000 - (SLINE_SIZE * SLINES_PER_ITER / 2)) +#define SCACHE_END (0x80000000 + STOTAL_BYTES - (SLINE_SIZE * SLINES_PER_ITER / 2)) +#define TCACHE_START (0x80000000 - (TLINE_SIZE * TLINES_PER_ITER / 2)) +#define TCACHE_END (0x80000000 + TTOTAL_BYTES - (TLINE_SIZE * TLINES_PER_ITER / 2)) + +#define CURRENT_ADDR a0 +#define END_ADDR a1 +#define CONFIG a2 +#define TEMP a3 + + .set noat + +/* + * __init_l23cache invalidates all secondary/tertiary data cache entries + */ + +#if defined(SLINE_ENC) && SLINE_ENC != 0 +LEAF(__init_l23cache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, SCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, SCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_scache_tag: + addu CURRENT_ADDR, (SLINE_SIZE * SLINES_PER_ITER) + cache Index_Store_Tag_S, (SLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*1)(CURRENT_ADDR) +#if SLINES_PER_ITER == 8 + cache Index_Store_Tag_S, (SLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_scache_tag + +$Ldone_scache: + +#if defined(TLINE_ENC) && TLINE_ENC != 0 + + /* Use KSEG0 base address */ + li CURRENT_ADDR, TCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, TCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_tcache_tag: + addu CURRENT_ADDR, (TLINE_SIZE * TLINES_PER_ITER) + cache Index_Store_Tag_T, (TLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*1)(CURRENT_ADDR) +#if TLINES_PER_ITER == 8 + cache Index_Store_Tag_T, (TLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_tcache_tag + +$Ldone_tcache: + +#endif // TLINE_ENC != 0 + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + jr ra +END(__init_l23cache_cached) + +#endif // SLINE_ENC != 0 diff --git a/libgloss/mips/boot/init_tlb.S b/libgloss/mips/boot/init_tlb.S new file mode 100644 index 0000000..20cf0b8 --- /dev/null +++ b/libgloss/mips/boot/init_tlb.S @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + +/* + * int, int __tlb_size(); + * + * Return number of entries in TLB. + * Entries in va0, number of sets in va1. + * Must not use registers t8 or a3 + * + */ +SLEAF(__tlb_size) + /* first see if we've got a TLB */ + mfc0 t0, C0_CONFIG + mfc0 t1, C0_CONFIG1 + move va0, zero + + ext t0, t0, CFG0_MT_SHIFT, CFG0_MT_BITS + /* No MMU test, 0 entries */ + beqz t0, 1f + + /* Fixed Address Translation, 0 entries */ + li t2, (CFG0_MT_FIXED >> CFG0_MT_SHIFT) + beq t0, t2, 1f + + /* Block Address Translator, 0 entries */ + li t2, (CFG0_MT_BAT >> CFG0_MT_SHIFT) + beq t0, t2, 1f + + /* (D)TLB or not? */ + andi t2, t0, (CFG0_MT_TLB | CFG0_MT_DUAL) >> CFG0_MT_SHIFT + beqz t2, 1f + + /* + * As per PRA, field holds No. of entries -1 + * Standard TLBs and Dual TLBs have extension fields. + */ + ext va0, t1, CFG1_MMUS_SHIFT, CFG1_MMUS_BITS + addiu va0, va0, 1 + + mfc0 t1, C0_CONFIG3 + ext t1, t1, CFG3_M_SHIFT, 1 + beqz t1, 1f + + mfc0 t1, C0_CONFIG4 +#if __mips_isa_rev < 6 + ext t3, t1, CFG4_MMUED_SHIFT, CFG4_MMUED_BITS + + li t2, (CFG4_MMUED_FTLBVEXT >> CFG4_MMUED_SHIFT) + beq t3, t2, 2f /* FTLB + VTLBExt */ + + li t2, (CFG4_MMUED_SIZEEXT >> CFG4_MMUED_SHIFT) + beq t3, t2, 3f /* SizeExt for VTLBEXT */ + + li t2, (CFG4_MMUED_FTLB >> CFG4_MMUED_SHIFT) + beq t3, t2, 4f /* FTLB Size */ + + /* No extension */ + jr ra + +3: + ext t3, t1, CFG4_MMUSE_SHIFT, CFG4_MMUSE_BITS + sll t2, t3, CFG1_MMUS_BITS + addu va0, va0, t2 + jr ra +#endif /* __mips_isa_rev < 6 */ +2: + ext t2, t1, CFG4_VTLBSEXT_SHIFT, CFG4_VTLBSEXT_BITS + sll t2, t2, CFG1_MMUS_BITS + addu va0, va0, t2 +4: + /* Skip FTLB size calc if Config MT != 4 */ + li t3, (CFG0_MT_DUAL >> CFG0_MT_SHIFT) + bne t3, t0, 1f + + /* Ways */ + li t2, 2 + ext t3, t1, CFG4_FTLBW_SHIFT, CFG4_FTLBW_BITS + addu t2, t2, t3 + + /* Sets per way */ + ext t3, t1, CFG4_FTLBS_SHIFT, CFG4_FTLBS_BITS + li va1, 1 + sllv va1, va1, t3 + + /* Total sets */ + sllv t2, t2, t3 + addu va0, va0, t2 + +1: jr ra +SEND(__tlb_size) + +/* + * void __tlbinvalall() + * + * Invalidate the TLB. + * Must not use register a3 + */ +SLEAF(__tlbinvalall) + + mfc0 t0, C0_CONFIG + and t2, t0, CFG0_MT_MASK + beqz t2, $Lexit /* Config[MT] test, return if no TLB */ + + li t1, CFG0_MT_BAT + beq t1, t2, $Lexit /* return as there is a BAT */ + + li t1, CFG0_MT_FIXED /* return as there is a FMT */ + beq t1, t2, $Lexit + + PTR_MTC0 zero, C0_ENTRYLO0 + PTR_MTC0 zero, C0_ENTRYLO1 + PTR_MTC0 zero, C0_PAGEMASK + + /* Fetch size & number of sets in va0, va1 */ + move t8, ra + jal __tlb_size + move ra, t8 + + /* If Config4 does not exist then use old method for invalidation */ + mfc0 t1, C0_CONFIG3 + ext t1, t1, CFG3_M_SHIFT, 1 + beqz t1, $Llegacy_init + + /* If Config4[IE] = 0, use old method for invalidation */ + mfc0 t9, C0_CONFIG4 + ext t2, t9, CFG4_IE_SHIFT, CFG4_IE_BITS + beqz t2, $Llegacy_init + + /* If Config4[IE] = 1, EHINV loop */ + li t1, (CFG4_IE_EHINV >> CFG4_IE_SHIFT) + beq t1, t2, $Lehinv_init + + /* + * If Config4[IE] = 2, tlbinvf loop. Handles Config[MT] being either + * 1 or 4. + */ + li t1, (CFG4_IE_INV >> CFG4_IE_SHIFT) + beq t1, t2, $Ltlbinvf_init + + /* TLB walk done by hardware, Config4[IE] = 3 */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + b $Lexit + +$Ltlbinvf_init: + /* + * TLB walk done by software, Config4[IE] = 2, Config[MT] = 4 or 1 + * + * one TLBINVF is executed with an index in VTLB range to + * invalidate all VTLB entries. + * + * For Dual TLBs additionally, one TLBINVF is executed per FTLB set. + */ + + /* Flush the VTLB */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + + /* + * For JTLB MMUs (Config[MT] = 1) only 1 tlbinvf is required + * early out in that case. + */ + mfc0 t0, C0_CONFIG + ext t3, t0, CFG0_MT_SHIFT, CFG0_MT_BITS + li t1, (CFG0_MT_TLB >> CFG0_MT_SHIFT) + beq t1, t3, $Lexit + + /* + * va0 contains number of TLB entries + * va1 contains number of sets per way + */ + lui t9, %hi(__tlb_stride_length) /* Fetch the tlb stride for */ + addiu t9, %lo(__tlb_stride_length) /* stepping through FTLB sets */ + mul va1, va1, t9 + subu t2, va0, va1 /* End pointer */ + +1: subu va0, va0, t9 + mtc0 va0, C0_INDEX + ehb /* mtc0, hazard on tlbinvf */ + .set push + .set eva + tlbinvf + .set pop + bne va0, t2, 1b + + b $Lexit + +$Lehinv_init: + /* + * Config4[IE] = 1. EHINV supported, but not tlbinvf. + * + * Invalidate the TLB for R3 onwards by loading EHINV and writing to all + * tlb entries. + */ + move t0, zero + li t1, C0_ENTRYHI_EHINV_MASK + mtc0 t1, C0_ENTRYHI +1: + mtc0 t0, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu t0, t0, 1 + bne va0, t0, 1b + + b $Lexit + +$Llegacy_init: + /* + * Invalidate the TLB for R1 onwards by loading + * 0x(FFFFFFFF)KSEG0_BASE into EntryHi and writing it into index 0 + * incrementing by a pagesize, writing into index 1, etc. + */ + + /* + * If large physical addressing is enabled, load 0xFFFFFFFF + * into the top half of EntryHi. + */ + move t0, zero /* t0 == 0 if XPA disabled */ + mfc0 t9, C0_CONFIG3 /* or not present */ + and t9, t1, CFG3_LPA + beqz t9, $Lno_xpa + + mfc0 t9, C0_PAGEGRAIN + ext t9, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + bnez t9, $Lno_xpa + + li t0, -1 /* t0 == 0xFFFFFFFF if XPA is used */ +$Lno_xpa: + li t1, (KSEG0_BASE - 2<<13) + + move t2, zero +1: addiu t1, t1, (2<<13) + PTR_MTC0 t1, C0_ENTRYHI + + beqz t0, $Lskip_entryhi + .set push + .set xpa + mthc0 t0, C0_ENTRYHI /* Store 0xFFFFFFFF to upper half of EntryHI */ + .set pop + +$Lskip_entryhi: + ehb /* mtc0, hazard on tlbp */ + + tlbp /* Probe for a match */ + ehb /* tlbp, Hazard on mfc0 */ + + mfc0 t8, C0_INDEX + bgez t8, 1b /* Skip this address if it exists */ + + mtc0 t2, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu t2, t2, 1 + bne va0, t2, 1b + +$Lexit: + PTR_MTC0 zero, C0_ENTRYHI /* Unset EntryHI, upper half is cleared */ + /* autmatically as mtc0 writes zeroes */ + MIPS_JRHB (ra) +SEND(__tlbinvalall) + +LEAF(__init_tlb) + + mfc0 t0, C0_CONFIG + and t2, t0, CFG0_MT_MASK + beqz t2, 1f /* return if no tlb present */ + + li t1, CFG0_MT_BAT + beq t1, t2, 1f /* return as there is a BAT */ + + li t1, CFG0_MT_FIXED /* return as there is a FMT */ + beq t1, t2, 1f + + lui t1, %hi(__enable_xpa) /* Test for XPA usage */ + ori t1, %lo(__enable_xpa) + beqz t1, 2f + + mfc0 t0, C0_CONFIG3 + and t0, t0, CFG3_LPA + bnez t0, 3f + + /* + * Raise an error because XPA was requested but LPA support is not + * available. + */ + /* Incorrect config supplied, report a boot failure through UHI */ + li t9, 23 + /* Reason - Predef/requested config incorrect */ + li a0, 2 + /* Trigger the UHI operation */ + sdbbp 1 + +3: li t1, 1 + mfc0 t0, C0_PAGEGRAIN + ins t0, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + mtc0 t0, C0_PAGEGRAIN +2: + move a3, ra + jal __tlbinvalall + move ra, a3 + + mtc0 zero, C0_PAGEMASK +1: jr ra +END(__init_tlb) diff --git a/libgloss/mips/boot/init_tlb_predef.S b/libgloss/mips/boot/init_tlb_predef.S new file mode 100644 index 0000000..e092d0a --- /dev/null +++ b/libgloss/mips/boot/init_tlb_predef.S @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +LEAF(__init_tlb) +#if HAVE_LPA && ENABLE_XPA + mfc0 t0, C0_PAGEGRAIN + li t1, 1 + ins t0, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + mtc0 t0, C0_PAGEGRAIN +#endif + # Top halves of registers are cleared impicitly with mtc0 + PTR_MTC0 zero, C0_PAGEMASK + PTR_MTC0 zero, C0_ENTRYLO0 + PTR_MTC0 zero, C0_ENTRYLO1 + +#if HAVE_HW_TLB_WALK + /* TLB walk done by hardware, Config4[IE] = 3 or Config[MT] = 1 */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop +#endif + +#if HAVE_SW_TLB_WALK + /* + * TLB walk done by software, Config4[IE] = 2, Config[MT] = 4 + * + * one TLBINVF is executed with an index in VTLB range to + * invalidate all VTLB entries. + * + * One TLBINVF is executed per FTLB entry. + * + */ + li t2, MMU_SIZE /* Start pointer/finger */ + li t8, FTLB_SETS + li t9, %hi(__tlb_stride_length) + addiu t9, %lo(__tlb_stride_length) + mul t8, t8, t9 + subu t1, t2, t8 /* End pointer */ + + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + +1: subu t2, t2, t9 + mtc0 t2, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + bne t1, t2, 1b +#endif + +#if HAVE_EHINV_WALK + li v0, MMU_SIZE + move v1, zero + li t0, C0_ENTRYHI_EHINV_MASK + PTR_MTC0 t0, C0_ENTRYHI +1: + mtc0 v1, C0_INDEX + ehb + + tlbwi + addiu v1, v1, 1 + bne v0, v1, 1b +#endif + +#if HAVE_NO_INV + /* + * Clean invalidate TLB for R1 onwards by loading + * 0x(FFFFFFFF)KSEG0_BASE into EntryHi and writing it into index MAX + * incrementing EntryHi by a pagesize, writing into index MAX-1, etc. + */ + li v0, MMU_SIZE + + /* + * If large physical addressing is enabled, load 0xFFFFFFFF + * into the top half of EntryHi. + */ +#if HAVE_LPA && ENABLE_LPA + li t0, -1 +#endif + li t1, (KSEG0_BASE - 2<<13) + + move v1, zero +1: addiu t1, t1, (2<<13) + PTR_MTC0 t1, C0_ENTRYHI +#if HAVE_LPA && ENABLE_LPA + mthc0 t0, C0_ENTRYHI +#endif + ehb /* mt(h)c0, hazard on tlbp */ + + tlbp /* Probe for a match */ + ehb /* tlbp, hazard on MFC0 */ + + mfc0 t8, C0_INDEX + bgez t8, 1b /* Skip this address if it exists */ + + mtc0 v0, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu v1, v1, 1 + bne v0, v1, 1b +#endif + + PTR_MTC0 zero, C0_ENTRYHI /* Unset EntryHI, top half */ + MIPS_JRHB (ra) +END(__init_tlb) diff --git a/libgloss/mips/boot/predef.h b/libgloss/mips/boot/predef.h new file mode 100644 index 0000000..eeaa79e --- /dev/null +++ b/libgloss/mips/boot/predef.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef C0_CONFIG0_VALUE +#error "Static TLB initialisation decisions require C0_CONFIG0_VALUE" +#endif + +#ifndef C0_CONFIG1_VALUE +#error "Static TLB/cache initialisation decisions require C0_CONFIG1_VALUE" +#endif + +#define ILINE_ENC ((C0_CONFIG1_VALUE & CFG1_IL_MASK) >> CFG1_IL_SHIFT) +#define ILINE_SIZE (2 << ILINE_ENC) +#define ISET_ENC ((C0_CONFIG1_VALUE & CFG1_IS_MASK) >> CFG1_IS_SHIFT) +#define ISET_SIZE (32 << ((ISET_ENC + 1) & 0x7)) +#define IASSOC_ENC ((C0_CONFIG1_VALUE & CFG1_IA_MASK) >> CFG1_IA_SHIFT) +#define IASSOC (IASSOC_ENC + 1) +#define ITOTAL_BYTES (ILINE_SIZE * ISET_SIZE * IASSOC) +#define DLINE_ENC ((C0_CONFIG1_VALUE & CFG1_DL_MASK) >> CFG1_DL_SHIFT) +#define DLINE_SIZE (2 << DLINE_ENC) +#define DSET_ENC ((C0_CONFIG1_VALUE & CFG1_DS_MASK) >> CFG1_DS_SHIFT) +#define DSET_SIZE (32 << ((DSET_ENC + 1) & 0x7)) +#define DASSOC_ENC ((C0_CONFIG1_VALUE & CFG1_DA_MASK) >> CFG1_DA_SHIFT) +#define DASSOC (DASSOC_ENC + 1) +#define DTOTAL_BYTES (DLINE_SIZE * DSET_SIZE * DASSOC) + +#ifndef C0_CONFIG2_VALUE +# error "Static cache initialisation decisions require C0_CONFIG2_VALUE" +#endif + +#ifndef C0_CONFIG3_VALUE +# error "Static TLB initialisation decisions require C0_CONFIG3_VALUE" +#endif + +#if (C0_CONFIG3_VALUE & CFG4_M) != 0 +# ifndef C0_CONFIG4_VALUE +# error "Static TLB/cache initialisation decisions require C0_CONFIG4_VALUE" +# endif +# if (C0_CONFIG4_VALUE & CFG4_M) != 0 +# ifndef C0_CONFIG5_VALUE +# error "Static cache initialisation decisions require C0_CONFIG5_VALUE" +# endif +# if (C0_CONFIG5_VALUE & CFG5_L2C) != 0 +# define MEM_MAPPED_L2C 1 +# endif +# endif +#endif + +#define SLINE_ENC ((C0_CONFIG2_VALUE & CFG2_SL_MASK) >> CFG2_SL_SHIFT) +#define SSET_ENC ((C0_CONFIG2_VALUE & CFG2_SS_MASK) >> CFG2_SS_SHIFT) +#define SASSOC_ENC ((C0_CONFIG2_VALUE & CFG2_SA_MASK) >> CFG2_SA_SHIFT) + +#define SLINE_SIZE (2 << SLINE_ENC) +#define SSET_SIZE (64 << SSET_ENC) +#define SASSOC (SASSOC_ENC + 1) +#define STOTAL_BYTES (SLINE_SIZE * SSET_SIZE * SASSOC) + +#define TLINE_ENC ((C0_CONFIG2_VALUE & CFG2_TL_MASK) >> CFG2_TL_SHIFT) +#define TLINE_SIZE (2 << TLINE_ENC) +#define TSET_ENC ((C0_CONFIG2_VALUE & CFG2_TS_MASK) >> CFG2_TS_SHIFT) +#define TSET_SIZE (64 << TSET_ENC) +#define TASSOC_ENC ((C0_CONFIG2_VALUE & CFG2_TA_MASK) >> CFG2_TA_SHIFT) +#define TASSOC (TASSOC_ENC + 1) +#define TTOTAL_BYTES (TLINE_SIZE * TSET_SIZE * TASSOC) + +/* TLB Macros */ + +// TLB Type +#define TLB_STANDARD ((C0_CONFIG0_VALUE & CFG0_MT_MASK) == CFG0_MT_TLB) +#define TLB_DUAL ((C0_CONFIG0_VALUE & CFG0_MT_MASK) == CFG0_MT_DUAL) +#define HAVE_TLB (TLB_STANDARD || TLB_DUAL) + +// Size definitions. +// FTLBs may be present. +#ifdef C0_CONFIG4_VALUE +# define FTLB_SET_ENC (C0_CONFIG4_VALUE & CFG4_FTLBS_MASK) >> (CFG4_FTLBS_SHIFT) +# define FTLB_WAY_ENC ((C0_CONFIG4_VALUE & CFG4_FTLBW_MASK) >> CFG4_FTLBW_SHIFT) +# if TLB_DUAL +# define FTLB_SETS (1 << FTLB_SET_ENC) +# define FTLB_SIZE (2 + FTLB_WAY_ENC) * FTLB_SETS +# else +# define FTLB_SETS 1 +# define FTLB_SIZE 0 +# endif + +// VTLB May be present +# define VTLB_SIZE_ENC ((C0_CONFIG4_VALUE & CFG4_VTLBSEXT_MASK) \ + >> CFG4_VTLBSEXT_SHIFT) +# define VTLB_SIZE (VTLB_SIZE_ENC << CFG1_MMUS_BITS) +#endif + +// Size +#define TLB_SIZE ((C0_CONFIG1_VALUE & CFG1_MMUS_MASK) >> CFG1_MMUS_SHIFT) + +// ISA < 6 relys on CFG4 MMU Extension definition +#if __mips_isa_rev < 6 + +#if !defined(C0_CONFIG4_VALUE) || (C0_CONFIG4_VALUE & CFG4_MMUED) == 0 +# define MMU_SIZE (TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_FTLBVEXT +# define MMU_SIZE (FTLB_SIZE + VTLB_SIZE + TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_SIZEEXT +# define MMUSE_ENC (C0_CONFIG4_VALUE & CFG4_MMUSE_MASK) >> CFG4_MMUSE_SHIFT +# define TLB_EXT_SIZE (MMUSE_ENC << CFG1_MMUS_BITS) +# define MMU_SIZE (TLB_EXT_SIZE + TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_FTLB +# define MMU_SIZE (FTLB_SIZE + TLB_SIZE + 1) +#endif /* C0_CONFIG4_VALUE & ...*/ + +#else + +// ISA >= 6 always uses the FTLB + VTLB fields. +#define MMU_SIZE (FTLB_SIZE + VTLB_SIZE + TLB_SIZE + 1) + +#endif /* __mips_isa_rev < 6 */ + + +// Invalidation +#ifdef C0_CONFIG4_VALUE +# define HAVE_HW_TLB_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_INVALL) +# define HAVE_SW_TLB_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_INV) +# define HAVE_EHINV_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_EHINV) +# define HAVE_NO_INV (!(HAVE_HW_TLB_WALK || HAVE_SW_TLB_WALK || HAVE_EHINV_WALK)) +#else +# define HAVE_NO_INV 1 +#endif + +// LPA +#define HAVE_LPA (C0_CONFIG3_VALUE & CFG3_LPA) diff --git a/libgloss/mips/boot/reset.S b/libgloss/mips/boot/reset.S new file mode 100644 index 0000000..37c674d --- /dev/null +++ b/libgloss/mips/boot/reset.S @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + + .set push + MIPS_NOMICROMIPS + +LEAF(__reset_vector) + lui k1, %hi(__cpu_init) + addiu k1, %lo(__cpu_init) + mtc0 zero, C0_COUNT /* Clear CP0 Count (Used to measure boot time.) */ + jr k1 + .space 32 /* Just to cope with a quirk of MIPS malta boards */ + /* this can be deleted for anything else */ +END(__reset_vector) + .set pop + +LEAF(__cpu_init) + + /* + * Verify the code is here due to a reset and not NMI. If this is an NMI then trigger + * a debugger breakpoint using a sdbbp instruction. + */ + + mfc0 k1, C0_STATUS + ext k1, k1, SR_NMI_SHIFT, 1 + beqz k1, $Lnot_nmi + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ + +$Lnot_nmi: + + /* Init CP0 Status, Count, Compare, Watch*, and Cause */ + jal __init_cp0 + + /* + * Initialise L2/L3 cache + * This could be done from cached code if there is a cca override or similar + */ + jal __init_l23cache + /* Save the L2 config register */ + move s0, a0 + + /* Initialize the L1 instruction cache */ + jal __init_icache + + /* + * The changing of Kernel mode cacheability must be done from KSEG1 + * Since the code is executing from KSEG0 it needs to do a jump to KSEG1, change K0 + * and jump back to KSEG0. + */ + + lui a2, %hi(__change_k0_cca) + addiu a2, a2, %lo(__change_k0_cca) + li a1, 0xf + ins a2, a1, 29, 1 /* changed to KSEG1 address by setting bit 29 */ + jalr a2 + + .weak __init_l23cache_cached + lui a2, %hi(__init_l23cache_cached) + addiu a2, a2, %lo(__init_l23cache_cached) + beqz a2, 1f + /* Pass in the L2 config register */ + move a0, s0 + jalr a2 +1: + /* Initialize the L1 data cache */ + jal __init_dcache + + /* Initialize the TLB */ + jal __init_tlb + + /* Allow everything else to be initialized via a hook */ + .weak __boot_init_hook + lui a2, %hi(__boot_init_hook) + addiu a2, a2, %lo(__boot_init_hook) + beqz a2, 1f + jalr a2 +1: + /* Skip copy to ram when executing in place */ + .weak __xip + lui a1, %hi(__xip) + addiu a1, a1, %lo(__xip) + bnez a1, $Lcopy_to_ram_done + /* Copy code and data to RAM */ + li s1, 0xffffffff + + /* Copy code and read-only/initialized data from FLASH to (uncached) RAM */ + lui a1, %hi(__flash_app_start) + addiu a1, a1, %lo(__flash_app_start) + ins a1, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a2, %hi(__app_start) + addiu a2, a2, %lo(__app_start) + ins a2, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a3, %hi(_edata) + addiu a3, a3, %lo(_edata) + ins a3, s1, 29, 1 /* Make it uncached (kseg1) */ + beq a2, a3, $Lcopy_to_ram_done +$Lnext_ram_word: + lw a0, 0(a1) + addiu a2, a2, 4 + addiu a1, a1, 4 + sw a0, -4(a2) + bne a3, a2, $Lnext_ram_word +$Lcopy_to_ram_done: + + # Prepare for eret to _start + lui ra, %hi($Lall_done) /* If main returns then go to all_done */ + addiu ra, ra, %lo($Lall_done) + lui t0, %hi(_start) + addiu t0, t0, %lo(_start) + mtc0 t0, C0_ERRPC /* Set ErrorEPC to _start */ + ehb + li a0, 0 /* UHI compliant null argument setup */ + + /* Return from exception will now execute the application startup code */ + eret + +$Lall_done: + /* Allow an exit hook to intercept the end of execution */ + .weak __boot_exit_hook + lui a2, %hi(__boot_exit_hook) + addiu a2, a2, %lo(__boot_exit_hook) + beqz a2, 1f + jalr a2 +1: + /* + * If _start returns it will return to this point. + * Just spin here reporting the exit. + */ + li t9, 1 /* UHI exit operation */ + move a0, va0 /* Collect exit code for UHI exit */ + sdbbp 1 /* Invoke UHI operation */ + b $Lall_done +END(__cpu_init) + +/************************************************************************************** + B O O T E X C E P T I O N H A N D L E R S (CP0 Status[BEV] = 1) +**************************************************************************************/ +/* NOTE: the linker script must insure that this code starts at start + 0x200 so the exception */ +/* vectors will be addressed properly. */ + +/* TLB refill, 32 bit task. */ +.org 0x200 +LEAF(__boot_tlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_tlb_refill) + +/* XTLB refill, 64 bit task. */ +.org 0x280 +LEAF(__boot_xtlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_xtlb_refill) + +/* Cache error exception. */ +.org 0x300 +LEAF(__boot_cache_error) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_cache_error) + +/* General exception. */ +.org 0x380 +LEAF(__boot_general_exception) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_general_exception) + +# If you want the above code to fit into 1k flash you will need to leave out the +# code below. This is the code that covers the debug exception which you normally will not get. + +/* EJTAG Debug */ +.org 0x480 +LEAF(__boot_debug_exception) + PTR_MFC0 k1, C0_DEPC + PTR_MTC0 k1, C0_DESAVE + lui k1, %hi(1f) + addiu k1, %lo(1f) + PTR_MTC0 k1, C0_DEPC + ehb + deret +1: wait + b 1b /* Stay here */ +END(__boot_debug_exception) diff --git a/libgloss/mips/boot/reset_predef.S b/libgloss/mips/boot/reset_predef.S new file mode 100644 index 0000000..d987ef7 --- /dev/null +++ b/libgloss/mips/boot/reset_predef.S @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + + .set push + MIPS_NOMICROMIPS + +LEAF(__reset_vector) + lui k1, %hi(__cpu_init) + addiu k1, %lo(__cpu_init) + mtc0 zero, C0_COUNT /* Clear CP0 Count (Used to measure boot time.) */ + jr k1 + .space 32 /* Just to cope with a quirk of MIPS malta boards */ + /* this can be deleted for anything else */ +END(__reset_vector) + .set pop + +LEAF(__cpu_init) + + /* + * Verify the code is here due to a reset and not NMI. If this is an NMI then trigger + * a debugger breakpoint using a sdbbp instruction. + */ + + mfc0 k1, C0_STATUS + ext k1, k1, SR_NMI_SHIFT, 1 + beqz k1, $Lnot_nmi + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ + +$Lnot_nmi: + +#ifndef SKIP_CORE_CHECK + jal __core_check +#endif + + /* Init CP0 Status, Count, Compare, Watch*, and Cause */ + jal __init_cp0 + +#if !defined(HCI) + +#if (defined(SLINE_ENC) && SLINE_ENC != 0) || (defined(MEM_MAPPED_L2C) && MEM_MAPPED_L2C != 0) + /* + * Initialise L2/L3 cache + * This could be done from cached code if there is a cca override or similar + */ + jal __init_l23cache + /* Save the L2 config register */ + move s0, a0 +#endif + +#if defined(ILINE_ENC) && ILINE_ENC != 0 + /* Initialize the L1 instruction cache */ + jal __init_icache +#endif + +#endif /* !defined(HCI) */ + + /* + * The changing of Kernel mode cacheability must be done from KSEG1 + * Since the code is executing from KSEG0 it needs to do a jump to KSEG1, change K0 + * and jump back to KSEG0. + */ + + lui a2, %hi(__change_k0_cca) + addiu a2, a2, %lo(__change_k0_cca) + li a1, 0xf + ins a2, a1, 29, 1 /* changed to KSEG1 address by setting bit 29 */ + jalr a2 + +#if !defined(HCI) + +#if (defined(SLINE_ENC) && SLINE_ENC != 0) || (defined(MEM_MAPPED_L2C) && MEM_MAPPED_L2C != 0) + /* Pass in the L2 config register */ + move a0, s0 + /* Support initialising L2 with L1 cache enabled */ + jal __init_l23cache_cached +#endif + +#if defined(DLINE_ENC) && DLINE_ENC != 0 + /* Initialize the L1 data cache */ + jal __init_dcache +#endif + +#endif /* !defined(HCI) */ + +#if defined(HAVE_TLB) && HAVE_TLB + /* Initialize the TLB */ + jal __init_tlb +#endif + + /* Allow everything else to be initialized via a hook */ + .weak __boot_init_hook + lui a2, %hi(__boot_init_hook) + addiu a2, a2, %lo(__boot_init_hook) + beqz a2, 1f + jalr a2 +1: + /* Skip copy to ram when executing in place */ + .weak __xip + lui a1, %hi(__xip) + addiu a1, a1, %lo(__xip) + bnez a1, $Lcopy_to_ram_done + + /* Copy code and data to RAM */ + li s1, 0xffffffff + + /* Copy code and read-only/initialized data from FLASH to (uncached) RAM */ + lui a1, %hi(__flash_app_start) + addiu a1, a1, %lo(__flash_app_start) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a1, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + lui a2, %hi(__app_start) + addiu a2, a2, %lo(__app_start) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a2, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + lui a3, %hi(_edata) + addiu a3, a3, %lo(_edata) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a3, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + beq a2, a3, $Lcopy_to_ram_done +$Lnext_ram_word: + lw a0, 0(a1) + addiu a2, a2, 4 + addiu a1, a1, 4 + sw a0, -4(a2) + bne a3, a2, $Lnext_ram_word +$Lcopy_to_ram_done: + + # Prepare for eret to _start + lui ra, %hi($Lall_done) /* If main returns then go to all_done */ + addiu ra, ra, %lo($Lall_done) + lui t0, %hi(_start) + addiu t0, t0, %lo(_start) + mtc0 t0, C0_ERRPC /* Set ErrorEPC to _start */ + ehb + li a0, 0 /* UHI compliant null argument setup */ + + /* Return from exception will now execute the application startup code */ + eret + +$Lall_done: + /* Allow an exit hook to intercept the end of execution */ + .weak __boot_exit_hook + lui a2, %hi(__boot_exit_hook) + addiu a2, a2, %lo(__boot_exit_hook) + beqz a2, 1f + jalr a2 +1: + /* + * If _start returns it will return to this point. + * Just spin here reporting the exit. + */ + li t9, 1 /* UHI exit operation */ + move a0, va0 /* Collect exit code for UHI exit */ + sdbbp 1 /* Invoke UHI operation */ + b $Lall_done + +END(__cpu_init) + +/************************************************************************************** + B O O T E X C E P T I O N H A N D L E R S (CP0 Status[BEV] = 1) +**************************************************************************************/ +/* NOTE: the linker script must insure that this code starts at start + 0x200 so the exception */ +/* vectors will be addressed properly. */ + +/* TLB refill, 32 bit task. */ +.org 0x200 +LEAF(__boot_tlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_tlb_refill) + +/* XTLB refill, 64 bit task. */ +.org 0x280 +LEAF(__boot_xtlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_xtlb_refill) + +/* Cache error exception. */ +.org 0x300 +LEAF(__boot_cache_error) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_cache_error) + +/* General exception. */ +.org 0x380 +LEAF(__boot_general_exception) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_general_exception) + +# If you want the above code to fit into 1k flash you will need to leave out the +# code below. This is the code that covers the debug exception which you normally will not get. + +/* EJTAG Debug */ +.org 0x480 +LEAF(__boot_debug_exception) + PTR_MFC0 k1, C0_DEPC + PTR_MTC0 k1, C0_DESAVE + lui k1, %hi(1f) + addiu k1, %lo(1f) + PTR_MTC0 k1, C0_DEPC + ehb + deret +1: wait + b 1b /* Stay here */ +END(__boot_debug_exception) |