diff mbox

[1/2] ARM: vexpress: refine MCPM smp operations override criteria

Message ID 20160923130907.4187-1-lorenzo.pieralisi@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lorenzo Pieralisi Sept. 23, 2016, 1:09 p.m. UTC
Current vexpress smp init code detects whether to override the
default smp ops with MCPM smp ops by matching the "cci-400"
compatible string, in that MCPM requires control over CCI ports
to manage low-power states entry/exit.

The "cci-400" compatible string check is a necessary but not
sufficient condition for MCPM to work, because the cci-400
can be made visible to the kernel, but firmware can nonetheless
disable non-secure CCI ports control, while still allowing PMU
access; if booted in non-secure world, the kernel would still
blindly override smp operations with MCPM operations, resulting
in kernel faults when the CCI ports programming interface is
accessed from non-secure world.

This means that the "cci-400" compatible string check would
result in a false positive in systems that eg boot in HYP mode,
where CCI ports non-secure access is explicitly not allowed,
and it is reported in the respective device tree nodes with
CCI ports marked as disabled.

Refactor the smp operations initialization to make sure that
the kernel is actually allowed to take control over CCI ports
(by enabling MCPM smp operations) before overriding default
vexpress smp operations.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

Comments

Lorenzo Pieralisi Sept. 23, 2016, 2:03 p.m. UTC | #1
On Fri, Sep 23, 2016 at 02:09:06PM +0100, Lorenzo Pieralisi wrote:
> Current vexpress smp init code detects whether to override the
> default smp ops with MCPM smp ops by matching the "cci-400"
> compatible string, in that MCPM requires control over CCI ports
> to manage low-power states entry/exit.
> 
> The "cci-400" compatible string check is a necessary but not
> sufficient condition for MCPM to work, because the cci-400
> can be made visible to the kernel, but firmware can nonetheless
> disable non-secure CCI ports control, while still allowing PMU
> access; if booted in non-secure world, the kernel would still
> blindly override smp operations with MCPM operations, resulting
> in kernel faults when the CCI ports programming interface is
> accessed from non-secure world.
> 
> This means that the "cci-400" compatible string check would
> result in a false positive in systems that eg boot in HYP mode,
> where CCI ports non-secure access is explicitly not allowed,
> and it is reported in the respective device tree nodes with
> CCI ports marked as disabled.
> 
> Refactor the smp operations initialization to make sure that
> the kernel is actually allowed to take control over CCI ports
> (by enabling MCPM smp operations) before overriding default
> vexpress smp operations.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>  1 file changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index 8b8d072..6cfd782 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -26,17 +26,34 @@
>  bool __init vexpress_smp_init_ops(void)
>  {
>  #ifdef CONFIG_MCPM
> +	int cpu;
> +	struct device_node *cpu_node, *cci_node;
> +
>  	/*
> -	 * The best way to detect a multi-cluster configuration at the moment
> -	 * is to look for the presence of a CCI in the system.
> +	 * The best way to detect a multi-cluster configuration
> +	 * is to detect if the kernel can take over CCI ports
> +	 * control. Loop over possible CPUs and check if CCI
> +	 * port control is available.
>  	 * Override the default vexpress_smp_ops if so.
>  	 */
> -	struct device_node *node;
> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
> -	if (node && of_device_is_available(node)) {
> -		mcpm_smp_set_ops();
> -		return true;
> +	for_each_possible_cpu(cpu) {
> +		bool available;
> +
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +		if (WARN(!cpu_node, "Missing cpu device node!"))
> +			return false;
> +
> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
> +		available = cci_node && of_device_is_available(cci_node);
> +		of_node_put(cci_node);
> +		of_node_put(cpu_node);
> +
> +		if (!available)
> +			return false;
>  	}
> +
> +	mcpm_smp_set_ops();
> +	return true;
>  #endif
>  	return false;

For the records, while moving the code around I missed I was ending
up with this idiotic double return, I have already reworked the patch
and will squash changes in the final version if we agree on the bulk of
the code.

Lorenzo
Liviu Dudau Sept. 23, 2016, 3 p.m. UTC | #2
On Fri, Sep 23, 2016 at 02:09:06PM +0100, Lorenzo Pieralisi wrote:
> Current vexpress smp init code detects whether to override the
> default smp ops with MCPM smp ops by matching the "cci-400"
> compatible string, in that MCPM requires control over CCI ports
> to manage low-power states entry/exit.
> 
> The "cci-400" compatible string check is a necessary but not
> sufficient condition for MCPM to work, because the cci-400
> can be made visible to the kernel, but firmware can nonetheless
> disable non-secure CCI ports control, while still allowing PMU
> access; if booted in non-secure world, the kernel would still
> blindly override smp operations with MCPM operations, resulting
> in kernel faults when the CCI ports programming interface is
> accessed from non-secure world.
> 
> This means that the "cci-400" compatible string check would
> result in a false positive in systems that eg boot in HYP mode,
> where CCI ports non-secure access is explicitly not allowed,
> and it is reported in the respective device tree nodes with
> CCI ports marked as disabled.

I remember seeing a patch from Marc this week exactly on this
subject, but I can't find it again today. However, I remember that
his patch was explicitly testing for the HYP presence.

> 
> Refactor the smp operations initialization to make sure that
> the kernel is actually allowed to take control over CCI ports
> (by enabling MCPM smp operations) before overriding default
> vexpress smp operations.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>  1 file changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index 8b8d072..6cfd782 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -26,17 +26,34 @@
>  bool __init vexpress_smp_init_ops(void)
>  {
>  #ifdef CONFIG_MCPM
> +	int cpu;
> +	struct device_node *cpu_node, *cci_node;
> +
>  	/*
> -	 * The best way to detect a multi-cluster configuration at the moment
> -	 * is to look for the presence of a CCI in the system.
> +	 * The best way to detect a multi-cluster configuration
> +	 * is to detect if the kernel can take over CCI ports
> +	 * control. Loop over possible CPUs and check if CCI
> +	 * port control is available.
>  	 * Override the default vexpress_smp_ops if so.
>  	 */
> -	struct device_node *node;
> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
> -	if (node && of_device_is_available(node)) {
> -		mcpm_smp_set_ops();
> -		return true;
> +	for_each_possible_cpu(cpu) {
> +		bool available;
> +
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +		if (WARN(!cpu_node, "Missing cpu device node!"))
> +			return false;
> +
> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
> +		available = cci_node && of_device_is_available(cci_node);

of_device_is_available() only checks the DT node for status = "enabled";

Does the HYP modify the DT to disable the cci-control-port? If not, then I guess
this patch is not enough?

Best regards,
Liviu

> +		of_node_put(cci_node);
> +		of_node_put(cpu_node);
> +
> +		if (!available)
> +			return false;
>  	}
> +
> +	mcpm_smp_set_ops();
> +	return true;
>  #endif
>  	return false;
>  }
> -- 
> 2.10.0
>
Sudeep Holla Sept. 23, 2016, 3:01 p.m. UTC | #3
On 23/09/16 16:00, Liviu Dudau wrote:
> On Fri, Sep 23, 2016 at 02:09:06PM +0100, Lorenzo Pieralisi wrote:
>> Current vexpress smp init code detects whether to override the
>> default smp ops with MCPM smp ops by matching the "cci-400"
>> compatible string, in that MCPM requires control over CCI ports
>> to manage low-power states entry/exit.
>>
>> The "cci-400" compatible string check is a necessary but not
>> sufficient condition for MCPM to work, because the cci-400
>> can be made visible to the kernel, but firmware can nonetheless
>> disable non-secure CCI ports control, while still allowing PMU
>> access; if booted in non-secure world, the kernel would still
>> blindly override smp operations with MCPM operations, resulting
>> in kernel faults when the CCI ports programming interface is
>> accessed from non-secure world.
>>
>> This means that the "cci-400" compatible string check would
>> result in a false positive in systems that eg boot in HYP mode,
>> where CCI ports non-secure access is explicitly not allowed,
>> and it is reported in the respective device tree nodes with
>> CCI ports marked as disabled.
>
> I remember seeing a patch from Marc this week exactly on this
> subject, but I can't find it again today. However, I remember that
> his patch was explicitly testing for the HYP presence.
>
>>
>> Refactor the smp operations initialization to make sure that
>> the kernel is actually allowed to take control over CCI ports
>> (by enabling MCPM smp operations) before overriding default
>> vexpress smp operations.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Liviu Dudau <liviu.dudau@arm.com>
>> Cc: Sudeep Holla <sudeep.holla@arm.com>
>> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>>  1 file changed, 24 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
>> index 8b8d072..6cfd782 100644
>> --- a/arch/arm/mach-vexpress/platsmp.c
>> +++ b/arch/arm/mach-vexpress/platsmp.c
>> @@ -26,17 +26,34 @@
>>  bool __init vexpress_smp_init_ops(void)
>>  {
>>  #ifdef CONFIG_MCPM
>> +	int cpu;
>> +	struct device_node *cpu_node, *cci_node;
>> +
>>  	/*
>> -	 * The best way to detect a multi-cluster configuration at the moment
>> -	 * is to look for the presence of a CCI in the system.
>> +	 * The best way to detect a multi-cluster configuration
>> +	 * is to detect if the kernel can take over CCI ports
>> +	 * control. Loop over possible CPUs and check if CCI
>> +	 * port control is available.
>>  	 * Override the default vexpress_smp_ops if so.
>>  	 */
>> -	struct device_node *node;
>> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
>> -	if (node && of_device_is_available(node)) {
>> -		mcpm_smp_set_ops();
>> -		return true;
>> +	for_each_possible_cpu(cpu) {
>> +		bool available;
>> +
>> +		cpu_node = of_get_cpu_node(cpu, NULL);
>> +		if (WARN(!cpu_node, "Missing cpu device node!"))
>> +			return false;
>> +
>> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
>> +		available = cci_node && of_device_is_available(cci_node);
>
> of_device_is_available() only checks the DT node for status = "enabled";
>
> Does the HYP modify the DT to disable the cci-control-port? If not, then I guess
> this patch is not enough?
>

Correct, I will send out the u-boot patch to disable the cci ports soon.
Nicolas Pitre Sept. 23, 2016, 3:46 p.m. UTC | #4
On Fri, 23 Sep 2016, Lorenzo Pieralisi wrote:

> Current vexpress smp init code detects whether to override the
> default smp ops with MCPM smp ops by matching the "cci-400"
> compatible string, in that MCPM requires control over CCI ports
> to manage low-power states entry/exit.
> 
> The "cci-400" compatible string check is a necessary but not
> sufficient condition for MCPM to work, because the cci-400
> can be made visible to the kernel, but firmware can nonetheless
> disable non-secure CCI ports control, while still allowing PMU
> access; if booted in non-secure world, the kernel would still
> blindly override smp operations with MCPM operations, resulting
> in kernel faults when the CCI ports programming interface is
> accessed from non-secure world.
> 
> This means that the "cci-400" compatible string check would
> result in a false positive in systems that eg boot in HYP mode,
> where CCI ports non-secure access is explicitly not allowed,
> and it is reported in the respective device tree nodes with
> CCI ports marked as disabled.
> 
> Refactor the smp operations initialization to make sure that
> the kernel is actually allowed to take control over CCI ports
> (by enabling MCPM smp operations) before overriding default
> vexpress smp operations.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Nicolas Pitre <nico@linaro.org>


> ---
>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>  1 file changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index 8b8d072..6cfd782 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -26,17 +26,34 @@
>  bool __init vexpress_smp_init_ops(void)
>  {
>  #ifdef CONFIG_MCPM
> +	int cpu;
> +	struct device_node *cpu_node, *cci_node;
> +
>  	/*
> -	 * The best way to detect a multi-cluster configuration at the moment
> -	 * is to look for the presence of a CCI in the system.
> +	 * The best way to detect a multi-cluster configuration
> +	 * is to detect if the kernel can take over CCI ports
> +	 * control. Loop over possible CPUs and check if CCI
> +	 * port control is available.
>  	 * Override the default vexpress_smp_ops if so.
>  	 */
> -	struct device_node *node;
> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
> -	if (node && of_device_is_available(node)) {
> -		mcpm_smp_set_ops();
> -		return true;
> +	for_each_possible_cpu(cpu) {
> +		bool available;
> +
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +		if (WARN(!cpu_node, "Missing cpu device node!"))
> +			return false;
> +
> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
> +		available = cci_node && of_device_is_available(cci_node);
> +		of_node_put(cci_node);
> +		of_node_put(cpu_node);
> +
> +		if (!available)
> +			return false;
>  	}
> +
> +	mcpm_smp_set_ops();
> +	return true;
>  #endif
>  	return false;
>  }
> -- 
> 2.10.0
> 
>
Jon Medhurst (Tixy) Sept. 26, 2016, 12:29 p.m. UTC | #5
On Fri, 2016-09-23 at 14:09 +0100, Lorenzo Pieralisi wrote:
> Current vexpress smp init code detects whether to override the
> default smp ops with MCPM smp ops by matching the "cci-400"
> compatible string, in that MCPM requires control over CCI ports
> to manage low-power states entry/exit.
> 
> The "cci-400" compatible string check is a necessary but not
> sufficient condition for MCPM to work, because the cci-400
> can be made visible to the kernel, but firmware can nonetheless
> disable non-secure CCI ports control, while still allowing PMU
> access; if booted in non-secure world, the kernel would still
> blindly override smp operations with MCPM operations, resulting
> in kernel faults when the CCI ports programming interface is
> accessed from non-secure world.
> 
> This means that the "cci-400" compatible string check would
> result in a false positive in systems that eg boot in HYP mode,
> where CCI ports non-secure access is explicitly not allowed,
> and it is reported in the respective device tree nodes with
> CCI ports marked as disabled.
> 
> Refactor the smp operations initialization to make sure that
> the kernel is actually allowed to take control over CCI ports
> (by enabling MCPM smp operations) before overriding default
> vexpress smp operations.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> ---

Tested-by: Jon Medhurst <tixy@linaro.org>

>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>  1 file changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index 8b8d072..6cfd782 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -26,17 +26,34 @@
>  bool __init vexpress_smp_init_ops(void)
>  {
>  #ifdef CONFIG_MCPM
> +	int cpu;
> +	struct device_node *cpu_node, *cci_node;
> +
>  	/*
> -	 * The best way to detect a multi-cluster configuration at the moment
> -	 * is to look for the presence of a CCI in the system.
> +	 * The best way to detect a multi-cluster configuration
> +	 * is to detect if the kernel can take over CCI ports
> +	 * control. Loop over possible CPUs and check if CCI
> +	 * port control is available.
>  	 * Override the default vexpress_smp_ops if so.
>  	 */
> -	struct device_node *node;
> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
> -	if (node && of_device_is_available(node)) {
> -		mcpm_smp_set_ops();
> -		return true;
> +	for_each_possible_cpu(cpu) {
> +		bool available;
> +
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +		if (WARN(!cpu_node, "Missing cpu device node!"))
> +			return false;
> +
> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
> +		available = cci_node && of_device_is_available(cci_node);
> +		of_node_put(cci_node);
> +		of_node_put(cpu_node);
> +
> +		if (!available)
> +			return false;
>  	}
> +
> +	mcpm_smp_set_ops();
> +	return true;
>  #endif
>  	return false;
>  }
Sudeep Holla Oct. 17, 2016, 5:31 p.m. UTC | #6
On 23/09/16 15:03, Lorenzo Pieralisi wrote:
> On Fri, Sep 23, 2016 at 02:09:06PM +0100, Lorenzo Pieralisi wrote:
>> Current vexpress smp init code detects whether to override the
>> default smp ops with MCPM smp ops by matching the "cci-400"
>> compatible string, in that MCPM requires control over CCI ports
>> to manage low-power states entry/exit.
>>
>> The "cci-400" compatible string check is a necessary but not
>> sufficient condition for MCPM to work, because the cci-400
>> can be made visible to the kernel, but firmware can nonetheless
>> disable non-secure CCI ports control, while still allowing PMU
>> access; if booted in non-secure world, the kernel would still
>> blindly override smp operations with MCPM operations, resulting
>> in kernel faults when the CCI ports programming interface is
>> accessed from non-secure world.
>>
>> This means that the "cci-400" compatible string check would
>> result in a false positive in systems that eg boot in HYP mode,
>> where CCI ports non-secure access is explicitly not allowed,
>> and it is reported in the respective device tree nodes with
>> CCI ports marked as disabled.
>>
>> Refactor the smp operations initialization to make sure that
>> the kernel is actually allowed to take control over CCI ports
>> (by enabling MCPM smp operations) before overriding default
>> vexpress smp operations.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Liviu Dudau <liviu.dudau@arm.com>
>> Cc: Sudeep Holla <sudeep.holla@arm.com>
>> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
>>  1 file changed, 24 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
>> index 8b8d072..6cfd782 100644
>> --- a/arch/arm/mach-vexpress/platsmp.c
>> +++ b/arch/arm/mach-vexpress/platsmp.c
>> @@ -26,17 +26,34 @@
>>  bool __init vexpress_smp_init_ops(void)
>>  {
>>  #ifdef CONFIG_MCPM
>> +	int cpu;
>> +	struct device_node *cpu_node, *cci_node;
>> +
>>  	/*
>> -	 * The best way to detect a multi-cluster configuration at the moment
>> -	 * is to look for the presence of a CCI in the system.
>> +	 * The best way to detect a multi-cluster configuration
>> +	 * is to detect if the kernel can take over CCI ports
>> +	 * control. Loop over possible CPUs and check if CCI
>> +	 * port control is available.
>>  	 * Override the default vexpress_smp_ops if so.
>>  	 */
>> -	struct device_node *node;
>> -	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
>> -	if (node && of_device_is_available(node)) {
>> -		mcpm_smp_set_ops();
>> -		return true;
>> +	for_each_possible_cpu(cpu) {
>> +		bool available;
>> +
>> +		cpu_node = of_get_cpu_node(cpu, NULL);
>> +		if (WARN(!cpu_node, "Missing cpu device node!"))
>> +			return false;
>> +
>> +		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
>> +		available = cci_node && of_device_is_available(cci_node);
>> +		of_node_put(cci_node);
>> +		of_node_put(cpu_node);
>> +
>> +		if (!available)
>> +			return false;
>>  	}
>> +
>> +	mcpm_smp_set_ops();
>> +	return true;
>>  #endif
>>  	return false;
>
> For the records, while moving the code around I missed I was ending
> up with this idiotic double return, I have already reworked the patch
> and will squash changes in the final version if we agree on the bulk of
> the code.
>

I applied both patches to [1] with the fix for the above issue. Let me
know if that's fine. I have tested both hyp mode boot and SVC mode +
MCPM boot with latest u-boot by just fliping a bit in the firmware
(board.txt) without recompiling the kernel.
Lorenzo Pieralisi Oct. 19, 2016, 8:38 a.m. UTC | #7
On Mon, Oct 17, 2016 at 06:31:58PM +0100, Sudeep Holla wrote:
> 
> 
> On 23/09/16 15:03, Lorenzo Pieralisi wrote:
> >On Fri, Sep 23, 2016 at 02:09:06PM +0100, Lorenzo Pieralisi wrote:
> >>Current vexpress smp init code detects whether to override the
> >>default smp ops with MCPM smp ops by matching the "cci-400"
> >>compatible string, in that MCPM requires control over CCI ports
> >>to manage low-power states entry/exit.
> >>
> >>The "cci-400" compatible string check is a necessary but not
> >>sufficient condition for MCPM to work, because the cci-400
> >>can be made visible to the kernel, but firmware can nonetheless
> >>disable non-secure CCI ports control, while still allowing PMU
> >>access; if booted in non-secure world, the kernel would still
> >>blindly override smp operations with MCPM operations, resulting
> >>in kernel faults when the CCI ports programming interface is
> >>accessed from non-secure world.
> >>
> >>This means that the "cci-400" compatible string check would
> >>result in a false positive in systems that eg boot in HYP mode,
> >>where CCI ports non-secure access is explicitly not allowed,
> >>and it is reported in the respective device tree nodes with
> >>CCI ports marked as disabled.
> >>
> >>Refactor the smp operations initialization to make sure that
> >>the kernel is actually allowed to take control over CCI ports
> >>(by enabling MCPM smp operations) before overriding default
> >>vexpress smp operations.
> >>
> >>Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >>Cc: Liviu Dudau <liviu.dudau@arm.com>
> >>Cc: Sudeep Holla <sudeep.holla@arm.com>
> >>Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> >>Cc: Marc Zyngier <marc.zyngier@arm.com>
> >>---
> >> arch/arm/mach-vexpress/platsmp.c | 31 ++++++++++++++++++++++++-------
> >> 1 file changed, 24 insertions(+), 7 deletions(-)
> >>
> >>diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> >>index 8b8d072..6cfd782 100644
> >>--- a/arch/arm/mach-vexpress/platsmp.c
> >>+++ b/arch/arm/mach-vexpress/platsmp.c
> >>@@ -26,17 +26,34 @@
> >> bool __init vexpress_smp_init_ops(void)
> >> {
> >> #ifdef CONFIG_MCPM
> >>+	int cpu;
> >>+	struct device_node *cpu_node, *cci_node;
> >>+
> >> 	/*
> >>-	 * The best way to detect a multi-cluster configuration at the moment
> >>-	 * is to look for the presence of a CCI in the system.
> >>+	 * The best way to detect a multi-cluster configuration
> >>+	 * is to detect if the kernel can take over CCI ports
> >>+	 * control. Loop over possible CPUs and check if CCI
> >>+	 * port control is available.
> >> 	 * Override the default vexpress_smp_ops if so.
> >> 	 */
> >>-	struct device_node *node;
> >>-	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
> >>-	if (node && of_device_is_available(node)) {
> >>-		mcpm_smp_set_ops();
> >>-		return true;
> >>+	for_each_possible_cpu(cpu) {
> >>+		bool available;
> >>+
> >>+		cpu_node = of_get_cpu_node(cpu, NULL);
> >>+		if (WARN(!cpu_node, "Missing cpu device node!"))
> >>+			return false;
> >>+
> >>+		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
> >>+		available = cci_node && of_device_is_available(cci_node);
> >>+		of_node_put(cci_node);
> >>+		of_node_put(cpu_node);
> >>+
> >>+		if (!available)
> >>+			return false;
> >> 	}
> >>+
> >>+	mcpm_smp_set_ops();
> >>+	return true;
> >> #endif
> >> 	return false;
> >
> >For the records, while moving the code around I missed I was ending
> >up with this idiotic double return, I have already reworked the patch
> >and will squash changes in the final version if we agree on the bulk of
> >the code.
> >
> 
> I applied both patches to [1] with the fix for the above issue. Let me
> know if that's fine. I have tested both hyp mode boot and SVC mode +
> MCPM boot with latest u-boot by just fliping a bit in the firmware
> (board.txt) without recompiling the kernel.

I updated the patch to remove the double return will send an updated
patch today.

Thanks !
Lorenzo

> 
> -- 
> Regards,
> Sudeep
> 
> [1] git.kernel.org/sudeep.holla/linux/h/vexpress/for-next
>
diff mbox

Patch

diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 8b8d072..6cfd782 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -26,17 +26,34 @@ 
 bool __init vexpress_smp_init_ops(void)
 {
 #ifdef CONFIG_MCPM
+	int cpu;
+	struct device_node *cpu_node, *cci_node;
+
 	/*
-	 * The best way to detect a multi-cluster configuration at the moment
-	 * is to look for the presence of a CCI in the system.
+	 * The best way to detect a multi-cluster configuration
+	 * is to detect if the kernel can take over CCI ports
+	 * control. Loop over possible CPUs and check if CCI
+	 * port control is available.
 	 * Override the default vexpress_smp_ops if so.
 	 */
-	struct device_node *node;
-	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
-	if (node && of_device_is_available(node)) {
-		mcpm_smp_set_ops();
-		return true;
+	for_each_possible_cpu(cpu) {
+		bool available;
+
+		cpu_node = of_get_cpu_node(cpu, NULL);
+		if (WARN(!cpu_node, "Missing cpu device node!"))
+			return false;
+
+		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
+		available = cci_node && of_device_is_available(cci_node);
+		of_node_put(cci_node);
+		of_node_put(cpu_node);
+
+		if (!available)
+			return false;
 	}
+
+	mcpm_smp_set_ops();
+	return true;
 #endif
 	return false;
 }