Commit b9655e70 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

x86/cpu: Encapsulate topology information in cpuinfo_x86



The topology related information is randomly scattered across cpuinfo_x86.

Create a new structure cpuinfo_topo and move in a first step initial_apicid
and apicid into it.

Aside of being better readable this is in preparation for replacing the
horribly fragile CPU topology evaluation code further down the road.

Consolidate APIC ID fields to u32 as that represents the hardware type.

No functional change.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarJuergen Gross <jgross@suse.com>
Tested-by: default avatarSohil Mehta <sohil.mehta@intel.com>
Tested-by: default avatarMichael Kelley <mikelley@microsoft.com>
Tested-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: default avatarZhang Rui <rui.zhang@intel.com>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20230814085112.269787744@linutronix.de
parent 965e05ff
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -76,10 +76,15 @@ extern u16 __read_mostly tlb_lld_1g[NR_INFO];

/*
 * CPU type and hardware bug flags. Kept separately for each CPU.
 *  Members of this structure are referenced in head_32.S, so think twice
 *  before touching them. [mj]
 */

struct cpuinfo_topology {
	// Real APIC ID read from the local APIC
	u32			apicid;
	// The initial APIC ID provided by CPUID
	u32			initial_apicid;
};

struct cpuinfo_x86 {
	__u8			x86;		/* CPU family */
	__u8			x86_vendor;	/* CPU vendor */
@@ -112,6 +117,7 @@ struct cpuinfo_x86 {
	};
	char			x86_vendor_id[16];
	char			x86_model_id[64];
	struct cpuinfo_topology	topo;
	/* in KB - valid for CPUS which support this call: */
	unsigned int		x86_cache_size;
	int			x86_cache_alignment;	/* In bytes */
@@ -125,8 +131,6 @@ struct cpuinfo_x86 {
	u64			ppin;
	/* cpuid returned max cores value: */
	u16			x86_max_cores;
	u16			apicid;
	u16			initial_apicid;
	u16			x86_clflush_size;
	/* number of cores as seen by the OS: */
	u16			booted_cores;
+5 −5
Original line number Diff line number Diff line
@@ -459,9 +459,9 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)

	bits = c->x86_coreid_bits;
	/* Low order bits define the core id (index of core in socket) */
	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
	c->cpu_core_id = c->topo.initial_apicid & ((1 << bits)-1);
	/* Convert the initial APIC ID into the socket ID */
	c->phys_proc_id = c->initial_apicid >> bits;
	c->phys_proc_id = c->topo.initial_apicid >> bits;
	/* use socket ID also for last level cache */
	per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
}
@@ -477,7 +477,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#ifdef CONFIG_NUMA
	int cpu = smp_processor_id();
	int node;
	unsigned apicid = c->apicid;
	unsigned apicid = c->topo.apicid;

	node = numa_cpu_node(cpu);
	if (node == NUMA_NO_NODE)
@@ -511,7 +511,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
		 * through CPU mapping may alter the outcome, directly
		 * access __apicid_to_node[].
		 */
		int ht_nodeid = c->initial_apicid;
		int ht_nodeid = c->topo.initial_apicid;

		if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
			node = __apicid_to_node[ht_nodeid];
@@ -1047,7 +1047,7 @@ static void init_amd(struct cpuinfo_x86 *c)
		set_cpu_cap(c, X86_FEATURE_FSRS);

	/* get apicid instead of initial apic id from cpuid */
	c->apicid = read_apic_id();
	c->topo.apicid = read_apic_id();

	/* K6s reports MCEs but don't actually have all the MSRs */
	if (c->x86 < 6)
+10 −10
Original line number Diff line number Diff line
@@ -678,7 +678,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
		 * LLC is at the core complex level.
		 * Core complex ID is ApicId[3] for these processors.
		 */
		per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
		per_cpu(cpu_llc_id, cpu) = c->topo.apicid >> 3;
	} else {
		/*
		 * LLC ID is calculated from the number of threads sharing the
@@ -694,7 +694,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
		if (num_sharing_cache) {
			int bits = get_count_order(num_sharing_cache);

			per_cpu(cpu_llc_id, cpu) = c->apicid >> bits;
			per_cpu(cpu_llc_id, cpu) = c->topo.apicid >> bits;
		}
	}
}
@@ -712,7 +712,7 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu)
	 * LLC is at the core complex level.
	 * Core complex ID is ApicId[3] for these processors.
	 */
	per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
	per_cpu(cpu_llc_id, cpu) = c->topo.apicid >> 3;
}

void init_amd_cacheinfo(struct cpuinfo_x86 *c)
@@ -776,13 +776,13 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
				new_l2 = this_leaf.size/1024;
				num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
				index_msb = get_count_order(num_threads_sharing);
				l2_id = c->apicid & ~((1 << index_msb) - 1);
				l2_id = c->topo.apicid & ~((1 << index_msb) - 1);
				break;
			case 3:
				new_l3 = this_leaf.size/1024;
				num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
				index_msb = get_count_order(num_threads_sharing);
				l3_id = c->apicid & ~((1 << index_msb) - 1);
				l3_id = c->topo.apicid & ~((1 << index_msb) - 1);
				break;
			default:
				break;
@@ -915,7 +915,7 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
		unsigned int apicid, nshared, first, last;

		nshared = base->eax.split.num_threads_sharing + 1;
		apicid = cpu_data(cpu).apicid;
		apicid = cpu_data(cpu).topo.apicid;
		first = apicid - (apicid % nshared);
		last = first + nshared - 1;

