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:
@@ -1,4 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 SiFive
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _ASM_RISCV_CACHEINFO_H
|
#ifndef _ASM_RISCV_CACHEINFO_H
|
||||||
#define _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);
|
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 */
|
#endif /* _ASM_RISCV_CACHEINFO_H */
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <uapi/asm/elf.h>
|
#include <uapi/asm/elf.h>
|
||||||
#include <asm/auxvec.h>
|
#include <asm/auxvec.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
#include <asm/cacheinfo.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are used to set parameters in the core dumps.
|
* These are used to set parameters in the core dumps.
|
||||||
@@ -61,6 +62,18 @@ extern unsigned long elf_hwcap;
|
|||||||
do { \
|
do { \
|
||||||
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
|
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
|
||||||
(elf_addr_t)current->mm->context.vdso); \
|
(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)
|
} while (0)
|
||||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||||
struct linux_binprm;
|
struct linux_binprm;
|
||||||
|
@@ -10,7 +10,28 @@
|
|||||||
/* vDSO location */
|
/* vDSO location */
|
||||||
#define AT_SYSINFO_EHDR 33
|
#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 */
|
/* entries in ARCH_DLINFO */
|
||||||
#define AT_VECTOR_SIZE_ARCH 1
|
#define AT_VECTOR_SIZE_ARCH 7
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
|
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
* Copyright (C) 2017 SiFive
|
* Copyright (C) 2017 SiFive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/cacheinfo.h>
|
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
@@ -25,6 +24,37 @@ cache_get_priv_group(struct cacheinfo *this_leaf)
|
|||||||
return NULL;
|
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,
|
static void ci_leaf_init(struct cacheinfo *this_leaf, enum cache_type type,
|
||||||
unsigned int level, unsigned int size,
|
unsigned int level, unsigned int size,
|
||||||
unsigned int sets, unsigned int line_size)
|
unsigned int sets, unsigned int line_size)
|
||||||
|
Reference in New Issue
Block a user