1515#include <linux/arch_topology.h>
1616#include <linux/cacheinfo.h>
1717#include <linux/cpufreq.h>
18+ #include <linux/cpu_smt.h>
1819#include <linux/init.h>
1920#include <linux/percpu.h>
2021#include <linux/sched/isolation.h>
22+ #include <linux/xarray.h>
2123
2224#include <asm/cpu.h>
2325#include <asm/cputype.h>
@@ -38,17 +40,28 @@ static bool __init acpi_cpu_is_threaded(int cpu)
3840 return !!is_threaded ;
3941}
4042
43+ struct cpu_smt_info {
44+ unsigned int thread_num ;
45+ int core_id ;
46+ };
47+
4148/*
4249 * Propagate the topology information of the processor_topology_node tree to the
4350 * cpu_topology array.
4451 */
4552int __init parse_acpi_topology (void )
4653{
54+ unsigned int max_smt_thread_num = 1 ;
55+ struct cpu_smt_info * entry ;
56+ struct xarray hetero_cpu ;
57+ unsigned long hetero_id ;
4758 int cpu , topology_id ;
4859
4960 if (acpi_disabled )
5061 return 0 ;
5162
63+ xa_init (& hetero_cpu );
64+
5265 for_each_possible_cpu (cpu ) {
5366 topology_id = find_acpi_cpu_topology (cpu , 0 );
5467 if (topology_id < 0 )
@@ -58,6 +71,34 @@ int __init parse_acpi_topology(void)
5871 cpu_topology [cpu ].thread_id = topology_id ;
5972 topology_id = find_acpi_cpu_topology (cpu , 1 );
6073 cpu_topology [cpu ].core_id = topology_id ;
74+
75+ /*
76+ * In the PPTT, CPUs below a node with the 'identical
77+ * implementation' flag have the same number of threads.
78+ * Count the number of threads for only one CPU (i.e.
79+ * one core_id) among those with the same hetero_id.
80+ * See the comment of find_acpi_cpu_topology_hetero_id()
81+ * for more details.
82+ *
83+ * One entry is created for each node having:
84+ * - the 'identical implementation' flag
85+ * - its parent not having the flag
86+ */
87+ hetero_id = find_acpi_cpu_topology_hetero_id (cpu );
88+ entry = xa_load (& hetero_cpu , hetero_id );
89+ if (!entry ) {
90+ entry = kzalloc (sizeof (* entry ), GFP_KERNEL );
91+ WARN_ON_ONCE (!entry );
92+
93+ if (entry ) {
94+ entry -> core_id = topology_id ;
95+ entry -> thread_num = 1 ;
96+ xa_store (& hetero_cpu , hetero_id ,
97+ entry , GFP_KERNEL );
98+ }
99+ } else if (entry -> core_id == topology_id ) {
100+ entry -> thread_num ++ ;
101+ }
61102 } else {
62103 cpu_topology [cpu ].thread_id = -1 ;
63104 cpu_topology [cpu ].core_id = topology_id ;
@@ -68,6 +109,19 @@ int __init parse_acpi_topology(void)
68109 cpu_topology [cpu ].package_id = topology_id ;
69110 }
70111
112+ /*
113+ * This is a short loop since the number of XArray elements is the
114+ * number of heterogeneous CPU clusters. On a homogeneous system
115+ * there's only one entry in the XArray.
116+ */
117+ xa_for_each (& hetero_cpu , hetero_id , entry ) {
118+ max_smt_thread_num = max (max_smt_thread_num , entry -> thread_num );
119+ xa_erase (& hetero_cpu , hetero_id );
120+ kfree (entry );
121+ }
122+
123+ cpu_smt_set_num_threads (max_smt_thread_num , max_smt_thread_num );
124+ xa_destroy (& hetero_cpu );
71125 return 0 ;
72126}
73127#endif
0 commit comments