@@ -924,14 +924,14 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
			if (!this_cpu_ci->info_list)
				continue;

			apicid = cpu_data(i).apicid;
			apicid = cpu_data(i).topo.apicid;
			if ((apicid < first) || (apicid > last))
				continue;

			this_leaf = this_cpu_ci->info_list + index;

			for_each_online_cpu(sibling) {
				apicid = cpu_data(sibling).apicid;
				apicid = cpu_data(sibling).topo.apicid;
				if ((apicid < first) || (apicid > last))
					continue;
				cpumask_set_cpu(sibling,
@@ -969,7 +969,7 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
	index_msb = get_count_order(num_threads_sharing);

	for_each_online_cpu(i)
		if (cpu_data(i).apicid >> index_msb == c->apicid >> index_msb) {
		if (cpu_data(i).topo.apicid >> index_msb == c->topo.apicid >> index_msb) {
			struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);

			if (i == cpu || !sib_cpu_ci->info_list)
@@ -1024,7 +1024,7 @@ static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4_regs)

	num_threads_sharing = 1 + id4_regs->eax.split.num_threads_sharing;
	index_msb = get_count_order(num_threads_sharing);
	id4_regs->id = c->apicid >> index_msb;
	id4_regs->id = c->topo.apicid >> index_msb;
}

int populate_cache_leaves(unsigned int cpu)
+9 −9
Original line number Diff line number Diff line
@@ -914,7 +914,7 @@ void detect_ht(struct cpuinfo_x86 *c)
		return;

	index_msb = get_count_order(smp_num_siblings);
	c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
	c->phys_proc_id = apic->phys_pkg_id(c->topo.initial_apicid, index_msb);

	smp_num_siblings = smp_num_siblings / c->x86_max_cores;

@@ -922,7 +922,7 @@ void detect_ht(struct cpuinfo_x86 *c)

	core_bits = get_count_order(c->x86_max_cores);

	c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
	c->cpu_core_id = apic->phys_pkg_id(c->topo.initial_apicid, index_msb) &
				       ((1 << core_bits) - 1);
#endif
}
@@ -1761,15 +1761,15 @@ static void generic_identify(struct cpuinfo_x86 *c)
	get_cpu_address_sizes(c);

	if (c->cpuid_level >= 0x00000001) {
		c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
		c->topo.initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
#ifdef CONFIG_X86_32
# ifdef CONFIG_SMP
		c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
		c->topo.apicid = apic->phys_pkg_id(c->topo.initial_apicid, 0);
# else
		c->apicid = c->initial_apicid;
		c->topo.apicid = c->topo.initial_apicid;
# endif
#endif
		c->phys_proc_id = c->initial_apicid;
		c->phys_proc_id = c->topo.initial_apicid;
	}

	get_model_name(c); /* Default name */
@@ -1803,9 +1803,9 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c)

	apicid = apic->cpu_present_to_apicid(cpu);

	if (apicid != c->apicid) {
	if (apicid != c->topo.apicid) {
		pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x APIC: %x\n",
		       cpu, apicid, c->initial_apicid);
		       cpu, apicid, c->topo.initial_apicid);
	}
	BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
	BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
@@ -1855,7 +1855,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
	apply_forced_caps(c);

#ifdef CONFIG_X86_64
	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
	c->topo.apicid = apic->phys_pkg_id(c->topo.initial_apicid, 0);
#endif

	/*
+6 −6
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
		 * when running on host.
		 */
		if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && c->x86_model <= 0x3)
			c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
			c->phys_proc_id = c->topo.apicid >> APICID_SOCKET_ID_BIT;

		cacheinfo_hygon_init_llc_id(c, cpu);
	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
@@ -120,9 +120,9 @@ static void hygon_detect_cmp(struct cpuinfo_x86 *c)

	bits = c->x86_coreid_bits;
	/* Low order bits define the core id (index of core in socket) */
	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
	c->cpu_core_id = c->topo.initial_apicid & ((1 << bits)-1);
	/* Convert the initial APIC ID into the socket ID */
	c->phys_proc_id = c->initial_apicid >> bits;
	c->phys_proc_id = c->topo.initial_apicid >> bits;
	/* use socket ID also for last level cache */
	per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
}
@@ -132,7 +132,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#ifdef CONFIG_NUMA
	int cpu = smp_processor_id();
	int node;
	unsigned int apicid = c->apicid;
	unsigned int apicid = c->topo.apicid;

	node = numa_cpu_node(cpu);
	if (node == NUMA_NO_NODE)
@@ -165,7 +165,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
		 * through CPU mapping may alter the outcome, directly
		 * access __apicid_to_node[].
		 */
		int ht_nodeid = c->initial_apicid;
		int ht_nodeid = c->topo.initial_apicid;

		if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
			node = __apicid_to_node[ht_nodeid];
@@ -305,7 +305,7 @@ static void init_hygon(struct cpuinfo_x86 *c)
	set_cpu_cap(c, X86_FEATURE_REP_GOOD);

	/* get apicid instead of initial apic id from cpuid */
	c->apicid = read_apic_id();
	c->topo.apicid = read_apic_id();

	/*
	 * XXX someone from Hygon needs to confirm this DTRT
Loading