1 // SPDX-License-Identifier: GPL-2.0-only 1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 2 /* 3 * Copyright (C) 2017 SiFive !! 3 * MIPS cacheinfo support 4 */ 4 */ >> 5 #include <linux/cacheinfo.h> 5 6 6 #include <linux/acpi.h> !! 7 /* Populates leaf and increments to next leaf */ 7 #include <linux/cpu.h> !! 8 #define populate_cache(cache, leaf, c_level, c_type) \ 8 #include <linux/of.h> !! 9 do { \ 9 #include <asm/cacheinfo.h> !! 10 leaf->type = c_type; \ >> 11 leaf->level = c_level; \ >> 12 leaf->coherency_line_size = c->cache.linesz; \ >> 13 leaf->number_of_sets = c->cache.sets; \ >> 14 leaf->ways_of_associativity = c->cache.ways; \ >> 15 leaf->size = c->cache.linesz * c->cache.sets * \ >> 16 c->cache.ways; \ >> 17 leaf++; \ >> 18 } while (0) 10 19 11 static struct riscv_cacheinfo_ops *rv_cache_op !! 20 int init_cache_level(unsigned int cpu) 12 << 13 void riscv_set_cacheinfo_ops(struct riscv_cach << 14 { << 15 rv_cache_ops = ops; << 16 } << 17 EXPORT_SYMBOL_GPL(riscv_set_cacheinfo_ops); << 18 << 19 const struct attribute_group * << 20 cache_get_priv_group(struct cacheinfo *this_le << 21 { 21 { 22 if (rv_cache_ops && rv_cache_ops->get_ !! 22 struct cpuinfo_mips *c = ¤t_cpu_data; 23 return rv_cache_ops->get_priv_ !! 23 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 24 return NULL; !! 24 int levels = 0, leaves = 0; 25 } << 26 25 27 static struct cacheinfo *get_cacheinfo(u32 lev << 28 { << 29 /* 26 /* 30 * Using raw_smp_processor_id() elides !! 27 * If Dcache is not set, we assume the cache structures 31 * is really indicative of a larger pr !! 28 * are not properly initialized. 32 * that cores have a homonogenous view << 33 * happens to be the case for the curr << 34 * likely won't be true in general. S << 35 * correct information for these syste << 36 * just eliding the check for now. << 37 */ 29 */ 38 struct cpu_cacheinfo *this_cpu_ci = ge !! 30 if (c->dcache.waysize) 39 struct cacheinfo *this_leaf; !! 31 levels += 1; 40 int index; !! 32 else >> 33 return -ENOENT; 41 34 42 for (index = 0; index < this_cpu_ci->n !! 35 43 this_leaf = this_cpu_ci->info_ !! 36 leaves += (c->icache.waysize) ? 2 : 1; 44 if (this_leaf->level == level !! 37 45 return this_leaf; !! 38 if (c->vcache.waysize) { >> 39 levels++; >> 40 leaves++; 46 } 41 } 47 42 48 return NULL; !! 43 if (c->scache.waysize) { 49 } !! 44 levels++; >> 45 leaves++; >> 46 } 50 47 51 uintptr_t get_cache_size(u32 level, enum cache !! 48 if (c->tcache.waysize) { 52 { !! 49 levels++; 53 struct cacheinfo *this_leaf = get_cach !! 50 leaves++; >> 51 } 54 52 55 return this_leaf ? this_leaf->size : 0 !! 53 this_cpu_ci->num_levels = levels; >> 54 this_cpu_ci->num_leaves = leaves; >> 55 return 0; 56 } 56 } 57 57 58 uintptr_t get_cache_geometry(u32 level, enum c !! 58 static void fill_cpumask_siblings(int cpu, cpumask_t *cpu_map) 59 { 59 { 60 struct cacheinfo *this_leaf = get_cach !! 60 int cpu1; 61 61 62 return this_leaf ? (this_leaf->ways_of !! 62 for_each_possible_cpu(cpu1) 63 this_leaf->coheren !! 63 if (cpus_are_siblings(cpu, cpu1)) 64 0; !! 64 cpumask_set_cpu(cpu1, cpu_map); 65 } 65 } 66 66 67 static void ci_leaf_init(struct cacheinfo *thi !! 67 static void fill_cpumask_cluster(int cpu, cpumask_t *cpu_map) 68 enum cache_type type, << 69 { 68 { 70 this_leaf->level = level; !! 69 int cpu1; 71 this_leaf->type = type; !! 70 int cluster = cpu_cluster(&cpu_data[cpu]); 72 } << 73 71 74 int init_cache_level(unsigned int cpu) !! 72 for_each_possible_cpu(cpu1) 75 { !! 73 if (cpu_cluster(&cpu_data[cpu1]) == cluster) 76 return init_of_cache_level(cpu); !! 74 cpumask_set_cpu(cpu1, cpu_map); 77 } 75 } 78 76 79 int populate_cache_leaves(unsigned int cpu) 77 int populate_cache_leaves(unsigned int cpu) 80 { 78 { >> 79 struct cpuinfo_mips *c = ¤t_cpu_data; 81 struct cpu_cacheinfo *this_cpu_ci = ge 80 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 82 struct cacheinfo *this_leaf = this_cpu 81 struct cacheinfo *this_leaf = this_cpu_ci->info_list; 83 struct device_node *np, *prev; !! 82 int level = 1; 84 int levels = 1, level = 1; << 85 83 86 if (!acpi_disabled) { !! 84 if (c->icache.waysize) { 87 int ret, fw_levels, split_leve !! 85 /* I/D caches are per core */ 88 !! 86 fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map); 89 ret = acpi_get_cache_info(cpu, !! 87 populate_cache(dcache, this_leaf, level, CACHE_TYPE_DATA); 90 if (ret) !! 88 fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map); 91 return ret; !! 89 populate_cache(icache, this_leaf, level, CACHE_TYPE_INST); 92 !! 90 level++; 93 BUG_ON((split_levels > fw_leve !! 91 } else { 94 (split_levels + fw_leve !! 92 populate_cache(dcache, this_leaf, level, CACHE_TYPE_UNIFIED); 95 !! 93 level++; 96 for (; level <= this_cpu_ci->n << 97 if (level <= split_lev << 98 ci_leaf_init(t << 99 ci_leaf_init(t << 100 } else { << 101 ci_leaf_init(t << 102 } << 103 } << 104 return 0; << 105 } 94 } 106 95 107 np = of_cpu_device_node_get(cpu); !! 96 if (c->vcache.waysize) { 108 if (!np) !! 97 /* Vcache is per core as well */ 109 return -ENOENT; !! 98 fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map); >> 99 populate_cache(vcache, this_leaf, level, CACHE_TYPE_UNIFIED); >> 100 level++; >> 101 } 110 102 111 if (of_property_read_bool(np, "cache-s !! 103 if (c->scache.waysize) { 112 ci_leaf_init(this_leaf++, CACH !! 104 /* Scache is per cluster */ 113 if (of_property_read_bool(np, "i-cache !! 105 fill_cpumask_cluster(cpu, &this_leaf->shared_cpu_map); 114 ci_leaf_init(this_leaf++, CACH !! 106 populate_cache(scache, this_leaf, level, CACHE_TYPE_UNIFIED); 115 if (of_property_read_bool(np, "d-cache !! 107 level++; 116 ci_leaf_init(this_leaf++, CACH << 117 << 118 prev = np; << 119 while ((np = of_find_next_cache_node(n << 120 of_node_put(prev); << 121 prev = np; << 122 if (!of_device_is_compatible(n << 123 break; << 124 if (of_property_read_u32(np, " << 125 break; << 126 if (level <= levels) << 127 break; << 128 if (of_property_read_bool(np, << 129 ci_leaf_init(this_leaf << 130 if (of_property_read_bool(np, << 131 ci_leaf_init(this_leaf << 132 if (of_property_read_bool(np, << 133 ci_leaf_init(this_leaf << 134 levels = level; << 135 } 108 } 136 of_node_put(np); !! 109 >> 110 if (c->tcache.waysize) >> 111 populate_cache(tcache, this_leaf, level, CACHE_TYPE_UNIFIED); >> 112 >> 113 this_cpu_ci->cpu_map_populated = true; 137 114 138 return 0; 115 return 0; 139 } 116 } 140 117
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.