diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 11a465243f660a1413026901ea02d00375f3b536..ecd02a7e1506a23d479fa54ad99b5831df39dcf2 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -4,6 +4,11 @@ #include +#ifdef CONFIG_ACPI +#define topology_die_id(cpu) (cpu_topology[cpu].die_id) +#define topology_die_cpumask(cpu) (&cpu_topology[cpu].die_cpus) +#endif + #ifdef CONFIG_NUMA struct pci_bus; diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 543c67cae02ff7d4c96dc027e85ec3d2b075ecc9..0b8f25c46daf5b71f4c852c21025ba2228593f30 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -121,6 +121,31 @@ int __init parse_acpi_topology(void) return 0; } + +static int cpu_die_map[NR_CPUS] __initdata = {[0 ... (NR_CPUS - 1)] = -1}; + +static int __init cpu_topology_die_map(void) +{ + int cpu, iter, die_id; + + acpi_cpu_die_init(cpu_die_map); + for_each_possible_cpu(cpu) { + die_id = cpu_die_map[cpu]; + cpu_topology[cpu].die_id = die_id; + cpumask_set_cpu(cpu, &cpu_topology[cpu].die_cpus); + if (die_id < 0) + continue; + for (iter = 0; iter < cpu; iter++) { + if (cpu_topology[iter].die_id != die_id) + continue; + cpumask_set_cpu(cpu, &cpu_topology[iter].die_cpus); + cpumask_set_cpu(iter, &cpu_topology[cpu].die_cpus); + } + } + return 0; +} + +late_initcall(cpu_topology_die_map); #endif #ifdef CONFIG_ARM64_AMU_EXTN diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 2ee5e05a0d69e881d6a28f02f7e05028037da9b9..66f0d0f587292acd179865c28ed37d9e019831a5 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -595,6 +595,66 @@ static int duplicate_processor_ids[] = { [0 ... NR_CPUS - 1] = -1, }; +struct acpi_cpu_die_ctx { + int die_id; + int *cpu_die_map; +}; + +static acpi_status __init acpi_cpu_die_walk(acpi_handle object, + u32 nesting_level, + void *context, + void **return_value) +{ + struct acpi_device *d = NULL; + int cpuid; + unsigned long long acpi_id; + acpi_status status; + struct acpi_cpu_die_ctx *ctx = context; + + acpi_bus_get_device(object, &d); + if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_DEVICE_HID)) + return AE_OK; + + status = acpi_evaluate_integer(object, METHOD_NAME__UID, NULL, + &acpi_id); + if (ACPI_FAILURE(status)) + return AE_OK; + + cpuid = acpi_get_cpuid(object, 1, (u32)acpi_id); + + if (cpuid >= NR_CPUS || cpuid < 0) + return AE_OK; + + ctx->cpu_die_map[cpuid] = ctx->die_id; + return AE_OK; +} + +static acpi_status __init acpi_cpu_die_topology(acpi_handle object, + u32 nesting_level, + void *context, + void **return_value) +{ + acpi_status status; + unsigned long long value; + struct acpi_cpu_die_ctx *ctx = context; + + status = acpi_evaluate_integer(object, METHOD_NAME__UID, NULL, &value); + if (ACPI_FAILURE(status)) + return AE_OK; + + ctx->die_id = (int)value; + return acpi_walk_namespace(ACPI_TYPE_DEVICE, object, ACPI_UINT32_MAX, + acpi_cpu_die_walk, NULL, context, NULL); +} + +void __init acpi_cpu_die_init(int *cpu_die_map) +{ + struct acpi_cpu_die_ctx ctx = {.cpu_die_map = cpu_die_map}; + + acpi_get_devices(ACPI_PROCESSOR_CONTAINER_HID, + acpi_cpu_die_topology, &ctx, NULL); +} + static void __init processor_validated_ids_update(int proc_id) { int i; diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 0f6cd6b73a61372c61eac5ad42222f332438999f..b852fca3a51635e512d564edd185e37f26668c9a 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -49,13 +49,17 @@ void topology_set_thermal_pressure(const struct cpumask *cpus, struct cpu_topology { int thread_id; int core_id; + int die_id; int package_id; int llc_id; cpumask_t thread_sibling; cpumask_t core_sibling; cpumask_t llc_sibling; + cpumask_t die_cpus; }; +extern void __init acpi_cpu_die_init(int *cpu_die_map); + #ifdef CONFIG_GENERIC_ARCH_TOPOLOGY extern struct cpu_topology cpu_topology[NR_CPUS];