PM / EM: consult something about cpumask in em_dev_register_perf_domain
Quoted 4 lines
Hi,
Quoted 8 lines
Quoted 4 lines · On Monday 12 Oct 2020 at 20:41:36 (+0800), [email protected] wrote:
From: zhuguangqing <[email protected]>
Hi, Lukasz, Quentin
I have three questions to consult about cpumask inenergy_model.c.OK, let's see if we can help :)
Thanks for your help and review.
Quoted 3 lines
Quoted 3 lines
1, The first one is about the meanings of the following two parameters,
[1] and [2].
[1]: "cpumask_t*cpus" in functionem_dev_register_perf_domain():
Pointer
Quoted 1 line
Quoted 1 line
to
cpumask_t, which in case of a CPU device is obligatory. It can be
taken
Quoted 2 lines
Quoted 2 lines
from i.e. '
policy->cpus'.
[2]: "unsigned long cpus[]" in structem_perf_domain: Cpumask covering
the
Quoted 7 lines
Quoted 7 lines
CPUs of the domain. It's here for performance reasons to avoid potential cache misses during energy calculations in the scheduler and simplifies allocating/freeing that memory region.
From the current code, we see [2] is copied from [1]. But from comments, accorinding to my understanding, [2] and [1] have different meanings.
[1] can be taken from i.e. 'policy->cpus', according to the comment in
the
Quoted 1 line
Quoted 1 line
defination of struct
cpufreq_policy, it means Online CPUs only.
Actually,
Quoted 13 lines
Quoted 6 lines
'
policy->cpus' is not always Online CPUs.
[2] meanseach_possible_cpusin the same domain, including phycical hotplug cpus(just possible), logically hotplug cpus(just present) and online cpus.Quoted 6 lines
So, the first question is, what are the meanings of [1] and [2]? I guess maybe there are the following 4 possible choices. A),
for_each_possible_cpuin the same domain, maybe phycical hotplug B),for_each_present_cpuin the same domain, maybe logically hotplug C),for_each_online_cpuin the same domain, online
D), others
Quoted 5 lines
So, if the comments are confusing we should update them, but from the EM framework perspective, all cpumasks must be the _possible_ CPUs in the domain. It's up to the clients (e.g. the scheduler) to deal with hotplug and so on, but the EM framework should cover non-online CPUs too.
I see, from the EM framework perspective, all cpumasks must be the _possible_ CPUs in the domain. But up to the clients (e.g. the scheduler), 'policy->cpus' maybe not the _possible_ CPUs. For example, in the function scmi_cpufreq_init() which calls em_dev_register_perf_domain(), 'policy->cpus'
is got from scmi_get_sharing_cpus() and cpufreq_online(), including CPUs satisfied the following three conditions at the same time which means _present_ CPUs according to my understanding.
1) _possible_
2) if (get_cpu_device(cpu))
3) in the same domain
Quoted 1 line
Quoted 1 line
2, The second question is about the function
em_dev_register_perf_domain().
Quoted 4 lines
Quoted 4 lines
If multiple clients register the same performance domain with different *dev or *cpus, how should we handle?
int em_dev_register_perf_domain(struct device *dev, unsigned int
nr_states,
Quoted 11 lines
Quoted 10 lines
struct
em_data_callback*cb,cpumask_t*cpus)For example, say cpu0 and cpu1 are in the same performance domain, cpu0 is registered first. As part of the init process,
em_dev_register_perf_domain()is called, then *dev =cpu0_dev, *cpus = 01b(cpu1 is initially offline). It creates aem_pdforcpu0_dev. After a while, cpu1 is online,em_dev_register_perf_domain()is called again as part of init process for cpu1, then *dev =cpu1_dev, *cpus = 11b(cpu1 is online). In this case, for the current code,cpu1_devcan not get itsem_pd.
Quoted 5 lines
As per the above, the registration should be done once, with the mask of all possible CPUs in the domain. If CPUs 0 and 1 share the same domain, a single call to
em_dev_register_perf_domain()should be sufficient to register both of them at once.
I just saw your discussion in https://lkml.org/lkml/2020/2/7/479, it mentioned
"PM_EM ignores hotplug ATM. Perhaps we should document that somewhere ..."
So, if PM_EM still ignores hotplug now, then the registration should be done once,
with the mask of all possible CPUs in the domain. If PM_EM consider hotplug in
the future, then we should consider the case that em_dev_register_perf_domain()
will be called more than once with different input parameters *dev or/and *cpus.
And the CPU mask might not be all possible CPUs in the domain.
Quoted 17 lines
Quoted 4 lines
3, The third question is, how can we ensure
cpu_devas follows is not NULL? If we can't ensure that, maybe we should add a check before using it.
/kernel/power/energy_model.cQuoted 8 lines
174) static int em_create_pd(struct device *dev, int
nr_states,
175) structem_data_callback*cb,cpumask_t*cpus)
176) {
199) if (_is_cpu_device(dev))
200)for_each_cpu(cpu, cpus){
201)cpu_dev=get_cpu_device(cpu);
202)cpu_dev->em_pd= pd;
203) }And that should not be necessary as we check for the !dev case at the top of
em_dev_register_perf_domain(). Or were you thinking about something else?
Quoted 6 lines
Oh I think I read that one wrong, but the conclusion should be the same, at least on Arm64 -- all _possible_ CPUs should be registered early enough for that not to be an issue.
Did you observe anything wrong there for your use-case?
I did not observe anything wrong for my use-case. But I think it's possible in
theory that cpu_dev maybe NULL. I observe that in the function scmi_cpufreq_init(), before calling em_dev_register_perf_domain(), 'policy->cpus' can be ensure that all the cpu_dev in CPU mask are not NULL. But maybe we can not ensure all the clients do the check. This could happen if the arch did not set up cpu_dev since this CPU is not in cpu_present mask and the driver did not send a correct CPU mask during registration.
Quoted 2 lines
Thanks,
Quentin
Quoted 8 lines · On Tuesday 13 Oct 2020 at 11:40:31 (+0800), zhuguangqing83 wrote:
I did not observe anything wrong for my use-case. But I think it's possible in
theory thatcpu_devmaybe NULL. I observe that in the functionscmi_cpufreq_init(), before callingem_dev_register_perf_domain(), 'policy->cpus' can be ensure that all thecpu_devin CPU mask are not NULL. But maybe we can not ensure all the clients do the check. This could happen if the arch did not set upcpu_devsince this CPU is not incpu_presentmask and the driver did not send a correct CPU mask during registration.
Admittedly this has only been tested on Arm64 where I think we can safely assume that all possible CPUs have been registered at once -- see topology_init().
And for allowing to register CPUs late in a perf domain, I'm not opposed to it in principle but that has deep implications as the existing EM users (e.g. EAS) currently hard rely on it being static after registration. If you have a real need for it and a patch that adds the feature and fixes all the users I'll be happy to look at it :)
Thanks,
Quentin