diff options
author | Zong Li <zong.li@sifive.com> | 2020-08-31 15:33:50 +0800 |
---|---|---|
committer | Palmer Dabbelt <palmerdabbelt@google.com> | 2020-09-15 18:46:08 -0700 |
commit | 38f5bd23deae24c8fa67a2c574b6d43df27a8aa8 (patch) | |
tree | 5d0762eb60036e15eef0d2a79497e594ee88923f /arch/riscv/kernel/cacheinfo.c | |
parent | b5fca7c55f9fbab5ad732c3bce00f31af6ba5cfa (diff) | |
download | linux-38f5bd23deae24c8fa67a2c574b6d43df27a8aa8.tar.bz2 |
riscv: Add cache information in AUX vector
There are no standard CSR registers to provide cache information, the
way for RISC-V is to get this information from DT. Currently, AT_L1I_X,
AT_L1D_X and AT_L2_X are present in glibc header, and sysconf syscall
could use them to get information of cache through AUX vector.
The result of 'getconf -a' as follows:
LEVEL1_ICACHE_SIZE 32768
LEVEL1_ICACHE_ASSOC 8
LEVEL1_ICACHE_LINESIZE 64
LEVEL1_DCACHE_SIZE 32768
LEVEL1_DCACHE_ASSOC 8
LEVEL1_DCACHE_LINESIZE 64
LEVEL2_CACHE_SIZE 2097152
LEVEL2_CACHE_ASSOC 32
LEVEL2_CACHE_LINESIZE 64
Signed-off-by: Zong Li <zong.li@sifive.com>
Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
Reviewed-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
Diffstat (limited to 'arch/riscv/kernel/cacheinfo.c')
-rw-r--r-- | arch/riscv/kernel/cacheinfo.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 291d7d8f748b..de59dd457b41 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -3,7 +3,6 @@ * Copyright (C) 2017 SiFive */ -#include <linux/cacheinfo.h> #include <linux/cpu.h> #include <linux/of.h> #include <linux/of_device.h> @@ -25,6 +24,37 @@ cache_get_priv_group(struct cacheinfo *this_leaf) return NULL; } +static struct cacheinfo *get_cacheinfo(u32 level, enum cache_type type) +{ + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(smp_processor_id()); + struct cacheinfo *this_leaf; + int index; + + for (index = 0; index < this_cpu_ci->num_leaves; index++) { + this_leaf = this_cpu_ci->info_list + index; + if (this_leaf->level == level && this_leaf->type == type) + return this_leaf; + } + + return NULL; +} + +uintptr_t get_cache_size(u32 level, enum cache_type type) +{ + struct cacheinfo *this_leaf = get_cacheinfo(level, type); + + return this_leaf ? this_leaf->size : 0; +} + +uintptr_t get_cache_geometry(u32 level, enum cache_type type) +{ + struct cacheinfo *this_leaf = get_cacheinfo(level, type); + + return this_leaf ? (this_leaf->ways_of_associativity << 16 | + this_leaf->coherency_line_size) : + 0; +} + static void ci_leaf_init(struct cacheinfo *this_leaf, enum cache_type type, unsigned int level, unsigned int size, unsigned int sets, unsigned int line_size) |