^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) * Check for extended topology enumeration cpuid leaf 0xb and if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * exists, use it for populating initial_apicid and cpu topology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/apic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/memtype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "cpu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* leaf 0xb SMT level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define SMT_LEVEL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* extended topology sub-leaf types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define INVALID_TYPE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SMT_TYPE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define CORE_TYPE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define DIE_TYPE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int __max_die_per_package __read_mostly = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) EXPORT_SYMBOL(__max_die_per_package);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Check if given CPUID extended toplogy "leaf" is implemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int check_extended_topology_leaf(int leaf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned int eax, ebx, ecx, edx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0;
^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) * Return best CPUID Extended Toplogy Leaf supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int detect_extended_topology_leaf(struct cpuinfo_x86 *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (c->cpuid_level >= 0x1f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (check_extended_topology_leaf(0x1f) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (c->cpuid_level >= 0xb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (check_extended_topology_leaf(0xb) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return 0xb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int detect_extended_topology_early(struct cpuinfo_x86 *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int eax, ebx, ecx, edx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) leaf = detect_extended_topology_leaf(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (leaf < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * initial apic id, which also represents 32-bit extended x2apic id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) c->initial_apicid = edx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Check for extended topology enumeration cpuid leaf, and if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * exists, use it for populating initial_apicid and cpu topology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int detect_extended_topology(struct cpuinfo_x86 *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int eax, ebx, ecx, edx, sub_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int core_select_mask, core_level_siblings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int die_select_mask, die_level_siblings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) leaf = detect_extended_topology_leaf(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (leaf < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Populate HT related information from sub-leaf level 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) c->initial_apicid = edx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) sub_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Check for the Core type in the implemented sub leaves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) die_level_siblings = core_level_siblings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (LEAFB_SUBTYPE(ecx) == DIE_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) sub_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) die_select_mask = (~(-1 << die_plus_mask_width)) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) core_plus_mask_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ht_mask_width) & core_select_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) core_plus_mask_width) & die_select_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) die_plus_mask_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Reinit the apicid, now that we have extended initial_apicid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) c->x86_max_cores = (core_level_siblings / smp_num_siblings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) __max_die_per_package = (die_level_siblings / core_level_siblings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }