Skip to content

Commit e6b18eb

Browse files
Yicong Yangctmarinas
authored andcommitted
arm64: topology: Support SMT control on ACPI based system
For ACPI we'll build the topology from PPTT and we cannot directly get the SMT number of each core. Instead using a temporary xarray to record the heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL) and SMT information of the first core in its heterogeneous CPU cluster when building the topology. Then we can know the largest SMT number in the system. If a homogeneous system's using ACPI 6.2 or later, all the CPUs should be under the root node of PPTT. There'll be only one entry in the xarray and all the CPUs in the system will be assumed identical. The framework's SMT control provides two interface to the users [1] through /sys/devices/system/cpu/smt/control (Documentation/ABI/testing/sysfs-devices-system-cpu): 1) enable SMT by writing "on" and disable by "off" 2) enable SMT by writing max_thread_number or disable by writing 1 Both method support to completely disable/enable the SMT cores so both work correctly for symmetric SMT platform and asymmetric platform with non-SMT and one type SMT cores like: core A: 1 thread core B: X (X!=1) threads Note that for a theoretically possible multiple SMT-X (X>1) core platform the SMT control is also supported as expected but only by writing the "on/off" method. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Hanjun Guo <guohanjun@huawei.com> Reviewed-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com> Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com> Link: https://lore.kernel.org/r/20250311075143.61078-4-yangyicong@huawei.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 5deb9c7 commit e6b18eb

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

arch/arm64/kernel/topology.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
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>
21+
#include <linux/xarray.h>
2022

2123
#include <asm/cpu.h>
2224
#include <asm/cputype.h>
@@ -37,17 +39,28 @@ static bool __init acpi_cpu_is_threaded(int cpu)
3739
return !!is_threaded;
3840
}
3941

42+
struct cpu_smt_info {
43+
unsigned int thread_num;
44+
int core_id;
45+
};
46+
4047
/*
4148
* Propagate the topology information of the processor_topology_node tree to the
4249
* cpu_topology array.
4350
*/
4451
int __init parse_acpi_topology(void)
4552
{
53+
unsigned int max_smt_thread_num = 1;
54+
struct cpu_smt_info *entry;
55+
struct xarray hetero_cpu;
56+
unsigned long hetero_id;
4657
int cpu, topology_id;
4758

4859
if (acpi_disabled)
4960
return 0;
5061

62+
xa_init(&hetero_cpu);
63+
5164
for_each_possible_cpu(cpu) {
5265
topology_id = find_acpi_cpu_topology(cpu, 0);
5366
if (topology_id < 0)
@@ -57,6 +70,34 @@ int __init parse_acpi_topology(void)
5770
cpu_topology[cpu].thread_id = topology_id;
5871
topology_id = find_acpi_cpu_topology(cpu, 1);
5972
cpu_topology[cpu].core_id = topology_id;
73+
74+
/*
75+
* In the PPTT, CPUs below a node with the 'identical
76+
* implementation' flag have the same number of threads.
77+
* Count the number of threads for only one CPU (i.e.
78+
* one core_id) among those with the same hetero_id.
79+
* See the comment of find_acpi_cpu_topology_hetero_id()
80+
* for more details.
81+
*
82+
* One entry is created for each node having:
83+
* - the 'identical implementation' flag
84+
* - its parent not having the flag
85+
*/
86+
hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
87+
entry = xa_load(&hetero_cpu, hetero_id);
88+
if (!entry) {
89+
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
90+
WARN_ON_ONCE(!entry);
91+
92+
if (entry) {
93+
entry->core_id = topology_id;
94+
entry->thread_num = 1;
95+
xa_store(&hetero_cpu, hetero_id,
96+
entry, GFP_KERNEL);
97+
}
98+
} else if (entry->core_id == topology_id) {
99+
entry->thread_num++;
100+
}
60101
} else {
61102
cpu_topology[cpu].thread_id = -1;
62103
cpu_topology[cpu].core_id = topology_id;
@@ -67,6 +108,19 @@ int __init parse_acpi_topology(void)
67108
cpu_topology[cpu].package_id = topology_id;
68109
}
69110

111+
/*
112+
* This is a short loop since the number of XArray elements is the
113+
* number of heterogeneous CPU clusters. On a homogeneous system
114+
* there's only one entry in the XArray.
115+
*/
116+
xa_for_each(&hetero_cpu, hetero_id, entry) {
117+
max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
118+
xa_erase(&hetero_cpu, hetero_id);
119+
kfree(entry);
120+
}
121+
122+
cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
123+
xa_destroy(&hetero_cpu);
70124
return 0;
71125
}
72126
#endif

0 commit comments

Comments
 (0)