1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2246246cbSSudeep Holla #ifndef _LINUX_CACHEINFO_H
3246246cbSSudeep Holla #define _LINUX_CACHEINFO_H
4246246cbSSudeep Holla
5246246cbSSudeep Holla #include <linux/bitops.h>
6685cb167STony Luck #include <linux/cpuhplock.h>
7e1b6705bSYury Norov #include <linux/cpumask_types.h>
8246246cbSSudeep Holla #include <linux/smp.h>
9246246cbSSudeep Holla
10246246cbSSudeep Holla struct device_node;
11246246cbSSudeep Holla struct attribute;
12246246cbSSudeep Holla
13246246cbSSudeep Holla enum cache_type {
14246246cbSSudeep Holla CACHE_TYPE_NOCACHE = 0,
15246246cbSSudeep Holla CACHE_TYPE_INST = BIT(0),
16246246cbSSudeep Holla CACHE_TYPE_DATA = BIT(1),
17246246cbSSudeep Holla CACHE_TYPE_SEPARATE = CACHE_TYPE_INST | CACHE_TYPE_DATA,
18246246cbSSudeep Holla CACHE_TYPE_UNIFIED = BIT(2),
19246246cbSSudeep Holla };
20246246cbSSudeep Holla
219a83c84cSShaokun Zhang extern unsigned int coherency_max_size;
229a83c84cSShaokun Zhang
23246246cbSSudeep Holla /**
24246246cbSSudeep Holla * struct cacheinfo - represent a cache leaf node
25e9a2ea5aSFenghua Yu * @id: This cache's id. It is unique among caches with the same (type, level).
26246246cbSSudeep Holla * @type: type of the cache - data, inst or unified
272539b258SWill Deacon * @level: represents the hierarchy in the multi-level cache
28246246cbSSudeep Holla * @coherency_line_size: size of each cache line usually representing
29246246cbSSudeep Holla * the minimum amount of data that gets transferred from memory
30246246cbSSudeep Holla * @number_of_sets: total number of sets, a set is a collection of cache
31246246cbSSudeep Holla * lines sharing the same index
32246246cbSSudeep Holla * @ways_of_associativity: number of ways in which a particular memory
33246246cbSSudeep Holla * block can be placed in the cache
34246246cbSSudeep Holla * @physical_line_partition: number of physical cache lines sharing the
35246246cbSSudeep Holla * same cachetag
36246246cbSSudeep Holla * @size: Total size of the cache
37246246cbSSudeep Holla * @shared_cpu_map: logical cpumask representing all the cpus sharing
38246246cbSSudeep Holla * this cache node
39246246cbSSudeep Holla * @attributes: bitfield representing various cache attributes
409b97387cSJeremy Linton * @fw_token: Unique value used to determine if different cacheinfo
419b97387cSJeremy Linton * structures represent a single hardware cache instance.
42246246cbSSudeep Holla * @disable_sysfs: indicates whether this node is visible to the user via
43246246cbSSudeep Holla * sysfs or not
44246246cbSSudeep Holla * @priv: pointer to any private data structure specific to particular
45246246cbSSudeep Holla * cache design
46246246cbSSudeep Holla *
47246246cbSSudeep Holla * While @of_node, @disable_sysfs and @priv are used for internal book
48246246cbSSudeep Holla * keeping, the remaining members form the core properties of the cache
49246246cbSSudeep Holla */
50246246cbSSudeep Holla struct cacheinfo {
51e9a2ea5aSFenghua Yu unsigned int id;
52246246cbSSudeep Holla enum cache_type type;
53246246cbSSudeep Holla unsigned int level;
54246246cbSSudeep Holla unsigned int coherency_line_size;
55246246cbSSudeep Holla unsigned int number_of_sets;
56246246cbSSudeep Holla unsigned int ways_of_associativity;
57246246cbSSudeep Holla unsigned int physical_line_partition;
58246246cbSSudeep Holla unsigned int size;
59246246cbSSudeep Holla cpumask_t shared_cpu_map;
60246246cbSSudeep Holla unsigned int attributes;
61246246cbSSudeep Holla #define CACHE_WRITE_THROUGH BIT(0)
62246246cbSSudeep Holla #define CACHE_WRITE_BACK BIT(1)
63246246cbSSudeep Holla #define CACHE_WRITE_POLICY_MASK \
64246246cbSSudeep Holla (CACHE_WRITE_THROUGH | CACHE_WRITE_BACK)
65246246cbSSudeep Holla #define CACHE_READ_ALLOCATE BIT(2)
66246246cbSSudeep Holla #define CACHE_WRITE_ALLOCATE BIT(3)
67246246cbSSudeep Holla #define CACHE_ALLOCATE_POLICY_MASK \
68246246cbSSudeep Holla (CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE)
69e9a2ea5aSFenghua Yu #define CACHE_ID BIT(4)
709b97387cSJeremy Linton void *fw_token;
71246246cbSSudeep Holla bool disable_sysfs;
72246246cbSSudeep Holla void *priv;
73246246cbSSudeep Holla };
74246246cbSSudeep Holla
75246246cbSSudeep Holla struct cpu_cacheinfo {
76246246cbSSudeep Holla struct cacheinfo *info_list;
7794a3bfe4SHuang Ying unsigned int per_cpu_data_slice_size;
78246246cbSSudeep Holla unsigned int num_levels;
79246246cbSSudeep Holla unsigned int num_leaves;
80fac51482SSudeep Holla bool cpu_map_populated;
816539cffaSRadu Rendec bool early_ci_levels;
82246246cbSSudeep Holla };
83246246cbSSudeep Holla
84246246cbSSudeep Holla struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);
856539cffaSRadu Rendec int early_cache_level(unsigned int cpu);
86246246cbSSudeep Holla int init_cache_level(unsigned int cpu);
87c3719bd9SPierre Gondois int init_of_cache_level(unsigned int cpu);
88246246cbSSudeep Holla int populate_cache_leaves(unsigned int cpu);
89582b468bSJeremy Linton int cache_setup_acpi(unsigned int cpu);
90cc1cfc47SSudeep Holla bool last_level_cache_is_valid(unsigned int cpu);
91cc1cfc47SSudeep Holla bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y);
925944ce09SPierre Gondois int fetch_cache_info(unsigned int cpu);
9336bbc5b4SSudeep Holla int detect_cache_attributes(unsigned int cpu);
942520e627SSudeep Holla #ifndef CONFIG_ACPI_PPTT
95582b468bSJeremy Linton /*
96bd500361SPierre Gondois * acpi_get_cache_info() is only called on ACPI enabled
97582b468bSJeremy Linton * platforms using the PPTT for topology. This means that if
98582b468bSJeremy Linton * the platform supports other firmware configuration methods
99582b468bSJeremy Linton * we need to stub out the call when ACPI is disabled.
100582b468bSJeremy Linton * ACPI enabled platforms not using PPTT won't be making calls
101582b468bSJeremy Linton * to this function so we need not worry about them.
102582b468bSJeremy Linton */
103bd500361SPierre Gondois static inline
acpi_get_cache_info(unsigned int cpu,unsigned int * levels,unsigned int * split_levels)104bd500361SPierre Gondois int acpi_get_cache_info(unsigned int cpu,
105bd500361SPierre Gondois unsigned int *levels, unsigned int *split_levels)
106582b468bSJeremy Linton {
107d931b83eSPierre Gondois return -ENOENT;
108582b468bSJeremy Linton }
109582b468bSJeremy Linton #else
110bd500361SPierre Gondois int acpi_get_cache_info(unsigned int cpu,
111bd500361SPierre Gondois unsigned int *levels, unsigned int *split_levels);
112582b468bSJeremy Linton #endif
113246246cbSSudeep Holla
114246246cbSSudeep Holla const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf);
115246246cbSSudeep Holla
116709c4362SJames Morse /*
117685cb167STony Luck * Get the cacheinfo structure for the cache associated with @cpu at
118685cb167STony Luck * level @level.
119685cb167STony Luck * cpuhp lock must be held.
120685cb167STony Luck */
get_cpu_cacheinfo_level(int cpu,int level)121685cb167STony Luck static inline struct cacheinfo *get_cpu_cacheinfo_level(int cpu, int level)
122685cb167STony Luck {
123685cb167STony Luck struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
124685cb167STony Luck int i;
125685cb167STony Luck
126685cb167STony Luck lockdep_assert_cpus_held();
127685cb167STony Luck
128685cb167STony Luck for (i = 0; i < ci->num_leaves; i++) {
129685cb167STony Luck if (ci->info_list[i].level == level) {
130685cb167STony Luck if (ci->info_list[i].attributes & CACHE_ID)
131685cb167STony Luck return &ci->info_list[i];
132685cb167STony Luck return NULL;
133685cb167STony Luck }
134685cb167STony Luck }
135685cb167STony Luck
136685cb167STony Luck return NULL;
137685cb167STony Luck }
138685cb167STony Luck
139685cb167STony Luck /*
140709c4362SJames Morse * Get the id of the cache associated with @cpu at level @level.
141709c4362SJames Morse * cpuhp lock must be held.
142709c4362SJames Morse */
get_cpu_cacheinfo_id(int cpu,int level)143709c4362SJames Morse static inline int get_cpu_cacheinfo_id(int cpu, int level)
144709c4362SJames Morse {
145685cb167STony Luck struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, level);
146709c4362SJames Morse
147685cb167STony Luck return ci ? ci->id : -1;
148709c4362SJames Morse }
149709c4362SJames Morse
150*a9ff9447SDmitry Baryshkov #if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
151ef9f643aSPierre Gondois #define use_arch_cache_info() (true)
152ef9f643aSPierre Gondois #else
153ef9f643aSPierre Gondois #define use_arch_cache_info() (false)
154ef9f643aSPierre Gondois #endif
155ef9f643aSPierre Gondois
1568690bbcfSMathieu Desnoyers #ifndef CONFIG_ARCH_HAS_CPU_CACHE_ALIASING
1578690bbcfSMathieu Desnoyers #define cpu_dcache_is_aliasing() false
1588690bbcfSMathieu Desnoyers #define cpu_icache_is_aliasing() cpu_dcache_is_aliasing()
1598690bbcfSMathieu Desnoyers #else
1608690bbcfSMathieu Desnoyers #include <asm/cachetype.h>
1618690bbcfSMathieu Desnoyers
162246246cbSSudeep Holla #ifndef cpu_icache_is_aliasing
163 #define cpu_icache_is_aliasing() cpu_dcache_is_aliasing()
164 #endif
165
166 #endif
167
168 #endif /* _LINUX_CACHEINFO_H */
169