| #ifndef XTENSA_CACHEATTRASM_H | |
| #define XTENSA_CACHEATTRASM_H | |
| /* | |
| * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND | |
| * | |
| * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific | |
| * CACHEATTR register related definitions that depend on CORE | |
| * configuration. | |
| * | |
| * This file is subject to the terms and conditions of the GNU General Public | |
| * License. See the file "COPYING" in the main directory of this archive | |
| * for more details. | |
| * | |
| * Copyright (C) 2002 Tensilica Inc. | |
| */ | |
| #include <xtensa/coreasm.h> | |
| /* | |
| * This header file defines assembler macros of the form: | |
| * <x>cacheattr_<func> | |
| * where: | |
| * <x> is 'i', 'd' or absent for instruction, data | |
| * or both caches; and | |
| * <func> indicates the function of the macro. | |
| * | |
| * The following functions are defined: | |
| * | |
| * icacheattr_get | |
| * Reads I-cache CACHEATTR into a2 (clobbers a3-a5). | |
| * | |
| * dcacheattr_get | |
| * Reads D-cache CACHEATTR into a2 (clobbers a3-a5). | |
| * (Note: for configs with a real CACHEATTR register, the | |
| * above two macros are identical.) | |
| * | |
| * cacheattr_set | |
| * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered). | |
| * Works even when changing one's own code's attributes. | |
| * | |
| * icacheattr_is_enabled label | |
| * Branches to \label if I-cache appears to have been enabled | |
| * (eg. if CACHEATTR contains a cache-enabled attribute). | |
| * (clobbers a2-a5,SAR) | |
| * | |
| * dcacheattr_is_enabled label | |
| * Branches to \label if D-cache appears to have been enabled | |
| * (eg. if CACHEATTR contains a cache-enabled attribute). | |
| * (clobbers a2-a5,SAR) | |
| * | |
| * cacheattr_is_enabled label | |
| * Branches to \label if either I-cache or D-cache appears to have been enabled | |
| * (eg. if CACHEATTR contains a cache-enabled attribute). | |
| * (clobbers a2-a5,SAR) | |
| * | |
| * The following macros are only defined under certain conditions: | |
| * | |
| * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) | |
| * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered). | |
| * | |
| * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) | |
| * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered). | |
| */ | |
| /*************************** GENERIC -- ALL CACHES ***************************/ | |
| /* | |
| * _cacheattr_get | |
| * | |
| * (Internal macro.) | |
| * Returns value of CACHEATTR register (or closest equivalent) in a2. | |
| * | |
| * Entry: | |
| * (none) | |
| * Exit: | |
| * a2 value read from CACHEATTR | |
| * a3-a5 clobbered (temporaries) | |
| */ | |
| .macro _cacheattr_get tlb | |
| #if XCHAL_HAVE_CACHEATTR | |
| rsr a2, CACHEATTR | |
| #elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| // We have a config that "mimics" CACHEATTR using a simplified | |
| // "MMU" composed of a single statically-mapped way. | |
| // DTLB and ITLB are independent, so there's no single | |
| // cache attribute that can describe both. So for now | |
| // just return the DTLB state. | |
| movi a5, 0xE0000000 | |
| movi a2, 0 | |
| movi a3, 0 | |
| 1: add a3, a3, a5 // next segment | |
| r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0 | |
| dsync // interlock??? | |
| slli a2, a2, 4 | |
| extui a4, a4, 0, 4 // extract CA | |
| or a2, a2, a4 | |
| bnez a3, 1b | |
| #else | |
| // This macro isn't applicable to arbitrary MMU configurations. | |
| // Just return zero. | |
| movi a2, 0 | |
| #endif | |
| .endm | |
| .macro icacheattr_get | |
| _cacheattr_get itlb | |
| .endm | |
| .macro dcacheattr_get | |
| _cacheattr_get dtlb | |
| .endm | |
| #define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 /* default (powerup/reset) value of CACHEATTR, all BYPASS | |
| mode (ie. disabled/bypassed caches) */ | |
| #if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| #define XCHAL_FCA_ENAMASK 0x001A /* bitmap of fetch attributes that require enabled icache */ | |
| #define XCHAL_LCA_ENAMASK 0x0003 /* bitmap of load attributes that require enabled dcache */ | |
| #define XCHAL_SCA_ENAMASK 0x0003 /* bitmap of store attributes that require enabled dcache */ | |
| #define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */ | |
| #define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */ | |
| /* | |
| * _cacheattr_is_enabled | |
| * | |
| * (Internal macro.) | |
| * Branches to \label if CACHEATTR in a2 indicates an enabled | |
| * cache, using mask in a3. | |
| * | |
| * Parameters: | |
| * label where to branch to if cache is enabled | |
| * Entry: | |
| * a2 contains CACHEATTR value used to determine whether | |
| * caches are enabled | |
| * a3 16-bit constant where each bit correspond to | |
| * one of the 16 possible CA values (in a CACHEATTR mask); | |
| * CA values that indicate the cache is enabled | |
| * have their corresponding bit set in this mask | |
| * (eg. use XCHAL_xCA_ENAMASK , above) | |
| * Exit: | |
| * a2,a4,a5 clobbered | |
| * SAR clobbered | |
| */ | |
| .macro _cacheattr_is_enabled label | |
| movi a4, 8 // loop 8 times | |
| .Lcaife\@: | |
| extui a5, a2, 0, 4 // get CA nibble | |
| ssr a5 // index into mask according to CA... | |
| srl a5, a3 // ...and get CA's mask bit in a5 bit 0 | |
| bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label | |
| srli a2, a2, 4 // next nibble | |
| addi a4, a4, -1 | |
| bnez a4, .Lcaife\@ // loop for each nibble | |
| .endm | |
| #else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */ | |
| .macro _cacheattr_is_enabled label | |
| j \label // macro not applicable, assume caches always enabled | |
| .endm | |
| #endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */ | |
| /* | |
| * icacheattr_is_enabled | |
| * | |
| * Branches to \label if I-cache is enabled. | |
| * | |
| * Parameters: | |
| * label where to branch to if icache is enabled | |
| * Entry: | |
| * (none) | |
| * Exit: | |
| * a2-a5, SAR clobbered (temporaries) | |
| */ | |
| .macro icacheattr_is_enabled label | |
| #if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| icacheattr_get | |
| movi a3, XCHAL_FCA_ENAMASK | |
| #endif | |
| _cacheattr_is_enabled \label | |
| .endm | |
| /* | |
| * dcacheattr_is_enabled | |
| * | |
| * Branches to \label if D-cache is enabled. | |
| * | |
| * Parameters: | |
| * label where to branch to if dcache is enabled | |
| * Entry: | |
| * (none) | |
| * Exit: | |
| * a2-a5, SAR clobbered (temporaries) | |
| */ | |
| .macro dcacheattr_is_enabled label | |
| #if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| dcacheattr_get | |
| movi a3, XCHAL_LSCA_ENAMASK | |
| #endif | |
| _cacheattr_is_enabled \label | |
| .endm | |
| /* | |
| * cacheattr_is_enabled | |
| * | |
| * Branches to \label if either I-cache or D-cache is enabled. | |
| * | |
| * Parameters: | |
| * label where to branch to if a cache is enabled | |
| * Entry: | |
| * (none) | |
| * Exit: | |
| * a2-a5, SAR clobbered (temporaries) | |
| */ | |
| .macro cacheattr_is_enabled label | |
| #if XCHAL_HAVE_CACHEATTR | |
| rsr a2, CACHEATTR | |
| movi a3, XCHAL_ALLCA_ENAMASK | |
| #elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| icacheattr_get | |
| movi a3, XCHAL_FCA_ENAMASK | |
| _cacheattr_is_enabled \label | |
| dcacheattr_get | |
| movi a3, XCHAL_LSCA_ENAMASK | |
| #endif | |
| _cacheattr_is_enabled \label | |
| .endm | |
| /* | |
| * The ISA does not have a defined way to change the | |
| * instruction cache attributes of the running code, | |
| * ie. of the memory area that encloses the current PC. | |
| * However, each micro-architecture (or class of | |
| * configurations within a micro-architecture) | |
| * provides a way to deal with this issue. | |
| * | |
| * Here are a few macros used to implement the relevant | |
| * approach taken. | |
| */ | |
| #if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| // We have a config that "mimics" CACHEATTR using a simplified | |
| // "MMU" composed of a single statically-mapped way. | |
| /* | |
| * icacheattr_set | |
| * | |
| * Entry: | |
| * a2 cacheattr value to set | |
| * Exit: | |
| * a2 unchanged | |
| * a3-a8 clobbered (temporaries) | |
| */ | |
| .macro icacheattr_set | |
| movi a5, 0xE0000000 // mask of upper 3 bits | |
| movi a6, 3f // PC where ITLB is set | |
| movi a3, 0 // start at region 0 (0 .. 7) | |
| and a6, a6, a5 // upper 3 bits of local PC area | |
| mov a7, a2 // copy a2 so it doesn't get clobbered | |
| j 3f | |
| # if XCHAL_HAVE_XLT_CACHEATTR | |
| // Can do translations, use generic method: | |
| 1: sub a6, a3, a5 // address of some other segment | |
| ritlb1 a8, a6 // save its PPN+CA | |
| dsync // interlock?? | |
| witlb a4, a6 // make it translate to this code area | |
| movi a6, 5f // where to jump into it | |
| isync | |
| sub a6, a6, a5 // adjust jump address within that other segment | |
| jx a6 | |
| // Note that in the following code snippet, which runs at a different virtual | |
| // address than it is assembled for, we avoid using literals (eg. via movi/l32r) | |
| // just in case literals end up in a different 512 MB segment, and we avoid | |
| // instructions that rely on the current PC being what is expected. | |
| // | |
| .align 4 | |
| _j 6f // this is at label '5' minus 4 bytes | |
| .align 4 | |
| 5: witlb a4, a3 // we're in other segment, now can write previous segment's CA | |
| isync | |
| add a6, a6, a5 // back to previous segment | |
| addi a6, a6, -4 // next jump label | |
| jx a6 | |
| 6: sub a6, a3, a5 // address of some other segment | |
| witlb a8, a6 // restore PPN+CA of other segment | |
| mov a6, a3 // restore a6 | |
| isync | |
| # else /* XCHAL_HAVE_XLT_CACHEATTR */ | |
| // Use micro-architecture specific method. | |
| // The following 4-instruction sequence is aligned such that | |
| // it all fits within a single I-cache line. Sixteen byte | |
| // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE | |
| // actually causes problems because that can be greater than | |
| // the alignment of the reset vector, where this macro is often | |
| // invoked, which would cause the linker to align the reset | |
| // vector code away from the reset vector!!). | |
| .align 16 /*XCHAL_ICACHE_LINESIZE*/ | |
| 1: _witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB | |
| _isync | |
| nop | |
| nop | |
| # endif /* XCHAL_HAVE_XLT_CACHEATTR */ | |
| beq a3, a5, 4f // done? | |
| // Note that in the WITLB loop, we don't do any load/stores | |
| // (may not be an issue here, but it is important in the DTLB case). | |
| 2: srli a7, a7, 4 // next CA | |
| sub a3, a3, a5 // next segment (add 0x20000000) | |
| 3: | |
| # if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */ | |
| ritlb1 a8, a3 // get current PPN+CA of segment | |
| dsync // interlock??? | |
| extui a4, a7, 0, 4 // extract CA to set | |
| srli a8, a8, 4 // clear CA but keep PPN ... | |
| slli a8, a8, 4 // ... | |
| add a4, a4, a8 // combine new CA with PPN to preserve | |
| # else | |
| extui a4, a7, 0, 4 // extract CA | |
| # endif | |
| beq a3, a6, 1b // current PC's region? if so, do it in a safe way | |
| witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB | |
| bne a3, a5, 2b | |
| isync // make sure all ifetch changes take effect | |
| 4: | |
| .endm // icacheattr_set | |
| /* | |
| * dcacheattr_set | |
| * | |
| * Entry: | |
| * a2 cacheattr value to set | |
| * Exit: | |
| * a2 unchanged | |
| * a3-a8 clobbered (temporaries) | |
| */ | |
| .macro dcacheattr_set | |
| movi a5, 0xE0000000 // mask of upper 3 bits | |
| movi a3, 0 // start at region 0 (0 .. 7) | |
| mov a7, a2 // copy a2 so it doesn't get clobbered | |
| j 3f | |
| // Note that in the WDTLB loop, we don't do any load/stores | |
| // (including implicit l32r via movi) because it isn't safe. | |
| 2: srli a7, a7, 4 // next CA | |
| sub a3, a3, a5 // next segment (add 0x20000000) | |
| 3: | |
| # if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */ | |
| rdtlb1 a8, a3 // get current PPN+CA of segment | |
| dsync // interlock??? | |
| extui a4, a7, 0, 4 // extract CA to set | |
| srli a8, a8, 4 // clear CA but keep PPN ... | |
| slli a8, a8, 4 // ... | |
| add a4, a4, a8 // combine new CA with PPN to preserve | |
| # else | |
| extui a4, a7, 0, 4 // extract CA to set | |
| # endif | |
| wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB | |
| bne a3, a5, 2b | |
| dsync // make sure all data path changes take effect | |
| .endm // dcacheattr_set | |
| #endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */ | |
| /* | |
| * cacheattr_set | |
| * | |
| * Macro that sets the current CACHEATTR safely | |
| * (both i and d) according to the current contents of a2. | |
| * It works even when changing the cache attributes of | |
| * the currently running code. | |
| * | |
| * Entry: | |
| * a2 cacheattr value to set | |
| * Exit: | |
| * a2 unchanged | |
| * a3-a8 clobbered (temporaries) | |
| */ | |
| .macro cacheattr_set | |
| #if XCHAL_HAVE_CACHEATTR | |
| # if XCHAL_ICACHE_LINESIZE < 4 | |
| // No i-cache, so can always safely write to CACHEATTR: | |
| wsr a2, CACHEATTR | |
| # else | |
| // The Athens micro-architecture, when using the old | |
| // exception architecture option (ie. with the CACHEATTR register) | |
| // allows changing the cache attributes of the running code | |
| // using the following exact sequence aligned to be within | |
| // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE | |
| // alignment actually causes problems because that can be greater | |
| // than the alignment of the reset vector, where this macro is often | |
| // invoked, which would cause the linker to align the reset | |
| // vector code away from the reset vector!!). | |
| j 1f | |
| .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line | |
| 1: _wsr a2, CACHEATTR | |
| _isync | |
| nop | |
| nop | |
| # endif | |
| #elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR | |
| // DTLB and ITLB are independent, but to keep semantics | |
| // of this macro we simply write to both. | |
| icacheattr_set | |
| dcacheattr_set | |
| #else | |
| // This macro isn't applicable to arbitrary MMU configurations. | |
| // Do nothing in this case. | |
| #endif | |
| .endm | |
| #endif /*XTENSA_CACHEATTRASM_H*/ | |