Hi all,
These are a few trivial patches to populate cpu capacity information
using performance information from ACPI's CPPC.
I've tied this functionality to the existing function
init_freq_invariance_cppc() called in acpi_cppc_processor_probe().
This function is renamed to a more generic arch_init_invariance_cppc().
The patches have been build tested on x86 and more thoroughly tested on
Juno R2 (arm64), which uses the new functionality, with the following
results:
root@ubuntu:~# dmesg | grep cpu_capacity
[ 2.157494] init_cpu_capacity_cppc: CPU0 cpu_capacity=38300 (raw).
[ 2.163699] init_cpu_capacity_cppc: CPU1 cpu_capacity=38300 (raw).
[ 2.169899] init_cpu_capacity_cppc: CPU2 cpu_capacity=38300 (raw).
[ 2.176098] init_cpu_capacity_cppc: CPU3 cpu_capacity=38300 (raw).
[ 2.182296] init_cpu_capacity_cppc: CPU4 cpu_capacity=102400 (raw).
[ 2.188581] init_cpu_capacity_cppc: CPU5 cpu_capacity=102400 (raw).
[ 2.194867] cpu_capacity: capacity_scale=102400
[ 2.199409] cpu_capacity: CPU0 cpu_capacity=383
[ 2.203952] cpu_capacity: CPU1 cpu_capacity=383
[ 2.208495] cpu_capacity: CPU2 cpu_capacity=383
[ 2.213037] cpu_capacity: CPU3 cpu_capacity=383
[ 2.217580] cpu_capacity: CPU4 cpu_capacity=1024
[ 2.222209] cpu_capacity: CPU5 cpu_capacity=1024
[ 2.226886] init_cpu_capacity_cppc: cpu_capacity initialization done
root@ubuntu:~# tail -n +1 /sys/devices/system/cpu/cpu*/cpu_capacity
==> /sys/devices/system/cpu/cpu0/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu1/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu2/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu3/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu4/cpu_capacity <==
1024
==> /sys/devices/system/cpu/cpu5/cpu_capacity <==
1024
All works as expected even if ACPI processor support is built as a
module.
Patches are based on v5.13-rc1.
Let me know what you think!
Thanks,
Ionela.
Ionela Voinescu (3):
x86, ACPI: rename init_freq_invariance_cppc to
arch_init_invariance_cppc
arch_topology: obtain cpu capacity using information from CPPC
arm64, topology: enable use of init_cpu_capacity_cppc()
arch/arm64/include/asm/topology.h | 4 ++++
arch/x86/include/asm/topology.h | 2 +-
drivers/acpi/cppc_acpi.c | 6 ++---
drivers/base/arch_topology.c | 39 +++++++++++++++++++++++++++++++
include/linux/arch_topology.h | 4 ++++
5 files changed, 51 insertions(+), 4 deletions(-)
--
2.29.2.dirty
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
init_freq_invariance_cppc() was called in acpi_cppc_processor_probe(),
after CPU performance information and controls were populated from the
per-cpu _CPC objects.
But these _CPC objects provide information that helps with both CPU
(u-arch) and frequency invariance. Therefore, change the function name
to a more generic one, while adding the arch_ prefix, as this function
is expected to be defined differently by different architectures.
Signed-off-by: Ionela Voinescu <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Giovanni Gherdovich <redacted>
Cc: "Rafael J. Wysocki" <redacted>
---
arch/x86/include/asm/topology.h | 2 +-
drivers/acpi/cppc_acpi.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
Define init_cpu_capacity_cppc() to use highest performance values
from _CPC objects to obtain and set maximum capacity information for
each CPU. acpi_cppc_processor_probe() is a good point at which to
trigger the initialization of CPU (u-arch) capacity values, as at this
point the highest performance values can be obtained from each CPU's
_CPC objects. Architectures can therefore use this functionality
through arch_init_invariance_cppc().
The performance scale used by CPPC is a unified scale for all CPUs in
the system. Therefore, by obtaining the raw highest performance values
from the _CPC objects, and normalizing them on the [0, 1024] capacity
scale, used by the task scheduler, we obtain the CPU capacity of each
CPU.
While an ACPI Notify(0x85) could alert about a change in the highest
performance value, which should in turn retrigger the CPU capacity
computations, this notification is not currently handled by the ACPI
processor driver. When supported, a call to arch_init_invariance_cppc()
would perform the update.
Signed-off-by: Ionela Voinescu <redacted>
Cc: Sudeep Holla <redacted>
---
drivers/base/arch_topology.c | 39 +++++++++++++++++++++++++++++++++++
include/linux/arch_topology.h | 4 ++++
2 files changed, 43 insertions(+)
Now that the arch topology driver provides a method of setting CPU
capacity values based on information on highest performance from CPPC,
use this functionality on arm64 platforms.
Signed-off-by: Ionela Voinescu <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/topology.h | 4 ++++
1 file changed, 4 insertions(+)
On Fri, May 14, 2021 at 10:53:39AM +0100, Ionela Voinescu wrote:
Now that the arch topology driver provides a method of setting CPU
capacity values based on information on highest performance from CPPC,
use this functionality on arm64 platforms.
Signed-off-by: Ionela Voinescu <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
init_cpu_capacity_cppc() shares a lot of functionality with the existing
DT/CPUfreq-based approach (topology_parse_cpu_capacity(),
register_cpufreq_notifier(), init_cpu_capacity_callback()). It looks
like that the different ways of invocation (two steps per cpu vs. one
step for all cpus) makes it hard to restructure the code to create more
common bits.
+void init_cpu_capacity_cppc(void)
+{
+ struct cppc_perf_caps perf_caps;
+ int cpu;
+
+ if (likely(acpi_disabled || !acpi_cpc_valid()))
There is quite a variety in the layout of the pr_xxx() log messages in
this file. Originally the 'cpu_capacity:' was used to indicate that this
log is from drivers/base/arch_topology.c. Now the GCC __func__
identifier is used. Maybe this can be aligned better? Especially since
the functionality used in the existing DT-driven and now in the new
CPPC-driven functionality is quite similar. Debugging is so much easier
with consistent log strings.
In case a system has CONFIG_ACPI_CPPC_LIB what does this mean for the
DT-based approach via `register_cpufreq_notifier()`?
Looks like we rely on:
376 static int __init register_cpufreq_notifier(void)
...
385 if (!acpi_disabled || ...)
386 return -EINVAL;
to disable the CPUfreq part of the DT/CPUfreq-based approach on an ACPI
system.
[...]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
The prefix `topology_` was meant to indicate that those functions come
from drivers/base/arch_topology.c. You probably refrained from it since
topology_init_cpu_capacity_cppc()
is a pretty long function name ... Still more consistent though.
[...]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hi all,
These are a few trivial patches to populate cpu capacity information
using performance information from ACPI's CPPC.
I've tied this functionality to the existing function
init_freq_invariance_cppc() called in acpi_cppc_processor_probe().
This function is renamed to a more generic arch_init_invariance_cppc().
The patches have been build tested on x86 and more thoroughly tested on
Juno R2 (arm64), which uses the new functionality, with the following
results:
root@ubuntu:~# dmesg | grep cpu_capacity
[ 2.157494] init_cpu_capacity_cppc: CPU0 cpu_capacity=38300 (raw).
[ 2.163699] init_cpu_capacity_cppc: CPU1 cpu_capacity=38300 (raw).
[ 2.169899] init_cpu_capacity_cppc: CPU2 cpu_capacity=38300 (raw).
[ 2.176098] init_cpu_capacity_cppc: CPU3 cpu_capacity=38300 (raw).
[ 2.182296] init_cpu_capacity_cppc: CPU4 cpu_capacity=102400 (raw).
[ 2.188581] init_cpu_capacity_cppc: CPU5 cpu_capacity=102400 (raw).
[ 2.194867] cpu_capacity: capacity_scale=102400
[ 2.199409] cpu_capacity: CPU0 cpu_capacity=383
[ 2.203952] cpu_capacity: CPU1 cpu_capacity=383
[ 2.208495] cpu_capacity: CPU2 cpu_capacity=383
[ 2.213037] cpu_capacity: CPU3 cpu_capacity=383
[ 2.217580] cpu_capacity: CPU4 cpu_capacity=1024
[ 2.222209] cpu_capacity: CPU5 cpu_capacity=1024
[ 2.226886] init_cpu_capacity_cppc: cpu_capacity initialization done
root@ubuntu:~# tail -n +1 /sys/devices/system/cpu/cpu*/cpu_capacity
==> /sys/devices/system/cpu/cpu0/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu1/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu2/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu3/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu4/cpu_capacity <==
1024
==> /sys/devices/system/cpu/cpu5/cpu_capacity <==
1024
All works as expected even if ACPI processor support is built as a
module.
init_cpu_capacity_cppc() shares a lot of functionality with the existing
DT/CPUfreq-based approach (topology_parse_cpu_capacity(),
register_cpufreq_notifier(), init_cpu_capacity_callback()). It looks
like that the different ways of invocation (two steps per cpu vs. one
step for all cpus) makes it hard to restructure the code to create more
common bits.
Yes, I looked at ways to reuse more of the DT-based functionality, but I
did not find a better way. We reuse the normalization functionality and
the rebuild of the scheduling domains, but I'm not sure there's room for
much more, as the rest is specific to each source of capacity
information, DT+cpufreq or CPPC.
I also did not want to tie the new CPPC based functionality to cpufreq.
While the DT-based path needs cpufreq policies initialized as it needs
information on maximum frequency to obtain capacity, this is not needed
in the new code. This results in simpler code and ensures support even
for systems that do not have a cpufreq driver.
quoted
+void init_cpu_capacity_cppc(void)
+{
+ struct cppc_perf_caps perf_caps;
+ int cpu;
+
+ if (likely(acpi_disabled || !acpi_cpc_valid()))
likely(acpi_disabled) ?
likely (acpi_disabled || !acpi_cpc_valid()) :)
It's "likely" useless, but this function gets called for each CPU from
acpi_cppc_processor_probe(), but it only continues with setting the
cpu_scale after all possible CPUs have their _CPC objects populated.
Therefore it's a lot more likely we return here.
There is quite a variety in the layout of the pr_xxx() log messages in
this file. Originally the 'cpu_capacity:' was used to indicate that this
log is from drivers/base/arch_topology.c. Now the GCC __func__
identifier is used. Maybe this can be aligned better? Especially since
the functionality used in the existing DT-driven and now in the new
CPPC-driven functionality is quite similar. Debugging is so much easier
with consistent log strings.
Right! My intention was to keep the prints relatively similar, but my
wanting to reduce the line length got the better of me. I'll keep the
prints consistent.
In case a system has CONFIG_ACPI_CPPC_LIB what does this mean for the
DT-based approach via `register_cpufreq_notifier()`?
CONFIG_ACPI_CPPC_LIB is enabled by default on arm64. This only ensures
that we have the functionality to parse and work with the ACPI _CPC
objects and it does not guarantee that ACPI will be used.
Looks like we rely on:
376 static int __init register_cpufreq_notifier(void)
...
385 if (!acpi_disabled || ...)
386 return -EINVAL;
to disable the CPUfreq part of the DT/CPUfreq-based approach on an ACPI
system.
It's both acpi_disabled and raw_capacity that guard the DT path. You
need both to not use ACPI (therefore using DT) and to have valid
capacity-dmips-mhz in DT for the cpufreq notifier that will eventually
populate the cpu_scale variables to be registered.
Thank you,
Ionela.
The prefix `topology_` was meant to indicate that those functions come
from drivers/base/arch_topology.c. You probably refrained from it since
topology_init_cpu_capacity_cppc()
is a pretty long function name ... Still more consistent though.
Hi Valentin,
On Tuesday 18 May 2021 at 14:12:03 (+0100), Valentin Schneider wrote:
Hi,
On 14/05/21 10:53, Ionela Voinescu wrote:
quoted
Hi all,
These are a few trivial patches to populate cpu capacity information
using performance information from ACPI's CPPC.
I've tied this functionality to the existing function
init_freq_invariance_cppc() called in acpi_cppc_processor_probe().
This function is renamed to a more generic arch_init_invariance_cppc().
The patches have been build tested on x86 and more thoroughly tested on
Juno R2 (arm64), which uses the new functionality, with the following
results:
root@ubuntu:~# dmesg | grep cpu_capacity
[ 2.157494] init_cpu_capacity_cppc: CPU0 cpu_capacity=38300 (raw).
[ 2.163699] init_cpu_capacity_cppc: CPU1 cpu_capacity=38300 (raw).
[ 2.169899] init_cpu_capacity_cppc: CPU2 cpu_capacity=38300 (raw).
[ 2.176098] init_cpu_capacity_cppc: CPU3 cpu_capacity=38300 (raw).
[ 2.182296] init_cpu_capacity_cppc: CPU4 cpu_capacity=102400 (raw).
[ 2.188581] init_cpu_capacity_cppc: CPU5 cpu_capacity=102400 (raw).
[ 2.194867] cpu_capacity: capacity_scale=102400
[ 2.199409] cpu_capacity: CPU0 cpu_capacity=383
[ 2.203952] cpu_capacity: CPU1 cpu_capacity=383
[ 2.208495] cpu_capacity: CPU2 cpu_capacity=383
[ 2.213037] cpu_capacity: CPU3 cpu_capacity=383
[ 2.217580] cpu_capacity: CPU4 cpu_capacity=1024
[ 2.222209] cpu_capacity: CPU5 cpu_capacity=1024
[ 2.226886] init_cpu_capacity_cppc: cpu_capacity initialization done
root@ubuntu:~# tail -n +1 /sys/devices/system/cpu/cpu*/cpu_capacity
==> /sys/devices/system/cpu/cpu0/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu1/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu2/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu3/cpu_capacity <==
383
==> /sys/devices/system/cpu/cpu4/cpu_capacity <==
1024
==> /sys/devices/system/cpu/cpu5/cpu_capacity <==
1024
All works as expected even if ACPI processor support is built as a
module.
Many thanks for testing and fixing the debugfs problem. I'll take a look
over your patch.
Ionela.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel