mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-20 12:54:36 +08:00
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>
This commit is contained in:
parent
b5fca7c55f
commit
38f5bd23de
@ -1,4 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020 SiFive
|
||||
*/
|
||||
|
||||
#ifndef _ASM_RISCV_CACHEINFO_H
|
||||
#define _ASM_RISCV_CACHEINFO_H
|
||||
@ -11,5 +14,7 @@ struct riscv_cacheinfo_ops {
|
||||
};
|
||||
|
||||
void riscv_set_cacheinfo_ops(struct riscv_cacheinfo_ops *ops);
|
||||
uintptr_t get_cache_size(u32 level, enum cache_type type);
|
||||
uintptr_t get_cache_geometry(u32 level, enum cache_type type);
|
||||
|
||||
#endif /* _ASM_RISCV_CACHEINFO_H */
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <uapi/asm/elf.h>
|
||||
#include <asm/auxvec.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
@ -61,6 +62,18 @@ extern unsigned long elf_hwcap;
|
||||
do { \
|
||||
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
|
||||
(elf_addr_t)current->mm->context.vdso); \
|
||||
NEW_AUX_ENT(AT_L1I_CACHESIZE, \
|
||||
get_cache_size(1, CACHE_TYPE_INST)); \
|
||||
NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \
|
||||
get_cache_geometry(1, CACHE_TYPE_INST)); \
|
||||
NEW_AUX_ENT(AT_L1D_CACHESIZE, \
|
||||
get_cache_size(1, CACHE_TYPE_DATA)); \
|
||||
NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, \
|
||||
get_cache_geometry(1, CACHE_TYPE_DATA)); \
|
||||
NEW_AUX_ENT(AT_L2_CACHESIZE, \
|
||||
get_cache_size(2, CACHE_TYPE_UNIFIED)); \
|
||||
NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \
|
||||
get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \
|
||||
} while (0)
|
||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||
struct linux_binprm;
|
||||
|
@ -10,7 +10,28 @@
|
||||
/* vDSO location */
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
|
||||
/*
|
||||
* The set of entries below represent more extensive information
|
||||
* about the caches, in the form of two entry per cache type,
|
||||
* one entry containing the cache size in bytes, and the other
|
||||
* containing the cache line size in bytes in the bottom 16 bits
|
||||
* and the cache associativity in the next 16 bits.
|
||||
*
|
||||
* The associativity is such that if N is the 16-bit value, the
|
||||
* cache is N way set associative. A value if 0xffff means fully
|
||||
* associative, a value of 1 means directly mapped.
|
||||
*
|
||||
* For all these fields, a value of 0 means that the information
|
||||
* is not known.
|
||||
*/
|
||||
#define AT_L1I_CACHESIZE 40
|
||||
#define AT_L1I_CACHEGEOMETRY 41
|
||||
#define AT_L1D_CACHESIZE 42
|
||||
#define AT_L1D_CACHEGEOMETRY 43
|
||||
#define AT_L2_CACHESIZE 44
|
||||
#define AT_L2_CACHEGEOMETRY 45
|
||||
|
||||
/* entries in ARCH_DLINFO */
|
||||
#define AT_VECTOR_SIZE_ARCH 1
|
||||
#define AT_VECTOR_SIZE_ARCH 7
|
||||
|
||||
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user