2022-05-31 13:04:11 +03:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* LoongArch cacheinfo support
*
* Copyright ( C ) 2020 - 2022 Loongson Technology Corporation Limited
*/
# include <linux/cacheinfo.h>
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
# include <linux/topology.h>
2022-07-13 13:00:41 +03:00
# include <asm/bootinfo.h>
# include <asm/cpu-info.h>
2022-05-31 13:04:11 +03:00
int init_cache_level ( unsigned int cpu )
{
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
int cache_present = current_cpu_data . cache_leaves_present ;
2022-05-31 13:04:11 +03:00
struct cpu_cacheinfo * this_cpu_ci = get_cpu_cacheinfo ( cpu ) ;
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
this_cpu_ci - > num_levels =
current_cpu_data . cache_leaves [ cache_present - 1 ] . level ;
this_cpu_ci - > num_leaves = cache_present ;
2022-05-31 13:04:11 +03:00
return 0 ;
}
static inline bool cache_leaves_are_shared ( struct cacheinfo * this_leaf ,
struct cacheinfo * sib_leaf )
{
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
return ( ! ( * ( unsigned char * ) ( this_leaf - > priv ) & CACHE_PRIVATE )
& & ! ( * ( unsigned char * ) ( sib_leaf - > priv ) & CACHE_PRIVATE ) ) ;
2022-05-31 13:04:11 +03:00
}
static void cache_cpumap_setup ( unsigned int cpu )
{
unsigned int index ;
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
struct cacheinfo * this_leaf , * sib_leaf ;
struct cpu_cacheinfo * this_cpu_ci = get_cpu_cacheinfo ( cpu ) ;
2022-05-31 13:04:11 +03:00
for ( index = 0 ; index < this_cpu_ci - > num_leaves ; index + + ) {
unsigned int i ;
this_leaf = this_cpu_ci - > info_list + index ;
/* skip if shared_cpu_map is already populated */
if ( ! cpumask_empty ( & this_leaf - > shared_cpu_map ) )
continue ;
cpumask_set_cpu ( cpu , & this_leaf - > shared_cpu_map ) ;
for_each_online_cpu ( i ) {
struct cpu_cacheinfo * sib_cpu_ci = get_cpu_cacheinfo ( i ) ;
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
if ( i = = cpu | | ! sib_cpu_ci - > info_list | |
( cpu_to_node ( i ) ! = cpu_to_node ( cpu ) ) )
continue ;
2022-05-31 13:04:11 +03:00
sib_leaf = sib_cpu_ci - > info_list + index ;
if ( cache_leaves_are_shared ( this_leaf , sib_leaf ) ) {
cpumask_set_cpu ( cpu , & sib_leaf - > shared_cpu_map ) ;
cpumask_set_cpu ( i , & this_leaf - > shared_cpu_map ) ;
}
}
}
}
int populate_cache_leaves ( unsigned int cpu )
{
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
int i , cache_present = current_cpu_data . cache_leaves_present ;
2022-05-31 13:04:11 +03:00
struct cpu_cacheinfo * this_cpu_ci = get_cpu_cacheinfo ( cpu ) ;
struct cacheinfo * this_leaf = this_cpu_ci - > info_list ;
LoongArch: Refactor cache probe and flush methods
Current cache probe and flush methods have some drawbacks:
1, Assume there are 3 cache levels and only 3 levels;
2, Assume L1 = I + D, L2 = V, L3 = S, V is exclusive, S is inclusive.
However, the fact is I + D, I + D + V, I + D + S and I + D + V + S are
all valid. So, refactor the cache probe and flush methods to adapt more
types of cache hierarchy.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-10-12 11:36:14 +03:00
struct cache_desc * cd , * cdesc = current_cpu_data . cache_leaves ;
for ( i = 0 ; i < cache_present ; i + + ) {
cd = cdesc + i ;
this_leaf - > type = cd - > type ;
this_leaf - > level = cd - > level ;
this_leaf - > coherency_line_size = cd - > linesz ;
this_leaf - > number_of_sets = cd - > sets ;
this_leaf - > ways_of_associativity = cd - > ways ;
this_leaf - > size = cd - > linesz * cd - > sets * cd - > ways ;
this_leaf - > priv = & cd - > flags ;
this_leaf + + ;
2022-05-31 13:04:11 +03:00
}
cache_cpumap_setup ( cpu ) ;
this_cpu_ci - > cpu_map_populated = true ;
return 0 ;
}