diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm64/armv8/cache.c | 58 | ||||
-rw-r--r-- | src/arch/arm64/include/armv8/arch/cache.h | 21 | ||||
-rw-r--r-- | src/arch/arm64/include/armv8/arch/lib_helpers.h | 1 |
3 files changed, 80 insertions, 0 deletions
diff --git a/src/arch/arm64/armv8/cache.c b/src/arch/arm64/armv8/cache.c index ae0729e331..dbaedec31d 100644 --- a/src/arch/arm64/armv8/cache.c +++ b/src/arch/arm64/armv8/cache.c @@ -11,6 +11,64 @@ #include <arch/lib_helpers.h> #include <program_loading.h> +enum cache_type cpu_get_cache_type(enum cache_level level) +{ + uint32_t ctype_bitshift = (level - 1) * 3; + + if (level < CACHE_L1 || level > CACHE_L7) + return NO_CACHE; + + /* 3-bits per cache-level */ + return (raw_read_clidr_el1() >> ctype_bitshift) & 0x7; +} + +static uint64_t get_ccsidr_el1_assoc(uint64_t ccsidr_el1) +{ + /* [23:20] - CCIDX support enables 64-bit CCSIDR_EL1 */ + if ((raw_read_id_aa64mmfr2_el1() & 0xF00000) == 0x100000) { + /* [23:3] */ + return (ccsidr_el1 & 0xFFFFF8) >> 3; + } else { + /* [12:3] */ + return (ccsidr_el1 & 0x1FF8) >> 3; + } +} + +static uint64_t get_ccsidr_el1_numsets(uint64_t ccsidr_el1) +{ + /* [23:20] - CCIDX support enables 64-bit CCSIDR_EL1 */ + if ((raw_read_id_aa64mmfr2_el1() & 0xF00000) == 0x100000) { + /* [55:32] */ + return (ccsidr_el1 & 0xFFFFFF00000000) >> 32; + } else { + /* [27:13] */ + return (ccsidr_el1 & 0xFFFE000) >> 13; + } +} + +void cpu_get_cache_info(enum cache_level level, enum cache_type type, size_t *cache_size, size_t *assoc) +{ + uint64_t ccsidr_el1; + + if (cache_size == NULL || assoc == NULL) + return; + + if (level < CACHE_L1 || level > CACHE_L7) + return; + + /* [0] - Indicates instruction cache; [3:1] - Indicates cache level */ + raw_write_csselr_el1(((level - 1) << 1) | (type == CACHE_INSTRUCTION)); + ccsidr_el1 = raw_read_ccsidr_el1(); + + /* [2:0] - Indicates (Log2(Number of bytes in cache line) - 4) */ + uint8_t line_length = 1 << ((ccsidr_el1 & 0x7) + 4); + /* (Number of sets in cache) - 1 */ + uint64_t num_sets = get_ccsidr_el1_numsets(ccsidr_el1) + 1; + /* (Associativity of cache) - 1 */ + *assoc = get_ccsidr_el1_assoc(ccsidr_el1) + 1; + *cache_size = line_length * *assoc * num_sets; +} + unsigned int dcache_line_bytes(void) { uint32_t ctr_el0; diff --git a/src/arch/arm64/include/armv8/arch/cache.h b/src/arch/arm64/include/armv8/arch/cache.h index bb9d6febec..3a72d40c7a 100644 --- a/src/arch/arm64/include/armv8/arch/cache.h +++ b/src/arch/arm64/include/armv8/arch/cache.h @@ -13,6 +13,27 @@ #include <stddef.h> #include <arch/barrier.h> +enum cache_level { + CACHE_L1 = 1, + CACHE_L2 = 2, + CACHE_L3 = 3, + CACHE_L4 = 4, + CACHE_L5 = 5, + CACHE_L6 = 6, + CACHE_L7 = 7, +}; + +enum cache_type { + NO_CACHE = 0, + CACHE_INSTRUCTION = 1, + CACHE_DATA = 2, + CACHE_SEPARATE = 3, + CACHE_UNIFIED = 4, +}; + +enum cache_type cpu_get_cache_type(enum cache_level level); +void cpu_get_cache_info(enum cache_level level, enum cache_type, size_t *cache_size, size_t *assoc); + /* dcache clean by virtual address to PoC */ void dcache_clean_by_mva(void const *addr, size_t len); diff --git a/src/arch/arm64/include/armv8/arch/lib_helpers.h b/src/arch/arm64/include/armv8/arch/lib_helpers.h index 4b3730f48b..ff3459a91e 100644 --- a/src/arch/arm64/include/armv8/arch/lib_helpers.h +++ b/src/arch/arm64/include/armv8/arch/lib_helpers.h @@ -162,6 +162,7 @@ MAKE_REGISTER_ACCESSORS(hacr_el2) MAKE_REGISTER_ACCESSORS(hcr_el2) MAKE_REGISTER_ACCESSORS(hpfar_el2) MAKE_REGISTER_ACCESSORS(hstr_el2) +MAKE_REGISTER_ACCESSORS(id_aa64mmfr2_el1) MAKE_REGISTER_ACCESSORS(isr_el1) MAKE_REGISTER_ACCESSORS_EL123(mair) MAKE_REGISTER_ACCESSORS_EL123(mdcr) |