diff options
author | Benjamin Doron <benjamin.doron@9elements.com> | 2023-06-14 18:12:43 -0400 |
---|---|---|
committer | Shelley Chen <shchen@google.com> | 2023-10-25 22:21:58 +0000 |
commit | 1087a17edc4d1b02e57ddd4fcaf7c5fade174c79 (patch) | |
tree | 7bceeb0ce5740a35d186bc47bc5942f8963c9563 /src/arch/arm64/armv8 | |
parent | 6f66ca82de79b3b5c143332c1b9dbf06df0e303d (diff) |
arch/arm64/cache: Implement helpers to obtain CPU cache details
This is required for compliant ACPI/SMBIOS implementations on AArch64,
and can optionally be displayed to the user.
Change-Id: I7022fc3c0035208bc3fdc716fc33f6b78d8e74fc
Signed-off-by: Benjamin Doron <benjamin.doron@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/78042
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Diffstat (limited to 'src/arch/arm64/armv8')
-rw-r--r-- | src/arch/arm64/armv8/cache.c | 58 |
1 files changed, 58 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; |