^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * pptt.c - parsing of Processor Properties Topology Table (PPTT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018, ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file implements parsing of the Processor Properties Topology Table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * which is optionally used to describe the processor and cache topology.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Due to the relative pointers used throughout the table, this doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * leverage the existing subtable parsing in the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * The PPTT structure is an inverted tree, with each node potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * holding one or two inverted tree data structures describing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the caches available at that level. Each cache structure optionally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * contains properties describing the cache at a given level which can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * used to override hardware probed values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define pr_fmt(fmt) "ACPI PPTT: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/cacheinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <acpi/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static struct acpi_subtable_header *fetch_pptt_subtable(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u32 pptt_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct acpi_subtable_header *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* there isn't a subtable at reference 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (pptt_ref < sizeof(struct acpi_subtable_header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (pptt_ref + sizeof(struct acpi_subtable_header) > table_hdr->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, pptt_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (entry->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (pptt_ref + entry->length > table_hdr->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct acpi_pptt_processor *fetch_pptt_node(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 pptt_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return (struct acpi_pptt_processor *)fetch_pptt_subtable(table_hdr, pptt_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static struct acpi_pptt_cache *fetch_pptt_cache(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 pptt_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return (struct acpi_pptt_cache *)fetch_pptt_subtable(table_hdr, pptt_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct acpi_subtable_header *acpi_get_pptt_resource(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct acpi_pptt_processor *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (resource >= node->number_of_priv_resources)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ref = ACPI_ADD_PTR(u32, node, sizeof(struct acpi_pptt_processor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ref += resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return fetch_pptt_subtable(table_hdr, *ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static inline bool acpi_pptt_match_type(int table_type, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ((table_type & ACPI_PPTT_MASK_CACHE_TYPE) == type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) table_type & ACPI_PPTT_CACHE_TYPE_UNIFIED & type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * @table_hdr: Pointer to the head of the PPTT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @local_level: passed res reflects this cache level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @res: cache resource in the PPTT we want to walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @found: returns a pointer to the requested level if found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @level: the requested cache level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @type: the requested cache type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Attempt to find a given cache level, while counting the max number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * of cache levels for the cache node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * Given a pptt resource, verify that it is a cache node, then walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * down each level of caches, counting how many levels are found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * as well as checking the cache type (icache, dcache, unified). If a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * level & type match, then we set found, and continue the search.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Once the entire cache branch has been walked return its max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * depth.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Return: The cache structure and the level we terminated with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int local_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct acpi_subtable_header *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct acpi_pptt_cache **found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned int level, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct acpi_pptt_cache *cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (res->type != ACPI_PPTT_TYPE_CACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) cache = (struct acpi_pptt_cache *) res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) while (cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) local_level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (local_level == level &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cache->flags & ACPI_PPTT_CACHE_TYPE_VALID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) acpi_pptt_match_type(cache->attributes, type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (*found != NULL && cache != *found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pr_warn("Found duplicate cache level/type unable to determine uniqueness\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) pr_debug("Found cache @ level %u\n", level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *found = cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * continue looking at this node's resource list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * to verify that we don't find a duplicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * cache node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return local_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static struct acpi_pptt_cache *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) acpi_find_cache_level(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct acpi_pptt_processor *cpu_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int *starting_level, unsigned int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct acpi_subtable_header *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned int number_of_levels = *starting_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int resource = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct acpi_pptt_cache *ret = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int local_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* walk down from processor node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) while ((res = acpi_get_pptt_resource(table_hdr, cpu_node, resource))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) resource++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) local_level = acpi_pptt_walk_cache(table_hdr, *starting_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) res, &ret, level, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * we are looking for the max depth. Since its potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * possible for a given node to have resources with differing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * depths verify that the depth we have found is the largest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (number_of_levels < local_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) number_of_levels = local_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (number_of_levels > *starting_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *starting_level = number_of_levels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * acpi_count_levels() - Given a PPTT table, and a CPU node, count the caches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @table_hdr: Pointer to the head of the PPTT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @cpu_node: processor node we wish to count caches for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Given a processor node containing a processing unit, walk into it and count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * how many levels exist solely for it, and then walk up each level until we hit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * the root node (ignore the package level because it may be possible to have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * caches that exist across packages). Count the number of cache levels that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * exist at each level on the way up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Return: Total number of levels found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static int acpi_count_levels(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct acpi_pptt_processor *cpu_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int total_levels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) } while (cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return total_levels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * acpi_pptt_leaf_node() - Given a processor node, determine if its a leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @table_hdr: Pointer to the head of the PPTT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @node: passed node is checked to see if its a leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Determine if the *node parameter is a leaf node by iterating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * PPTT table, looking for nodes which reference it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * Return: 0 if we find a node referencing the passed node (or table error),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * or 1 if we don't.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct acpi_pptt_processor *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct acpi_subtable_header *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned long table_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u32 node_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct acpi_pptt_processor *cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 proc_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (table_hdr->revision > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return (node->flags & ACPI_PPTT_ACPI_LEAF_NODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) table_end = (unsigned long)table_hdr + table_hdr->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) node_entry = ACPI_PTR_DIFF(node, table_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) sizeof(struct acpi_table_pptt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) proc_sz = sizeof(struct acpi_pptt_processor *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) while ((unsigned long)entry + proc_sz < table_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cpu_node = (struct acpi_pptt_processor *)entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) cpu_node->parent == node_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (entry->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) entry->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * acpi_find_processor_node() - Given a PPTT table find the requested processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @table_hdr: Pointer to the head of the PPTT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * @acpi_cpu_id: CPU we are searching for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Find the subtable entry describing the provided processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * This is done by iterating the PPTT table looking for processor nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * which have an acpi_processor_id that matches the acpi_cpu_id parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * passed into the function. If we find a node that matches this criteria
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * we verify that its a leaf node in the topology rather than depending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * on the valid flag, which doesn't need to be set for leaf nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * Return: NULL, or the processors acpi_pptt_processor*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u32 acpi_cpu_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct acpi_subtable_header *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned long table_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct acpi_pptt_processor *cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u32 proc_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) table_end = (unsigned long)table_hdr + table_hdr->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sizeof(struct acpi_table_pptt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) proc_sz = sizeof(struct acpi_pptt_processor *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* find the processor structure associated with this cpuid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) while ((unsigned long)entry + proc_sz < table_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) cpu_node = (struct acpi_pptt_processor *)entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (entry->length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) pr_warn("Invalid zero length subtable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) acpi_cpu_id == cpu_node->acpi_processor_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) acpi_pptt_leaf_node(table_hdr, cpu_node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return (struct acpi_pptt_processor *)entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) entry->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int acpi_find_cache_levels(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 acpi_cpu_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int number_of_levels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct acpi_pptt_processor *cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) cpu = acpi_find_processor_node(table_hdr, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) number_of_levels = acpi_count_levels(table_hdr, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return number_of_levels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static u8 acpi_cache_type(enum cache_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case CACHE_TYPE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pr_debug("Looking for data cache\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return ACPI_PPTT_CACHE_TYPE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case CACHE_TYPE_INST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pr_debug("Looking for instruction cache\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ACPI_PPTT_CACHE_TYPE_INSTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case CACHE_TYPE_UNIFIED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pr_debug("Looking for unified cache\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * It is important that ACPI_PPTT_CACHE_TYPE_UNIFIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * contains the bit pattern that will match both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * ACPI unified bit patterns because we use it later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * to match both cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return ACPI_PPTT_CACHE_TYPE_UNIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u32 acpi_cpu_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) enum cache_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) unsigned int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct acpi_pptt_processor **node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned int total_levels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct acpi_pptt_cache *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct acpi_pptt_processor *cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u8 acpi_type = acpi_cache_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) pr_debug("Looking for CPU %d's level %u cache type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) acpi_cpu_id, level, acpi_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) cpu_node = acpi_find_processor_node(table_hdr, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) while (cpu_node && !found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) found = acpi_find_cache_level(table_hdr, cpu_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) &total_levels, level, acpi_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *node = cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * update_cache_properties() - Update cacheinfo for the given processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * @this_leaf: Kernel cache info structure being updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * @found_cache: The PPTT node describing this cache instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @cpu_node: A unique reference to describe this cache instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * The ACPI spec implies that the fields in the cache structures are used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * extend and correct the information probed from the hardware. Lets only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * set fields that we determine are VALID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Return: nothing. Side effect of updating the global cacheinfo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static void update_cache_properties(struct cacheinfo *this_leaf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct acpi_pptt_cache *found_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct acpi_pptt_processor *cpu_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) this_leaf->fw_token = cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) this_leaf->size = found_cache->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) this_leaf->coherency_line_size = found_cache->line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) this_leaf->number_of_sets = found_cache->number_of_sets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) this_leaf->ways_of_associativity = found_cache->associativity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) switch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case ACPI_PPTT_CACHE_POLICY_WT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) this_leaf->attributes = CACHE_WRITE_THROUGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case ACPI_PPTT_CACHE_POLICY_WB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) this_leaf->attributes = CACHE_WRITE_BACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (found_cache->flags & ACPI_PPTT_ALLOCATION_TYPE_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) switch (found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case ACPI_PPTT_CACHE_READ_ALLOCATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) this_leaf->attributes |= CACHE_READ_ALLOCATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case ACPI_PPTT_CACHE_WRITE_ALLOCATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) this_leaf->attributes |= CACHE_WRITE_ALLOCATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case ACPI_PPTT_CACHE_RW_ALLOCATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case ACPI_PPTT_CACHE_RW_ALLOCATE_ALT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) this_leaf->attributes |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * If cache type is NOCACHE, then the cache hasn't been specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * via other mechanisms. Update the type if a cache type has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Note, we assume such caches are unified based on conventional system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * design and known examples. Significant work is required elsewhere to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * fully support data/instruction only type caches which are only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * specified in PPTT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (this_leaf->type == CACHE_TYPE_NOCACHE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) found_cache->flags & ACPI_PPTT_CACHE_TYPE_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) this_leaf->type = CACHE_TYPE_UNIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void cache_setup_acpi_cpu(struct acpi_table_header *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct acpi_pptt_cache *found_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct cacheinfo *this_leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) unsigned int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct acpi_pptt_processor *cpu_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) while (index < get_cpu_cacheinfo(cpu)->num_leaves) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) this_leaf = this_cpu_ci->info_list + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) found_cache = acpi_find_cache_node(table, acpi_cpu_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) this_leaf->type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) this_leaf->level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) &cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pr_debug("found = %p %p\n", found_cache, cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (found_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) update_cache_properties(this_leaf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) found_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static bool flag_identical(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct acpi_pptt_processor *cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct acpi_pptt_processor *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* heterogeneous machines must use PPTT revision > 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (table_hdr->revision < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* Locate the last node in the tree with IDENTICAL set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (cpu->flags & ACPI_PPTT_ACPI_IDENTICAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) next = fetch_pptt_node(table_hdr, cpu->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!(next && next->flags & ACPI_PPTT_ACPI_IDENTICAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Passing level values greater than this will result in search termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) #define PPTT_ABORT_PACKAGE 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static struct acpi_pptt_processor *acpi_find_processor_tag(struct acpi_table_header *table_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct acpi_pptt_processor *cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) int level, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct acpi_pptt_processor *prev_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) while (cpu && level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* special case the identical flag to find last identical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (flag == ACPI_PPTT_ACPI_IDENTICAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (flag_identical(table_hdr, cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) } else if (cpu->flags & flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) pr_debug("level %d\n", level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) prev_node = fetch_pptt_node(table_hdr, cpu->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (prev_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) cpu = prev_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) level--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static void acpi_pptt_warn_missing(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) pr_warn_once("No PPTT table found, CPU and cache topology may be inaccurate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * topology_get_acpi_cpu_tag() - Find a unique topology value for a feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * @table: Pointer to the head of the PPTT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * @level: A level that terminates the search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * @flag: A flag which terminates the search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * Get a unique value given a CPU, and a topology level, that can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * matched to determine which cpus share common topological features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * at that level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * Return: Unique value, or -ENOENT if unable to locate CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static int topology_get_acpi_cpu_tag(struct acpi_table_header *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) unsigned int cpu, int level, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct acpi_pptt_processor *cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (cpu_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) cpu_node = acpi_find_processor_tag(table, cpu_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) level, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * As per specification if the processor structure represents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * an actual processor, then ACPI processor ID must be valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * For processor containers ACPI_PPTT_ACPI_PROCESSOR_ID_VALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * should be set if the UID is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (level == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return cpu_node->acpi_processor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return ACPI_PTR_DIFF(cpu_node, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pr_warn_once("PPTT table found, but unable to locate core %d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cpu, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct acpi_table_header *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) acpi_pptt_warn_missing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) retval = topology_get_acpi_cpu_tag(table, cpu, level, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pr_debug("Topology Setup ACPI CPU %d, level %d ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) cpu, level, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) acpi_put_table(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * check_acpi_cpu_flag() - Determine if CPU node has a flag set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * @rev: The minimum PPTT revision defining the flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * @flag: The flag itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * Check the node representing a CPU for a given flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * the table revision isn't new enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * 1, any passed flag set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * 0, flag unset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct acpi_table_header *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct acpi_pptt_processor *cpu_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) acpi_pptt_warn_missing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (table->revision >= rev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (cpu_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ret = (cpu_node->flags & flag) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) acpi_put_table(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * acpi_find_last_cache_level() - Determines the number of cache levels for a PE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * Given a logical CPU number, returns the number of levels of cache represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * indicating we didn't find any cache levels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * Return: Cache levels visible to this core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) int acpi_find_last_cache_level(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u32 acpi_cpu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct acpi_table_header *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int number_of_levels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pr_debug("Cache Setup find last level CPU=%d\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) acpi_cpu_id = get_acpi_id_for_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) acpi_pptt_warn_missing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) acpi_put_table(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) pr_debug("Cache Setup find last level level=%d\n", number_of_levels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return number_of_levels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * cache_setup_acpi() - Override CPU cache topology with data from the PPTT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * Updates the global cache info provided by cpu_get_cacheinfo()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * when there are valid properties in the acpi_pptt_cache nodes. A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * successful parse may not result in any updates if none of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * cache levels have any valid flags set. Further, a unique value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * associated with each known CPU cache entry. This unique value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * can be used to determine whether caches are shared between CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * Return: -ENOENT on failure to find table, or 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) int cache_setup_acpi(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct acpi_table_header *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) pr_debug("Cache Setup ACPI CPU %d\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) acpi_pptt_warn_missing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) cache_setup_acpi_cpu(table, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) acpi_put_table(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * acpi_pptt_cpu_is_thread() - Determine if CPU is a thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * Return: 1, a thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * 0, not a thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * -ENOENT ,if the PPTT doesn't exist, the CPU cannot be found or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * the table revision isn't new enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int acpi_pptt_cpu_is_thread(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return check_acpi_cpu_flag(cpu, 2, ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * find_acpi_cpu_topology() - Determine a unique topology value for a given CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * @level: The topological level for which we would like a unique ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * Determine a topology unique ID for each thread/core/cluster/mc_grouping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * /socket/etc. This ID can then be used to group peers, which will have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * matching ids.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * The search terminates when either the requested level is found or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * we reach a root node. Levels beyond the termination point will return the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * same unique ID. The unique id for level 0 is the acpi processor id. All
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * other levels beyond this use a generated value to uniquely identify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * a topological feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * Otherwise returns a value which represents a unique topological feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int find_acpi_cpu_topology(unsigned int cpu, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return find_acpi_cpu_topology_tag(cpu, level, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * find_acpi_cpu_cache_topology() - Determine a unique cache topology value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @level: The cache level for which we would like a unique ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * Determine a unique ID for each unified cache in the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * Otherwise returns a value which represents a unique topological feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int find_acpi_cpu_cache_topology(unsigned int cpu, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct acpi_table_header *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct acpi_pptt_cache *found_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct acpi_pptt_processor *cpu_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) acpi_pptt_warn_missing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) found_cache = acpi_find_cache_node(table, acpi_cpu_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) CACHE_TYPE_UNIFIED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) &cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (found_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ret = ACPI_PTR_DIFF(cpu_node, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) acpi_put_table(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * find_acpi_cpu_topology_package() - Determine a unique CPU package value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * Determine a topology unique package ID for the given CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * This ID can then be used to group peers, which will have matching ids.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * The search terminates when either a level is found with the PHYSICAL_PACKAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * flag set or we reach a root node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * Otherwise returns a value which represents the package for this CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int find_acpi_cpu_topology_package(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ACPI_PPTT_PHYSICAL_PACKAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * find_acpi_cpu_topology_hetero_id() - Get a core architecture tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * @cpu: Kernel logical CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * Determine a unique heterogeneous tag for the given CPU. CPUs with the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * implementation should have matching tags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * The returned tag can be used to group peers with identical implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * The search terminates when a level is found with the identical implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * flag set or we reach a root node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * Due to limitations in the PPTT data structure, there may be rare situations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * where two cores in a heterogeneous machine may be identical, but won't have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * the same tag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * Otherwise returns a value which represents a group of identical cores
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * similar to this CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) int find_acpi_cpu_topology_hetero_id(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ACPI_PPTT_ACPI_IDENTICAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }