1628c3bb4SHuacai Chen // SPDX-License-Identifier: GPL-2.0-only 2628c3bb4SHuacai Chen /* 3628c3bb4SHuacai Chen * LoongArch cacheinfo support 4628c3bb4SHuacai Chen * 5628c3bb4SHuacai Chen * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6628c3bb4SHuacai Chen */ 7628c3bb4SHuacai Chen #include <linux/cacheinfo.h> 8*b61a40afSHuacai Chen #include <linux/topology.h> 91aea29d7SHuacai Chen #include <asm/bootinfo.h> 101aea29d7SHuacai Chen #include <asm/cpu-info.h> 11628c3bb4SHuacai Chen init_cache_level(unsigned int cpu)12628c3bb4SHuacai Chenint init_cache_level(unsigned int cpu) 13628c3bb4SHuacai Chen { 14*b61a40afSHuacai Chen int cache_present = current_cpu_data.cache_leaves_present; 15628c3bb4SHuacai Chen struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 16628c3bb4SHuacai Chen 17*b61a40afSHuacai Chen this_cpu_ci->num_levels = 18*b61a40afSHuacai Chen current_cpu_data.cache_leaves[cache_present - 1].level; 19*b61a40afSHuacai Chen this_cpu_ci->num_leaves = cache_present; 20628c3bb4SHuacai Chen 21628c3bb4SHuacai Chen return 0; 22628c3bb4SHuacai Chen } 23628c3bb4SHuacai Chen cache_leaves_are_shared(struct cacheinfo * this_leaf,struct cacheinfo * sib_leaf)24628c3bb4SHuacai Chenstatic inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, 25628c3bb4SHuacai Chen struct cacheinfo *sib_leaf) 26628c3bb4SHuacai Chen { 27*b61a40afSHuacai Chen return (!(*(unsigned char *)(this_leaf->priv) & CACHE_PRIVATE) 28*b61a40afSHuacai Chen && !(*(unsigned char *)(sib_leaf->priv) & CACHE_PRIVATE)); 29628c3bb4SHuacai Chen } 30628c3bb4SHuacai Chen cache_cpumap_setup(unsigned int cpu)31628c3bb4SHuacai Chenstatic void cache_cpumap_setup(unsigned int cpu) 32628c3bb4SHuacai Chen { 33628c3bb4SHuacai Chen unsigned int index; 34*b61a40afSHuacai Chen struct cacheinfo *this_leaf, *sib_leaf; 35*b61a40afSHuacai Chen struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 36628c3bb4SHuacai Chen 37628c3bb4SHuacai Chen for (index = 0; index < this_cpu_ci->num_leaves; index++) { 38628c3bb4SHuacai Chen unsigned int i; 39628c3bb4SHuacai Chen 40628c3bb4SHuacai Chen this_leaf = this_cpu_ci->info_list + index; 41628c3bb4SHuacai Chen /* skip if shared_cpu_map is already populated */ 42628c3bb4SHuacai Chen if (!cpumask_empty(&this_leaf->shared_cpu_map)) 43628c3bb4SHuacai Chen continue; 44628c3bb4SHuacai Chen 45628c3bb4SHuacai Chen cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); 46628c3bb4SHuacai Chen for_each_online_cpu(i) { 47628c3bb4SHuacai Chen struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i); 48628c3bb4SHuacai Chen 49*b61a40afSHuacai Chen if (i == cpu || !sib_cpu_ci->info_list || 50*b61a40afSHuacai Chen (cpu_to_node(i) != cpu_to_node(cpu))) 51*b61a40afSHuacai Chen continue; 52*b61a40afSHuacai Chen 53628c3bb4SHuacai Chen sib_leaf = sib_cpu_ci->info_list + index; 54628c3bb4SHuacai Chen if (cache_leaves_are_shared(this_leaf, sib_leaf)) { 55628c3bb4SHuacai Chen cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); 56628c3bb4SHuacai Chen cpumask_set_cpu(i, &this_leaf->shared_cpu_map); 57628c3bb4SHuacai Chen } 58628c3bb4SHuacai Chen } 59628c3bb4SHuacai Chen } 60628c3bb4SHuacai Chen } 61628c3bb4SHuacai Chen populate_cache_leaves(unsigned int cpu)62628c3bb4SHuacai Chenint populate_cache_leaves(unsigned int cpu) 63628c3bb4SHuacai Chen { 64*b61a40afSHuacai Chen int i, cache_present = current_cpu_data.cache_leaves_present; 65628c3bb4SHuacai Chen struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 66628c3bb4SHuacai Chen struct cacheinfo *this_leaf = this_cpu_ci->info_list; 67*b61a40afSHuacai Chen struct cache_desc *cd, *cdesc = current_cpu_data.cache_leaves; 68628c3bb4SHuacai Chen 69*b61a40afSHuacai Chen for (i = 0; i < cache_present; i++) { 70*b61a40afSHuacai Chen cd = cdesc + i; 711aea29d7SHuacai Chen 72*b61a40afSHuacai Chen this_leaf->type = cd->type; 73*b61a40afSHuacai Chen this_leaf->level = cd->level; 74*b61a40afSHuacai Chen this_leaf->coherency_line_size = cd->linesz; 75*b61a40afSHuacai Chen this_leaf->number_of_sets = cd->sets; 76*b61a40afSHuacai Chen this_leaf->ways_of_associativity = cd->ways; 77*b61a40afSHuacai Chen this_leaf->size = cd->linesz * cd->sets * cd->ways; 78*b61a40afSHuacai Chen this_leaf->priv = &cd->flags; 79*b61a40afSHuacai Chen this_leaf++; 80628c3bb4SHuacai Chen } 81628c3bb4SHuacai Chen 82628c3bb4SHuacai Chen cache_cpumap_setup(cpu); 83628c3bb4SHuacai Chen this_cpu_ci->cpu_map_populated = true; 84628c3bb4SHuacai Chen 85628c3bb4SHuacai Chen return 0; 86628c3bb4SHuacai Chen } 87