diff mbox

ARM: move firmware_ops to drivers/firmware

Message ID 1384678169-28228-1-git-send-email-acourbot@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alexandre Courbot Nov. 17, 2013, 8:49 a.m. UTC
The ARM tree includes a firmware_ops interface that is designed to
implement support for simple, TrustZone-based firmwares but could
also cover other use-cases. It has been suggested that this
interface might be useful to other architectures (e.g. arm64) and
that it should be moved out of arch/arm.

This patch takes care of this by performing the following:
* Move the ARM firmware interface into drivers/firmware/ and rename
  it to platform_firmware,
* Update its documentation accordingly,
* Update the only user of the API to date (Exynos secure firmware
  support) to use the new API.

The ARM architecture's Kconfig now needs to include the Kconfig of
drivers/firmware, which will result in an empty menu for most platforms
that don't make use of any firmware. To avoid this, a new invisible
ARCH_SUPPORTS_FIRMWARE configuration variable is also defined for ARM,
that should explicitly be set by platforms that support firmware so that
the firmware menu is included.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 Documentation/arm/firmware.txt               | 88 ---------------------------
 Documentation/firmware/platform_firmware.txt | 89 ++++++++++++++++++++++++++++
 arch/arm/Kconfig                             |  9 +++
 arch/arm/common/Makefile                     |  2 -
 arch/arm/common/firmware.c                   | 18 ------
 arch/arm/include/asm/firmware.h              | 66 ---------------------
 arch/arm/mach-exynos/Makefile                |  2 +-
 arch/arm/mach-exynos/firmware.c              |  7 +--
 arch/arm/mach-exynos/platsmp.c               | 10 ++--
 drivers/firmware/Kconfig                     |  8 +++
 drivers/firmware/Makefile                    |  1 +
 drivers/firmware/platform_firmware.c         | 17 ++++++
 include/linux/platform_firmware.h            | 69 +++++++++++++++++++++
 13 files changed, 203 insertions(+), 183 deletions(-)
 delete mode 100644 Documentation/arm/firmware.txt
 create mode 100644 Documentation/firmware/platform_firmware.txt
 delete mode 100644 arch/arm/common/firmware.c
 delete mode 100644 arch/arm/include/asm/firmware.h
 create mode 100644 drivers/firmware/platform_firmware.c
 create mode 100644 include/linux/platform_firmware.h

Comments

Catalin Marinas Nov. 17, 2013, 3:59 p.m. UTC | #1
On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
> The ARM tree includes a firmware_ops interface that is designed to
> implement support for simple, TrustZone-based firmwares but could
> also cover other use-cases. It has been suggested that this
> interface might be useful to other architectures (e.g. arm64) and
> that it should be moved out of arch/arm.

NAK. I'm for code sharing with arm via common locations but this API
goes against the ARMv8 firmware standardisation efforts like PSCI,
encouraging each platform to define there own non-standard interface.

> --- /dev/null
> +++ b/include/linux/platform_firmware.h
> @@ -0,0 +1,69 @@
> +/*
> + * Copyright (C) 2012 Samsung Electronics.
> + * Kyungmin Park <kyungmin.park@samsung.com>
> + * Tomasz Figa <t.figa@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _PLATFORM_FIRMWARE_H
> +#define _PLATFORM_FIRMWARE_H
> +
> +#include <linux/bug.h>
> +
> +/*
> + * struct platform_firmware_ops
> + *
> + * A structure to specify available firmware operations.
> + *
> + * A filled up structure can be registered with
> + * register_platform_firmware_ops().
> + */
> +struct platform_firmware_ops {
> +       /*
> +        * Enters CPU idle mode
> +        */
> +       int (*do_idle)(void);

Covered by PSCI already.

> +       /*
> +        * Sets boot address of specified physical CPU
> +        */
> +       int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);

Covered either by PSCI or spin-table release method (PSCI if firmware
call is required).

> +       /*
> +        * Boots specified physical CPU
> +        */
> +       int (*cpu_boot)(int cpu);

PSCI.

> +       /*
> +        * Initializes L2 cache
> +        */
> +       int (*l2x0_init)(void);

No L2x0 (L210, L220, PL310) cache on ARMv8. And here I strongly
recommend the hardware people to make proper external caches which can
be flushed by standard CPU instructions, not MMIO. Any such caches
must be enabled by firmware before Linux starts.

The above firmware API is 32-bit ARM only. Form 64-bit ARM, you have
the choice of PSCI so far but as I said in a long thread to Nico, I'm
open to other standard interfaces if there are good reasons PSCI
cannot be used. Note the _standard_ part, I don't want every SoC with
their own firmware API for standard things like secondary CPU
booting/hotplug/idle.
Alexandre Courbot Nov. 18, 2013, 3:05 a.m. UTC | #2
On 11/18/2013 12:59 AM, Catalin Marinas wrote:
> On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
>> The ARM tree includes a firmware_ops interface that is designed to
>> implement support for simple, TrustZone-based firmwares but could
>> also cover other use-cases. It has been suggested that this
>> interface might be useful to other architectures (e.g. arm64) and
>> that it should be moved out of arch/arm.
>
> NAK. I'm for code sharing with arm via common locations but this API
> goes against the ARMv8 firmware standardisation efforts like PSCI,
> encouraging each platform to define there own non-standard interface.

I have to say, I pretty much agree with your NAK.

The reason for this patch is that the suggestion to move firmware_ops 
out of arch/arm is the last (I hope) thing that prevents my Trusted 
Foundation support series from being merged. Now if we can all agree:

* that ARMv8 will only use PSCI
* that there is no use-case of this interface outside of arch/arm as of 
today (and none foreseen in the near future)
* that the firmware_ops interface is quite ARMv7-specific anyway,
* that should a need to move it (for whatever reason) occur later, it 
will be easy to do (as this patch hopefully demonstrates).

... then this has indeed no reason to be. And maybe I can finally get 
Russell's blessing on my series.

>
>> --- /dev/null
>> +++ b/include/linux/platform_firmware.h
>> @@ -0,0 +1,69 @@
>> +/*
>> + * Copyright (C) 2012 Samsung Electronics.
>> + * Kyungmin Park <kyungmin.park@samsung.com>
>> + * Tomasz Figa <t.figa@samsung.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef _PLATFORM_FIRMWARE_H
>> +#define _PLATFORM_FIRMWARE_H
>> +
>> +#include <linux/bug.h>
>> +
>> +/*
>> + * struct platform_firmware_ops
>> + *
>> + * A structure to specify available firmware operations.
>> + *
>> + * A filled up structure can be registered with
>> + * register_platform_firmware_ops().
>> + */
>> +struct platform_firmware_ops {
>> +       /*
>> +        * Enters CPU idle mode
>> +        */
>> +       int (*do_idle)(void);
>
> Covered by PSCI already.
>
>> +       /*
>> +        * Sets boot address of specified physical CPU
>> +        */
>> +       int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
>
> Covered either by PSCI or spin-table release method (PSCI if firmware
> call is required).
>
>> +       /*
>> +        * Boots specified physical CPU
>> +        */
>> +       int (*cpu_boot)(int cpu);
>
> PSCI.
>
>> +       /*
>> +        * Initializes L2 cache
>> +        */
>> +       int (*l2x0_init)(void);
>
> No L2x0 (L210, L220, PL310) cache on ARMv8. And here I strongly
> recommend the hardware people to make proper external caches which can
> be flushed by standard CPU instructions, not MMIO. Any such caches
> must be enabled by firmware before Linux starts.
>
> The above firmware API is 32-bit ARM only. Form 64-bit ARM, you have
> the choice of PSCI so far but as I said in a long thread to Nico, I'm
> open to other standard interfaces if there are good reasons PSCI
> cannot be used. Note the _standard_ part, I don't want every SoC with
> their own firmware API for standard things like secondary CPU
> booting/hotplug/idle.
>
Catalin Marinas Nov. 18, 2013, 11:58 a.m. UTC | #3
On Mon, Nov 18, 2013 at 03:05:59AM +0000, Alex Courbot wrote:
> On 11/18/2013 12:59 AM, Catalin Marinas wrote:
> > On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
> >> The ARM tree includes a firmware_ops interface that is designed to
> >> implement support for simple, TrustZone-based firmwares but could
> >> also cover other use-cases. It has been suggested that this
> >> interface might be useful to other architectures (e.g. arm64) and
> >> that it should be moved out of arch/arm.
> >
> > NAK. I'm for code sharing with arm via common locations but this API
> > goes against the ARMv8 firmware standardisation efforts like PSCI,
> > encouraging each platform to define there own non-standard interface.
> 
> I have to say, I pretty much agree with your NAK.
> 
> The reason for this patch is that the suggestion to move firmware_ops 
> out of arch/arm is the last (I hope) thing that prevents my Trusted 
> Foundation support series from being merged.

Moving it into drivers shouldn't be a workaround. Nice try ;).

> Now if we can all agree:
> 
> * that ARMv8 will only use PSCI

Or spin-table (which does not require secure calls). Otherwise, if
secure firmware is present, SoCs should use PSCI (as the only firmware
standard currently supported in the arm64 kernel).

However, things evolve and we may have other needs in the future or PSCI
may not be sufficient or we get newer PSCI revisions. This can be
extended but my requirement is to decouple booting standard from SoC
support (together with the aim of having no SoC-specific code under
arch/arm64). I really don't see why SoCs can't agree on one (or very
few) standard booting protocol (and legacy argument doesn't work since
the ARMv8 firmware needs to be converted to AArch64 anyway).

> * that there is no use-case of this interface outside of arch/arm as of 
> today (and none foreseen in the near future)

The firmware_ops are only used under arch/arm so far, I don't see any
drivers doing anything with it. Also, l2x0_init is ARMv7 only.

On arm64, support for PSCI is handled via cpu_operations in the latest
kernel. That's an arm64 abstraction and is extensible (but we want to
keep tight control of this, hence no register_cpu_ops function).

> * that the firmware_ops interface is quite ARMv7-specific anyway,

This was introduced to allow SoC code to enable hooks for SoC-specific
firmware calls like cpu_idle, l2x0_init. By standardising the interface
and decoupling it from SoC code on arm64, we don't need per-SoC
firmware_ops.

Of course, trusted foundations interface could be plugged into cpu_ops
on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
the SMC calling convention (and it's easy to fix when porting to ARMv8).
If a supported standard API is used, then there is no need for
additional code in the kernel.

BTW, is legacy code the reason for not converting the SMC # to PSCI?
It's already supported on ARMv7, so you may not have much code left to
merge in the kernel ;).

> * that should a need to move it (for whatever reason) occur later, it 
> will be easy to do (as this patch hopefully demonstrates).

I agree, it's not hard to unify this but so far I haven't seen a good
reason.
Stephen Warren Nov. 18, 2013, 5 p.m. UTC | #4
On 11/17/2013 08:59 AM, Catalin Marinas wrote:
> On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
>> The ARM tree includes a firmware_ops interface that is designed to
>> implement support for simple, TrustZone-based firmwares but could
>> also cover other use-cases. It has been suggested that this
>> interface might be useful to other architectures (e.g. arm64) and
>> that it should be moved out of arch/arm.
> 
> NAK. I'm for code sharing with arm via common locations but this API
> goes against the ARMv8 firmware standardisation efforts like PSCI,
> encouraging each platform to define there own non-standard interface.

Surely PSCI is *an* implementation of firmware_ops?

Couldn't firmware_ops be relevant to non-ARM architectures too? If so,
that would support my previous point; we're presumably not requiring
non-ARM architectures to implement PSCI?

On a practical note, unless ARM mandates by ARM architecture licensing
condition that mechanisms other than PSCI are not allowed, then they're
going to exist even if the upstream Linux community doesn't like it.
History has certainly shown that.
Stephen Warren Nov. 18, 2013, 5:03 p.m. UTC | #5
On 11/18/2013 04:58 AM, Catalin Marinas wrote:
...
> Of course, trusted foundations interface could be plugged into cpu_ops
> on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
> the SMC calling convention (and it's easy to fix when porting to ARMv8).
> If a supported standard API is used, then there is no need for
> additional code in the kernel.

What happens when someone takes an existing working secure-mode SW stack
and simply re-uses it on some new ARMv8 SoC. Are you going to force
people working on upstream to re-write the secure mode firmware in
shipped hardware before allowing upstream kernel support?
Russell King - ARM Linux Nov. 18, 2013, 5:10 p.m. UTC | #6
On Mon, Nov 18, 2013 at 10:03:37AM -0700, Stephen Warren wrote:
> On 11/18/2013 04:58 AM, Catalin Marinas wrote:
> ...
> > Of course, trusted foundations interface could be plugged into cpu_ops
> > on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
> > the SMC calling convention (and it's easy to fix when porting to ARMv8).
> > If a supported standard API is used, then there is no need for
> > additional code in the kernel.
> 
> What happens when someone takes an existing working secure-mode SW stack
> and simply re-uses it on some new ARMv8 SoC. Are you going to force
> people working on upstream to re-write the secure mode firmware in
> shipped hardware before allowing upstream kernel support?

I'll tell you what will happen.  They'll say "screw mainline, we're doing
our own thing".  Vendors have been doing that for years, this will be no
different and require no additional effort from them.
Russell King - ARM Linux Nov. 18, 2013, 5:14 p.m. UTC | #7
On Sun, Nov 17, 2013 at 03:59:04PM +0000, Catalin Marinas wrote:
> No L2x0 (L210, L220, PL310) cache on ARMv8. And here I strongly
> recommend the hardware people to make proper external caches which can
> be flushed by standard CPU instructions, not MMIO. Any such caches
> must be enabled by firmware before Linux starts.

Yea, and we've seen what a trainwreck that causes on 32-bit ARM with
the kernel exploding at boot time because of a dirty L2 cache.
Stephen Warren Nov. 18, 2013, 5:18 p.m. UTC | #8
On 11/18/2013 10:10 AM, Russell King - ARM Linux wrote:
> On Mon, Nov 18, 2013 at 10:03:37AM -0700, Stephen Warren wrote:
>> On 11/18/2013 04:58 AM, Catalin Marinas wrote:
>> ...
>>> Of course, trusted foundations interface could be plugged into cpu_ops
>>> on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
>>> the SMC calling convention (and it's easy to fix when porting to ARMv8).
>>> If a supported standard API is used, then there is no need for
>>> additional code in the kernel.
>>
>> What happens when someone takes an existing working secure-mode SW stack
>> and simply re-uses it on some new ARMv8 SoC. Are you going to force
>> people working on upstream to re-write the secure mode firmware in
>> shipped hardware before allowing upstream kernel support?
> 
> I'll tell you what will happen.  They'll say "screw mainline, we're doing
> our own thing".  Vendors have been doing that for years, this will be no
> different and require no additional effort from them.

Yes, that's my point.

However, what does that mean for those people within the company trying
to move the SW stack towards mainline? If the answer from upstream is:
"no, you can't support the shipping HW in mainline", rather than a
practical approach that recognizes that the HW/SW/firmware really does
exist and might be useful to support in mainline, then that just makes
the life of people trying to push for mainline that much harder.
Catalin Marinas Nov. 18, 2013, 5:23 p.m. UTC | #9
On Mon, Nov 18, 2013 at 05:00:32PM +0000, Stephen Warren wrote:
> On 11/17/2013 08:59 AM, Catalin Marinas wrote:
> > On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
> >> The ARM tree includes a firmware_ops interface that is designed to
> >> implement support for simple, TrustZone-based firmwares but could
> >> also cover other use-cases. It has been suggested that this
> >> interface might be useful to other architectures (e.g. arm64) and
> >> that it should be moved out of arch/arm.
> > 
> > NAK. I'm for code sharing with arm via common locations but this API
> > goes against the ARMv8 firmware standardisation efforts like PSCI,
> > encouraging each platform to define there own non-standard interface.
> 
> Surely PSCI is *an* implementation of firmware_ops?
> 
> Couldn't firmware_ops be relevant to non-ARM architectures too?

There are similarities but you don't ask other architectures to
implement an l2x0_init function. If we find other things we want to
describe in here, does this structure become a pool of function pointers
to be shared by other architectures? What's the common functionality
that you want to place in this structure?

> If so, that would support my previous point; we're presumably not
> requiring non-ARM architectures to implement PSCI?

So you think non-ARM architectures could make use of the firmware_ops?

> On a practical note, unless ARM mandates by ARM architecture licensing
> condition that mechanisms other than PSCI are not allowed, then they're
> going to exist even if the upstream Linux community doesn't like it.
> History has certainly shown that.

I'm pretty sure they will exist, as there is tons of kernel code in
production devices that never reach mainline. And I already stated a few
times, this interface can be extended, I just don't want one per SoC
just because some vendors want to use different SMC numbers.
Catalin Marinas Nov. 18, 2013, 5:30 p.m. UTC | #10
On Mon, Nov 18, 2013 at 05:03:37PM +0000, Stephen Warren wrote:
> On 11/18/2013 04:58 AM, Catalin Marinas wrote:
> ...
> > Of course, trusted foundations interface could be plugged into cpu_ops
> > on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
> > the SMC calling convention (and it's easy to fix when porting to ARMv8).
> > If a supported standard API is used, then there is no need for
> > additional code in the kernel.
> 
> What happens when someone takes an existing working secure-mode SW stack
> and simply re-uses it on some new ARMv8 SoC. Are you going to force
> people working on upstream to re-write the secure mode firmware in
> shipped hardware before allowing upstream kernel support?

Don't confuse the secure stack with the secure monitor running at EL3.
If you want AArch64 support for lower levels (EL2, EL1, EL0), your
monitor _must_ be AArch64. You can't run legacy AArch32 code at EL3 and
have lower levels in AArch64 mode (architectural constraint). You can
still keep the secure services at S-EL1 in AArch32, only that the SMCs
are handled by EL3 (and that's another aspect the SMC calling convention
spec is trying to address, mixed register-width secure/non-secure OSes).
Stephen Warren Nov. 18, 2013, 5:52 p.m. UTC | #11
On 11/18/2013 10:30 AM, Catalin Marinas wrote:
> On Mon, Nov 18, 2013 at 05:03:37PM +0000, Stephen Warren wrote:
>> On 11/18/2013 04:58 AM, Catalin Marinas wrote:
>> ...
>>> Of course, trusted foundations interface could be plugged into cpu_ops
>>> on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
>>> the SMC calling convention (and it's easy to fix when porting to ARMv8).
>>> If a supported standard API is used, then there is no need for
>>> additional code in the kernel.
>>
>> What happens when someone takes an existing working secure-mode SW stack
>> and simply re-uses it on some new ARMv8 SoC. Are you going to force
>> people working on upstream to re-write the secure mode firmware in
>> shipped hardware before allowing upstream kernel support?
> 
> Don't confuse the secure stack with the secure monitor running at EL3.
> If you want AArch64 support for lower levels (EL2, EL1, EL0), your
> monitor _must_ be AArch64. You can't run legacy AArch32 code at EL3 and
> have lower levels in AArch64 mode (architectural constraint).

I was assuming that vendors would take the existing source code and
simply rebuild it to create the AArch64 secure world. As such, the same
SMC IDs, same structures, etc. would be used. The only source difference
would be to perhaps change some 32-bit registers/struct-fields up to
64-bit. Naively that sounds like the lowest-effort way to get an AArch64
secure world, so I'm purely guessing that that's what vendors will do.

> You can
> still keep the secure services at S-EL1 in AArch32, only that the SMCs
> are handled by EL3 (and that's another aspect the SMC calling convention
> spec is trying to address, mixed register-width secure/non-secure OSes).

I'm not sure of the implications of that statement. Since you mention
SMCs being handled by EL3, I think the quick-and-dirty conversion I
mention above is still likely to be used.
Christopher Covington Nov. 18, 2013, 7:04 p.m. UTC | #12
Hi Catalin,

On 11/18/2013 12:30 PM, Catalin Marinas wrote:
[...]
> You can't run legacy AArch32 code at EL3 and have lower levels in AArch64
> mode (architectural constraint).

What prevents AArch32 code from running at EL3 and then requesting a reset to
AArch64 by writing to the Reset Management Register before sliding down to
lower exception levels?

Thanks,
Christopher
Alexandre Courbot Nov. 19, 2013, 2:46 a.m. UTC | #13
On 11/18/2013 08:58 PM, Catalin Marinas wrote:
> On Mon, Nov 18, 2013 at 03:05:59AM +0000, Alex Courbot wrote:
>> On 11/18/2013 12:59 AM, Catalin Marinas wrote:
>>> On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
>>>> The ARM tree includes a firmware_ops interface that is designed to
>>>> implement support for simple, TrustZone-based firmwares but could
>>>> also cover other use-cases. It has been suggested that this
>>>> interface might be useful to other architectures (e.g. arm64) and
>>>> that it should be moved out of arch/arm.
>>>
>>> NAK. I'm for code sharing with arm via common locations but this API
>>> goes against the ARMv8 firmware standardisation efforts like PSCI,
>>> encouraging each platform to define there own non-standard interface.
>>
>> I have to say, I pretty much agree with your NAK.
>>
>> The reason for this patch is that the suggestion to move firmware_ops
>> out of arch/arm is the last (I hope) thing that prevents my Trusted
>> Foundation support series from being merged.
>
> Moving it into drivers shouldn't be a workaround. Nice try ;).

Hehe. I thought that just sending a patch would settle the issue one way 
or the other and avoid a huge discussion. Woke up this morning to see 
how wrong I was.

>
>> Now if we can all agree:
>>
>> * that ARMv8 will only use PSCI
>
> Or spin-table (which does not require secure calls). Otherwise, if
> secure firmware is present, SoCs should use PSCI (as the only firmware
> standard currently supported in the arm64 kernel).
>
> However, things evolve and we may have other needs in the future or PSCI
> may not be sufficient or we get newer PSCI revisions. This can be
> extended but my requirement is to decouple booting standard from SoC
> support (together with the aim of having no SoC-specific code under
> arch/arm64). I really don't see why SoCs can't agree on one (or very
> few) standard booting protocol (and legacy argument doesn't work since
> the ARMv8 firmware needs to be converted to AArch64 anyway).
>
>> * that there is no use-case of this interface outside of arch/arm as of
>> today (and none foreseen in the near future)
>
> The firmware_ops are only used under arch/arm so far, I don't see any
> drivers doing anything with it. Also, l2x0_init is ARMv7 only.
>
> On arm64, support for PSCI is handled via cpu_operations in the latest
> kernel. That's an arm64 abstraction and is extensible (but we want to
> keep tight control of this, hence no register_cpu_ops function).
>
>> * that the firmware_ops interface is quite ARMv7-specific anyway,
>
> This was introduced to allow SoC code to enable hooks for SoC-specific
> firmware calls like cpu_idle, l2x0_init. By standardising the interface
> and decoupling it from SoC code on arm64, we don't need per-SoC
> firmware_ops.
>
> Of course, trusted foundations interface could be plugged into cpu_ops
> on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
> the SMC calling convention (and it's easy to fix when porting to ARMv8).
> If a supported standard API is used, then there is no need for
> additional code in the kernel.
>
> BTW, is legacy code the reason for not converting the SMC # to PSCI?
> It's already supported on ARMv7, so you may not have much code left to
> merge in the kernel ;).

The problem here is twofold:

1) we are just consumers of the TrustZone secure monitor who receive a 
binary and do not have any control over its calling conventions. I agree 
that it would be trivial to make it compatible with PSCI, but it's just 
not something we can make by ourselves (TF does not even follow the SMC 
calling convention). If this problem is to be addressed, it should be 
done by forcing the TrustZone secure monitors providers to follow PSCI.

2) devices have already shipped with this firmware. Are we going to just 
renounce supporting them, even though the necessary support is 
lightweight and fits within already existing interfaces?

I certainly do hope that for ARMv8 things will be different and more 
standardized. But that's not something that can be guaranteed unless ARM 
strongly enforces it to firmware vendors. In case such a non-standard 
firmware gets used again, I *do* hope that using cpu_ops will be 
preferred over saying "this device cannot be supported in mainline, ever".

The kernel already supports non-standard hardware, BIOS, ACPI through 
hacks that are *way* more horrible than that. This should certainly not 
be encouraged, but that's not a valid reason to forbid otherwise 
perfectly fine devices to run mainline IMHO.

>
>> * that should a need to move it (for whatever reason) occur later, it
>> will be easy to do (as this patch hopefully demonstrates).
>
> I agree, it's not hard to unify this but so far I haven't seen a good
> reason.

Same here. arm64 has its own cpu_operations. Other archs have different 
needs and if we move this to a common place it will just become a messy 
placeholder for function pointers from which each arch will only use a 
subset.

Not to mention that if we follow the logic completely, we should then 
implement PCSI on top of cpu_ops and cpu_ops on top of firmware_ops (or 
the other way around ;)).

Alex.
Catalin Marinas Nov. 19, 2013, 11:02 a.m. UTC | #14
On Mon, Nov 18, 2013 at 07:04:50PM +0000, Christopher Covington wrote:
> On 11/18/2013 12:30 PM, Catalin Marinas wrote:
> [...]
> > You can't run legacy AArch32 code at EL3 and have lower levels in AArch64
> > mode (architectural constraint).
> 
> What prevents AArch32 code from running at EL3 and then requesting a reset to
> AArch64 by writing to the Reset Management Register before sliding down to
> lower exception levels?

You can do this for some initial code but the firmware still needs to
switch to AArch64 before dropping to lower exception levels. What this
thread is about is run-time calls to firmware for booting secondary
CPUs, idle, l2x0. At this point, the code at EL3 must run in AArch64
mode. There is no way you can bounce between AArch32 and AArch64 modes
using reset just to handle some SMCs.
Catalin Marinas Nov. 19, 2013, 11:38 a.m. UTC | #15
On Mon, Nov 18, 2013 at 05:52:36PM +0000, Stephen Warren wrote:
> On 11/18/2013 10:30 AM, Catalin Marinas wrote:
> > On Mon, Nov 18, 2013 at 05:03:37PM +0000, Stephen Warren wrote:
> >> On 11/18/2013 04:58 AM, Catalin Marinas wrote:
> >> ...
> >>> Of course, trusted foundations interface could be plugged into cpu_ops
> >>> on arm64 but I will NAK it on the grounds of not using the PSCI API, nor
> >>> the SMC calling convention (and it's easy to fix when porting to ARMv8).
> >>> If a supported standard API is used, then there is no need for
> >>> additional code in the kernel.
> >>
> >> What happens when someone takes an existing working secure-mode SW stack
> >> and simply re-uses it on some new ARMv8 SoC. Are you going to force
> >> people working on upstream to re-write the secure mode firmware in
> >> shipped hardware before allowing upstream kernel support?
> > 
> > Don't confuse the secure stack with the secure monitor running at EL3.
> > If you want AArch64 support for lower levels (EL2, EL1, EL0), your
> > monitor _must_ be AArch64. You can't run legacy AArch32 code at EL3 and
> > have lower levels in AArch64 mode (architectural constraint).
> 
> I was assuming that vendors would take the existing source code and
> simply rebuild it to create the AArch64 secure world.

Some C code can probably be reused but not the EL3 entry/exit code,
world switching and AArch64 initialisation. The main differences in
ARMv8 EL3 is that it has its own MMU and it can only be entered via SMC
and exit via ERET (you can no longer switch from/to secure SVC by
writing to CPSR). So apart from a different instruction set, the new
exception model requires a rewrite of the secure monitor logic used to
handle SMCs, switch worlds, pass arguments between worlds.

> As such, the same SMC IDs, same structures, etc. would be used. The
> only source difference would be to perhaps change some 32-bit
> registers/struct-fields up to 64-bit. Naively that sounds like the
> lowest-effort way to get an AArch64 secure world, so I'm purely
> guessing that that's what vendors will do.

It looks simpler in theory until you hit the new exception model and
realise the clear separation between EL3 (previously secure monitor) and
secure EL1 (previously secure SVC). I'm not referring to the whole
secure stack here, just the things I mentioned above.

> > You can
> > still keep the secure services at S-EL1 in AArch32, only that the SMCs
> > are handled by EL3 (and that's another aspect the SMC calling convention
> > spec is trying to address, mixed register-width secure/non-secure OSes).
> 
> I'm not sure of the implications of that statement. Since you mention
> SMCs being handled by EL3, I think the quick-and-dirty conversion I
> mention above is still likely to be used.

What I meant is that a secure OS (providing cryptography, banking etc.
services) can run in secure EL1 in AArch32 mode, it does not need to be
converted (though it helps from a performance perspective, new
instructions). But the world switching (which is pretty tightly coupled
with secure SVC on ARMv7) and SMC handling need to be rewritten.

And it's usually EL3 where you would place power management firmware on
ARMv8 (cache/TLB maintenance, power controller access). This is usually
done by the SoC vendor and not the secure OS provider (the latter may do
the final link).
Catalin Marinas Nov. 19, 2013, 12:26 p.m. UTC | #16
On Tue, Nov 19, 2013 at 02:46:55AM +0000, Alex Courbot wrote:
> On 11/18/2013 08:58 PM, Catalin Marinas wrote:
> > On Mon, Nov 18, 2013 at 03:05:59AM +0000, Alex Courbot wrote:
> >> On 11/18/2013 12:59 AM, Catalin Marinas wrote:
> >>> On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
> >>>> The ARM tree includes a firmware_ops interface that is designed to
> >>>> implement support for simple, TrustZone-based firmwares but could
> >>>> also cover other use-cases. It has been suggested that this
> >>>> interface might be useful to other architectures (e.g. arm64) and
> >>>> that it should be moved out of arch/arm.
> >>>
> >>> NAK. I'm for code sharing with arm via common locations but this API
> >>> goes against the ARMv8 firmware standardisation efforts like PSCI,
> >>> encouraging each platform to define there own non-standard interface.
> >>
> >> I have to say, I pretty much agree with your NAK.
> >>
> >> The reason for this patch is that the suggestion to move firmware_ops
> >> out of arch/arm is the last (I hope) thing that prevents my Trusted
> >> Foundation support series from being merged.
> >
> > Moving it into drivers shouldn't be a workaround. Nice try ;).
> 
> Hehe. I thought that just sending a patch would settle the issue one way 
> or the other and avoid a huge discussion. Woke up this morning to see 
> how wrong I was.

It's a sensitive topic ;).

> > BTW, is legacy code the reason for not converting the SMC # to PSCI?
> > It's already supported on ARMv7, so you may not have much code left to
> > merge in the kernel ;).
> 
> The problem here is twofold:
> 
> 1) we are just consumers of the TrustZone secure monitor who receive a 
> binary and do not have any control over its calling conventions. I agree 
> that it would be trivial to make it compatible with PSCI, but it's just 
> not something we can make by ourselves (TF does not even follow the SMC 
> calling convention). If this problem is to be addressed, it should be 
> done by forcing the TrustZone secure monitors providers to follow PSCI.

I agree and such discussions do happen ('forcing' is a bit harder, more
like 'strongly recommending'). On my side, I voice this message via the
Linux channels, so SoC vendors can also encourage their secure provider
in this direction. The benefit is that the Linux changes are minimal
afterwards, single image is easier.

But as I replied to Stephen, make sure you separate the secure OS (EL1)
from the secure firmware (EL3). The latter (or parts of it) are provided
by the SoC vendor (e.g. NVidia) and may be eventually linked into a big
blob by the secure OS provider. ARM is encouraging separation here and a
multi-stage firmware loading approach (and ARM started a public generic
firmware project, it's in the early days now).

> 2) devices have already shipped with this firmware. Are we going to just 
> renounce supporting them, even though the necessary support is 
> lightweight and fits within already existing interfaces?

I'm talking only about ARMv8 here. Please see my reply to Stephen for
the details of (not) reusing existing firmware.

> I certainly do hope that for ARMv8 things will be different and more 
> standardized. But that's not something that can be guaranteed unless ARM 
> strongly enforces it to firmware vendors. In case such a non-standard 
> firmware gets used again, I *do* hope that using cpu_ops will be 
> preferred over saying "this device cannot be supported in mainline, ever".

cpu_ops or firmware_ops is just a name and can be unified (TBD what
common functionality it contains). What I don't want to encourage is
each SoC registering its own firmware interface.

> The kernel already supports non-standard hardware, BIOS, ACPI through 
> hacks that are *way* more horrible than that. This should certainly not 
> be encouraged, but that's not a valid reason to forbid otherwise 
> perfectly fine devices to run mainline IMHO.

So you say we should just stop trying to standardise anything because
people don't care anyway. Why do we even bother with DT (or ACPI) since
board files were fine in the past (with a bit more code)?

> >> * that should a need to move it (for whatever reason) occur later, it
> >> will be easy to do (as this patch hopefully demonstrates).
> >
> > I agree, it's not hard to unify this but so far I haven't seen a good
> > reason.
> 
> Same here. arm64 has its own cpu_operations. Other archs have different 
> needs and if we move this to a common place it will just become a messy 
> placeholder for function pointers from which each arch will only use a 
> subset.

That was my initial point but it turned into a thread against PSCI
(again ;)).
Alexandre Courbot Nov. 19, 2013, 2:29 p.m. UTC | #17
On Tue, Nov 19, 2013 at 9:26 PM, Catalin Marinas
<catalin.marinas@arm.com> wrote:
> On Tue, Nov 19, 2013 at 02:46:55AM +0000, Alex Courbot wrote:
>> On 11/18/2013 08:58 PM, Catalin Marinas wrote:
>> > On Mon, Nov 18, 2013 at 03:05:59AM +0000, Alex Courbot wrote:
>> >> On 11/18/2013 12:59 AM, Catalin Marinas wrote:
>> >>> On 17 November 2013 08:49, Alexandre Courbot <acourbot@nvidia.com> wrote:
>> >>>> The ARM tree includes a firmware_ops interface that is designed to
>> >>>> implement support for simple, TrustZone-based firmwares but could
>> >>>> also cover other use-cases. It has been suggested that this
>> >>>> interface might be useful to other architectures (e.g. arm64) and
>> >>>> that it should be moved out of arch/arm.
>> >>>
>> >>> NAK. I'm for code sharing with arm via common locations but this API
>> >>> goes against the ARMv8 firmware standardisation efforts like PSCI,
>> >>> encouraging each platform to define there own non-standard interface.
>> >>
>> >> I have to say, I pretty much agree with your NAK.
>> >>
>> >> The reason for this patch is that the suggestion to move firmware_ops
>> >> out of arch/arm is the last (I hope) thing that prevents my Trusted
>> >> Foundation support series from being merged.
>> >
>> > Moving it into drivers shouldn't be a workaround. Nice try ;).
>>
>> Hehe. I thought that just sending a patch would settle the issue one way
>> or the other and avoid a huge discussion. Woke up this morning to see
>> how wrong I was.
>
> It's a sensitive topic ;).
>
>> > BTW, is legacy code the reason for not converting the SMC # to PSCI?
>> > It's already supported on ARMv7, so you may not have much code left to
>> > merge in the kernel ;).
>>
>> The problem here is twofold:
>>
>> 1) we are just consumers of the TrustZone secure monitor who receive a
>> binary and do not have any control over its calling conventions. I agree
>> that it would be trivial to make it compatible with PSCI, but it's just
>> not something we can make by ourselves (TF does not even follow the SMC
>> calling convention). If this problem is to be addressed, it should be
>> done by forcing the TrustZone secure monitors providers to follow PSCI.
>
> I agree and such discussions do happen ('forcing' is a bit harder, more
> like 'strongly recommending'). On my side, I voice this message via the
> Linux channels, so SoC vendors can also encourage their secure provider
> in this direction. The benefit is that the Linux changes are minimal
> afterwards, single image is easier.
>
> But as I replied to Stephen, make sure you separate the secure OS (EL1)
> from the secure firmware (EL3). The latter (or parts of it) are provided
> by the SoC vendor (e.g. NVidia) and may be eventually linked into a big
> blob by the secure OS provider. ARM is encouraging separation here and a
> multi-stage firmware loading approach (and ARM started a public generic
> firmware project, it's in the early days now).

Will keep that in mind and check whether that could apply to future
devices, thanks.

>
>> 2) devices have already shipped with this firmware. Are we going to just
>> renounce supporting them, even though the necessary support is
>> lightweight and fits within already existing interfaces?
>
> I'm talking only about ARMv8 here. Please see my reply to Stephen for
> the details of (not) reusing existing firmware.
>
>> I certainly do hope that for ARMv8 things will be different and more
>> standardized. But that's not something that can be guaranteed unless ARM
>> strongly enforces it to firmware vendors. In case such a non-standard
>> firmware gets used again, I *do* hope that using cpu_ops will be
>> preferred over saying "this device cannot be supported in mainline, ever".
>
> cpu_ops or firmware_ops is just a name and can be unified (TBD what
> common functionality it contains). What I don't want to encourage is
> each SoC registering its own firmware interface.

Sorry, are you talking about interface as in SMC interface, or as in
cpu_operations/firmware_ops?

>
>> The kernel already supports non-standard hardware, BIOS, ACPI through
>> hacks that are *way* more horrible than that. This should certainly not
>> be encouraged, but that's not a valid reason to forbid otherwise
>> perfectly fine devices to run mainline IMHO.
>
> So you say we should just stop trying to standardise anything because
> people don't care anyway. Why do we even bother with DT (or ACPI) since
> board files were fine in the past (with a bit more code)?

Oh no, that's not what I am saying at all. Standardization is good.
PSCI is good. Of course I would prefer that the secure monitor we use
follow established conventions - that'd be less work to support it and
less hassle to get my patches merged.

I may have misunderstood you, but I felt your mail sounded a bit like
"we won't merge support for firmwares that do not follow PSCI". I
agree that whenever it is possible to support a firmware through a
standard interface, this should be done - no discussion. But right now
I have two devices that are good representatives of Tegra 4 and
available in stores, which I would like to see supported in mainline
to satisfy requests from the community for Tegra development
platforms, and also initiate the habit to support future
NVIDIA-branded devices in mainline. Their secure monitor unfortunately
does not follow PSCI or the SMC convention and needs a custom
firmware_ops. Are they unworthy of mainline?

And if, by sheer misfortune, the same thing happened on an ARMv8
device (despite the EL1/EL3 separation), what would be the outcome?

IMHO, more devices in mainline is beneficial to everybody, and
actually *encourages* SoC vendors/firmware providers to follow
conventions. Banning devices is what triggers the kind of "screw it"
reactions mentioned earlier, and on the contrary once a device is in,
you tend to make sure the next ones follow the kernel trends because
you know you will need to support them in mainline as well and it will
make your life easier.

>
>> >> * that should a need to move it (for whatever reason) occur later, it
>> >> will be easy to do (as this patch hopefully demonstrates).
>> >
>> > I agree, it's not hard to unify this but so far I haven't seen a good
>> > reason.
>>
>> Same here. arm64 has its own cpu_operations. Other archs have different
>> needs and if we move this to a common place it will just become a messy
>> placeholder for function pointers from which each arch will only use a
>> subset.
>
> That was my initial point but it turned into a thread against PSCI
> (again ;)).

Not at all, hurray for PSCI! :) But let the uncool devices get some
mainline love too!
Catalin Marinas Nov. 19, 2013, 3:07 p.m. UTC | #18
On Tue, Nov 19, 2013 at 02:29:39PM +0000, Alexandre Courbot wrote:
> On Tue, Nov 19, 2013 at 9:26 PM, Catalin Marinas
> <catalin.marinas@arm.com> wrote:
> > On Tue, Nov 19, 2013 at 02:46:55AM +0000, Alex Courbot wrote:
> >> 2) devices have already shipped with this firmware. Are we going to just
> >> renounce supporting them, even though the necessary support is
> >> lightweight and fits within already existing interfaces?
> >
> > I'm talking only about ARMv8 here. Please see my reply to Stephen for
> > the details of (not) reusing existing firmware.
> >
> >> I certainly do hope that for ARMv8 things will be different and more
> >> standardized. But that's not something that can be guaranteed unless ARM
> >> strongly enforces it to firmware vendors. In case such a non-standard
> >> firmware gets used again, I *do* hope that using cpu_ops will be
> >> preferred over saying "this device cannot be supported in mainline, ever".
> >
> > cpu_ops or firmware_ops is just a name and can be unified (TBD what
> > common functionality it contains). What I don't want to encourage is
> > each SoC registering its own firmware interface.
> 
> Sorry, are you talking about interface as in SMC interface, or as in
> cpu_operations/firmware_ops?

Both. I don't want to see platforms defining their own SMC interface for
no good reason. The cpu_ops/firmware_ops handling in the kernel is just
some naming but the key is having standard SMC interfaces for CPU
operations.

> >> The kernel already supports non-standard hardware, BIOS, ACPI through
> >> hacks that are *way* more horrible than that. This should certainly not
> >> be encouraged, but that's not a valid reason to forbid otherwise
> >> perfectly fine devices to run mainline IMHO.
> >
> > So you say we should just stop trying to standardise anything because
> > people don't care anyway. Why do we even bother with DT (or ACPI) since
> > board files were fine in the past (with a bit more code)?
> 
> Oh no, that's not what I am saying at all. Standardization is good.
> PSCI is good. Of course I would prefer that the secure monitor we use
> follow established conventions - that'd be less work to support it and
> less hassle to get my patches merged.
> 
> I may have misunderstood you, but I felt your mail sounded a bit like
> "we won't merge support for firmwares that do not follow PSCI".

Just to clarify it: I won't merge support for _ARMv8_ firmware that does
not follow a standard CPU booting/power protocol supported by Linux.
Currently we only support PSCI. If there is a need for another protocol
and a good proposal, I'm open for discussions.

The above is all related to having no SoC code under arch/arm64 (or
board files, whatever you want to call them).

> I
> agree that whenever it is possible to support a firmware through a
> standard interface, this should be done - no discussion. But right now
> I have two devices that are good representatives of Tegra 4 and
> available in stores, which I would like to see supported in mainline
> to satisfy requests from the community for Tegra development
> platforms, and also initiate the habit to support future
> NVIDIA-branded devices in mainline. Their secure monitor unfortunately
> does not follow PSCI or the SMC convention and needs a custom
> firmware_ops. Are they unworthy of mainline?

Are they ARMv8? Since we didn't have any such rules on ARMv7 and
earlier, standard secure interface is nice to have but should not
prevent upstreaming. I made this clear already that it is ARMv8 only,
please don't try to generalise it.

> And if, by sheer misfortune, the same thing happened on an ARMv8
> device (despite the EL1/EL3 separation), what would be the outcome?

If some people get it wrong and they have to work around firmware bugs
for devices already in the field, we may need to bend the rules (bugs do
happen, both in software and hardware). But definitely _not_ when people
don't even bother.

> IMHO, more devices in mainline is beneficial to everybody, and
> actually *encourages* SoC vendors/firmware providers to follow
> conventions. Banning devices is what triggers the kind of "screw it"
> reactions mentioned earlier,

By following some rules and doing things in a standard way (firmware
interface in this case), it is more likely that their SoC support
requires minimal kernel code and it's easier to upstream and maintain.

> and on the contrary once a device is in,
> you tend to make sure the next ones follow the kernel trends because
> you know you will need to support them in mainline as well and it will
> make your life easier.

Not really. The next device won't follow the kernel trends but just the
same non-standard way of doing things that were accepted in the first
place.
Alexandre Courbot Nov. 19, 2013, 3:17 p.m. UTC | #19
On Wed, Nov 20, 2013 at 12:07 AM, Catalin Marinas
<catalin.marinas@arm.com> wrote:
> On Tue, Nov 19, 2013 at 02:29:39PM +0000, Alexandre Courbot wrote:
>> On Tue, Nov 19, 2013 at 9:26 PM, Catalin Marinas
>> <catalin.marinas@arm.com> wrote:
>> > On Tue, Nov 19, 2013 at 02:46:55AM +0000, Alex Courbot wrote:
>> >> 2) devices have already shipped with this firmware. Are we going to just
>> >> renounce supporting them, even though the necessary support is
>> >> lightweight and fits within already existing interfaces?
>> >
>> > I'm talking only about ARMv8 here. Please see my reply to Stephen for
>> > the details of (not) reusing existing firmware.
>> >
>> >> I certainly do hope that for ARMv8 things will be different and more
>> >> standardized. But that's not something that can be guaranteed unless ARM
>> >> strongly enforces it to firmware vendors. In case such a non-standard
>> >> firmware gets used again, I *do* hope that using cpu_ops will be
>> >> preferred over saying "this device cannot be supported in mainline, ever".
>> >
>> > cpu_ops or firmware_ops is just a name and can be unified (TBD what
>> > common functionality it contains). What I don't want to encourage is
>> > each SoC registering its own firmware interface.
>>
>> Sorry, are you talking about interface as in SMC interface, or as in
>> cpu_operations/firmware_ops?
>
> Both. I don't want to see platforms defining their own SMC interface for
> no good reason. The cpu_ops/firmware_ops handling in the kernel is just
> some naming but the key is having standard SMC interfaces for CPU
> operations.

Fair enough.

>
>> >> The kernel already supports non-standard hardware, BIOS, ACPI through
>> >> hacks that are *way* more horrible than that. This should certainly not
>> >> be encouraged, but that's not a valid reason to forbid otherwise
>> >> perfectly fine devices to run mainline IMHO.
>> >
>> > So you say we should just stop trying to standardise anything because
>> > people don't care anyway. Why do we even bother with DT (or ACPI) since
>> > board files were fine in the past (with a bit more code)?
>>
>> Oh no, that's not what I am saying at all. Standardization is good.
>> PSCI is good. Of course I would prefer that the secure monitor we use
>> follow established conventions - that'd be less work to support it and
>> less hassle to get my patches merged.
>>
>> I may have misunderstood you, but I felt your mail sounded a bit like
>> "we won't merge support for firmwares that do not follow PSCI".
>
> Just to clarify it: I won't merge support for _ARMv8_ firmware that does
> not follow a standard CPU booting/power protocol supported by Linux.
> Currently we only support PSCI. If there is a need for another protocol
> and a good proposal, I'm open for discussions.
>
> The above is all related to having no SoC code under arch/arm64 (or
> board files, whatever you want to call them).
>
>> I
>> agree that whenever it is possible to support a firmware through a
>> standard interface, this should be done - no discussion. But right now
>> I have two devices that are good representatives of Tegra 4 and
>> available in stores, which I would like to see supported in mainline
>> to satisfy requests from the community for Tegra development
>> platforms, and also initiate the habit to support future
>> NVIDIA-branded devices in mainline. Their secure monitor unfortunately
>> does not follow PSCI or the SMC convention and needs a custom
>> firmware_ops. Are they unworthy of mainline?
>
> Are they ARMv8? Since we didn't have any such rules on ARMv7 and
> earlier, standard secure interface is nice to have but should not
> prevent upstreaming. I made this clear already that it is ARMv8 only,
> please don't try to generalise it.

Sorry, that was not my intention at all - I just misunderstood what
you meant. Thanks for clarifying it.

>
>> And if, by sheer misfortune, the same thing happened on an ARMv8
>> device (despite the EL1/EL3 separation), what would be the outcome?
>
> If some people get it wrong and they have to work around firmware bugs
> for devices already in the field, we may need to bend the rules (bugs do
> happen, both in software and hardware). But definitely _not_ when people
> don't even bother.

Ok, I guess for ARMv8 there is absolutely no excuse not to follow PSCI
anyways. We'll need to be careful about this one.

>
>> IMHO, more devices in mainline is beneficial to everybody, and
>> actually *encourages* SoC vendors/firmware providers to follow
>> conventions. Banning devices is what triggers the kind of "screw it"
>> reactions mentioned earlier,
>
> By following some rules and doing things in a standard way (firmware
> interface in this case), it is more likely that their SoC support
> requires minimal kernel code and it's easier to upstream and maintain.
>
>> and on the contrary once a device is in,
>> you tend to make sure the next ones follow the kernel trends because
>> you know you will need to support them in mainline as well and it will
>> make your life easier.
>
> Not really. The next device won't follow the kernel trends but just the
> same non-standard way of doing things that were accepted in the first
> place.

I guess that depends on whether you see the glass as half-empty or half-full. ;)

So just in case this was not clear already, this patch is withdrawn,
right. :P I hope the ARM maintainers will be ok with Trusted
Foundations support using firmware_ops in arch/arm for that's the best
we can do.

Thanks,
Alex.
diff mbox

Patch

diff --git a/Documentation/arm/firmware.txt b/Documentation/arm/firmware.txt
deleted file mode 100644
index c2e468f..0000000
--- a/Documentation/arm/firmware.txt
+++ /dev/null
@@ -1,88 +0,0 @@ 
-Interface for registering and calling firmware-specific operations for ARM.
-----
-Written by Tomasz Figa <t.figa@samsung.com>
-
-Some boards are running with secure firmware running in TrustZone secure
-world, which changes the way some things have to be initialized. This makes
-a need to provide an interface for such platforms to specify available firmware
-operations and call them when needed.
-
-Firmware operations can be specified using struct firmware_ops
-
-	struct firmware_ops {
-		/*
-		* Enters CPU idle mode
-		*/
-		int (*do_idle)(void);
-		/*
-		* Sets boot address of specified physical CPU
-		*/
-		int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
-		/*
-		* Boots specified physical CPU
-		*/
-		int (*cpu_boot)(int cpu);
-		/*
-		* Initializes L2 cache
-		*/
-		int (*l2x0_init)(void);
-	};
-
-and then registered with register_firmware_ops function
-
-	void register_firmware_ops(const struct firmware_ops *ops)
-
-the ops pointer must be non-NULL.
-
-There is a default, empty set of operations provided, so there is no need to
-set anything if platform does not require firmware operations.
-
-To call a firmware operation, a helper macro is provided
-
-	#define call_firmware_op(op, ...)				\
-		((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
-
-the macro checks if the operation is provided and calls it or otherwise returns
--ENOSYS to signal that given operation is not available (for example, to allow
-fallback to legacy operation).
-
-Example of registering firmware operations:
-
-	/* board file */
-
-	static int platformX_do_idle(void)
-	{
-		/* tell platformX firmware to enter idle */
-		return 0;
-	}
-
-	static int platformX_cpu_boot(int i)
-	{
-		/* tell platformX firmware to boot CPU i */
-		return 0;
-	}
-
-	static const struct firmware_ops platformX_firmware_ops = {
-		.do_idle        = exynos_do_idle,
-		.cpu_boot       = exynos_cpu_boot,
-		/* other operations not available on platformX */
-	};
-
-	/* init_early callback of machine descriptor */
-	static void __init board_init_early(void)
-	{
-		register_firmware_ops(&platformX_firmware_ops);
-	}
-
-Example of using a firmware operation:
-
-	/* some platform code, e.g. SMP initialization */
-
-	__raw_writel(virt_to_phys(exynos4_secondary_startup),
-		CPU1_BOOT_REG);
-
-	/* Call Exynos specific smc call */
-	if (call_firmware_op(cpu_boot, cpu) == -ENOSYS)
-		cpu_boot_legacy(...); /* Try legacy way */
-
-	gic_raise_softirq(cpumask_of(cpu), 1);
diff --git a/Documentation/firmware/platform_firmware.txt b/Documentation/firmware/platform_firmware.txt
new file mode 100644
index 0000000..db2a3e7
--- /dev/null
+++ b/Documentation/firmware/platform_firmware.txt
@@ -0,0 +1,89 @@ 
+Interface for registering and calling firmware-specific operations.
+----
+Written by Tomasz Figa <t.figa@samsung.com>
+
+Some boards are running with secure firmware running in secure world, which
+changes the way some things have to be initialized. This makes a need to provide
+an interface for such platforms to specify available firmware operations and
+call them when needed.
+
+Firmware operations can be specified using struct platform_firmware_ops
+
+	struct platform_firmware_ops {
+		/*
+		* Enters CPU idle mode
+		*/
+		int (*do_idle)(void);
+		/*
+		* Sets boot address of specified physical CPU
+		*/
+		int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
+		/*
+		* Boots specified physical CPU
+		*/
+		int (*cpu_boot)(int cpu);
+		/*
+		* Initializes L2 cache
+		*/
+		int (*l2x0_init)(void);
+	};
+
+and then registered with register_platform_firmware_ops function
+
+void register_platform_firmware_ops(const struct platform_firmware_ops *ops)
+
+the ops pointer must be non-NULL.
+
+There is a default, empty set of operations provided, so there is no need to
+set anything if platform does not require firmware operations.
+
+To call a firmware operation, a helper macro is provided
+
+	#define call_platform_firmware_op(op, ...)				\
+		((platform_firmware_ops->op) ?
+		platform_firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
+
+the macro checks if the operation is provided and calls it or otherwise returns
+-ENOSYS to signal that given operation is not available (for example, to allow
+fallback to legacy operation).
+
+Example of registering firmware operations:
+
+	/* board file */
+
+	static int platformX_do_idle(void)
+	{
+		/* tell platformX firmware to enter idle */
+		return 0;
+	}
+
+	static int platformX_cpu_boot(int i)
+	{
+		/* tell platformX firmware to boot CPU i */
+		return 0;
+	}
+
+	static const struct platform_firmware_ops platformX_firmware_ops = {
+		.do_idle        = exynos_do_idle,
+		.cpu_boot       = exynos_cpu_boot,
+		/* other operations not available on platformX */
+	};
+
+	/* init_early callback of machine descriptor */
+	static void __init board_init_early(void)
+	{
+		register_platform_firmware_ops(&platformX_firmware_ops);
+	}
+
+Example of using a firmware operation:
+
+	/* some platform code, e.g. SMP initialization */
+
+	__raw_writel(virt_to_phys(exynos4_secondary_startup),
+		CPU1_BOOT_REG);
+
+	/* Call Exynos specific smc call */
+	if (call_platform_firmware_op(cpu_boot, cpu) == -ENOSYS)
+		cpu_boot_legacy(...); /* Try legacy way */
+
+	gic_raise_softirq(cpumask_of(cpu), 1);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cc68e6d..9026af0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -218,6 +218,9 @@  config NEED_RET_TO_USER
 config ARCH_MTD_XIP
 	bool
 
+config ARCH_SUPPORTS_FIRMWARE
+	bool
+
 config VECTORS_BASE
 	hex
 	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -806,6 +809,8 @@  config ARCH_EXYNOS
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_SPARSEMEM_ENABLE
+	select ARCH_SUPPORTS_FIRMWARE
+	select EXYNOS_FIRMWARE
 	select ARM_GIC
 	select COMMON_CLK
 	select CPU_V7
@@ -2256,6 +2261,10 @@  source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+if ARCH_SUPPORTS_FIRMWARE
+source "drivers/firmware/Kconfig"
+endif
+
 source "fs/Kconfig"
 
 source "arch/arm/Kconfig.debug"
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 4bdc416..f98a991 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -2,8 +2,6 @@ 
 # Makefile for the linux kernel.
 #
 
-obj-y				+= firmware.o
-
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
diff --git a/arch/arm/common/firmware.c b/arch/arm/common/firmware.c
deleted file mode 100644
index 27ddccb..0000000
--- a/arch/arm/common/firmware.c
+++ /dev/null
@@ -1,18 +0,0 @@ 
-/*
- * Copyright (C) 2012 Samsung Electronics.
- * Kyungmin Park <kyungmin.park@samsung.com>
- * Tomasz Figa <t.figa@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/suspend.h>
-
-#include <asm/firmware.h>
-
-static const struct firmware_ops default_firmware_ops;
-
-const struct firmware_ops *firmware_ops = &default_firmware_ops;
diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h
deleted file mode 100644
index 1563130..0000000
--- a/arch/arm/include/asm/firmware.h
+++ /dev/null
@@ -1,66 +0,0 @@ 
-/*
- * Copyright (C) 2012 Samsung Electronics.
- * Kyungmin Park <kyungmin.park@samsung.com>
- * Tomasz Figa <t.figa@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_FIRMWARE_H
-#define __ASM_ARM_FIRMWARE_H
-
-#include <linux/bug.h>
-
-/*
- * struct firmware_ops
- *
- * A structure to specify available firmware operations.
- *
- * A filled up structure can be registered with register_firmware_ops().
- */
-struct firmware_ops {
-	/*
-	 * Enters CPU idle mode
-	 */
-	int (*do_idle)(void);
-	/*
-	 * Sets boot address of specified physical CPU
-	 */
-	int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
-	/*
-	 * Boots specified physical CPU
-	 */
-	int (*cpu_boot)(int cpu);
-	/*
-	 * Initializes L2 cache
-	 */
-	int (*l2x0_init)(void);
-};
-
-/* Global pointer for current firmware_ops structure, can't be NULL. */
-extern const struct firmware_ops *firmware_ops;
-
-/*
- * call_firmware_op(op, ...)
- *
- * Checks if firmware operation is present and calls it,
- * otherwise returns -ENOSYS
- */
-#define call_firmware_op(op, ...)					\
-	((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
-
-/*
- * register_firmware_ops(ops)
- *
- * A function to register platform firmware_ops struct.
- */
-static inline void register_firmware_ops(const struct firmware_ops *ops)
-{
-	BUG_ON(!ops);
-
-	firmware_ops = ops;
-}
-
-#endif
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 8930b66..7132d03 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -25,7 +25,7 @@  obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= exynos-smc.o
-obj-$(CONFIG_ARCH_EXYNOS)	+= firmware.o
+obj-$(CONFIG_EXYNOS_FIRMWARE)	+= firmware.o
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_exynos-smc.o		:=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index 932129e..6dc4938 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -13,8 +13,7 @@ 
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-
-#include <asm/firmware.h>
+#include <linux/platform_firmware.h>
 
 #include <mach/map.h>
 
@@ -40,7 +39,7 @@  static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 	return 0;
 }
 
-static const struct firmware_ops exynos_firmware_ops = {
+static const struct platform_firmware_ops exynos_firmware_ops = {
 	.do_idle		= exynos_do_idle,
 	.set_cpu_boot_addr	= exynos_set_cpu_boot_addr,
 	.cpu_boot		= exynos_cpu_boot,
@@ -64,5 +63,5 @@  void __init exynos_firmware_init(void)
 
 	pr_info("Running under secure firmware.\n");
 
-	register_firmware_ops(&exynos_firmware_ops);
+	register_platform_firmware_ops(&exynos_firmware_ops);
 }
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 58b43e6..132d21c 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -20,11 +20,11 @@ 
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/platform_firmware.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <asm/firmware.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
@@ -150,10 +150,11 @@  static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 		 * Try to set boot address using firmware first
 		 * and fall back to boot register if it fails.
 		 */
-		if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+		if (call_platform_firmware_op(set_cpu_boot_addr, phys_cpu,
+					      boot_addr))
 			__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
 
-		call_firmware_op(cpu_boot, phys_cpu);
+		call_platform_firmware_op(cpu_boot, phys_cpu);
 
 		arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
@@ -225,7 +226,8 @@  static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 		phys_cpu = cpu_logical_map(i);
 		boot_addr = virt_to_phys(exynos4_secondary_startup);
 
-		if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+		if (call_platform_firmware_op(set_cpu_boot_addr, phys_cpu,
+					      boot_addr))
 			__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
 	}
 }
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 0747872..1fb9da6 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -129,6 +129,14 @@  config ISCSI_IBFT
 	  detect iSCSI boot parameters dynamically during system boot, say Y.
 	  Otherwise, say N.
 
+config PLATFORM_FIRMWARE
+	bool
+
+config EXYNOS_FIRMWARE
+	bool "Support for Exynos secure firmware"
+	select PLATFORM_FIRMWARE
+	depends on ARM && ARCH_EXYNOS
+
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
 
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 299fad6..9cd2231 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -11,6 +11,7 @@  obj-$(CONFIG_DMIID)		+= dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+obj-$(CONFIG_PLATFORM_FIRMWARE) += platform_firmware.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
diff --git a/drivers/firmware/platform_firmware.c b/drivers/firmware/platform_firmware.c
new file mode 100644
index 0000000..1644df2
--- /dev/null
+++ b/drivers/firmware/platform_firmware.c
@@ -0,0 +1,17 @@ 
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/platform_firmware.h>
+
+static const struct platform_firmware_ops default_ops;
+
+const struct platform_firmware_ops *platform_firmware_ops = &default_ops;
diff --git a/include/linux/platform_firmware.h b/include/linux/platform_firmware.h
new file mode 100644
index 0000000..601e3fd
--- /dev/null
+++ b/include/linux/platform_firmware.h
@@ -0,0 +1,69 @@ 
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PLATFORM_FIRMWARE_H
+#define _PLATFORM_FIRMWARE_H
+
+#include <linux/bug.h>
+
+/*
+ * struct platform_firmware_ops
+ *
+ * A structure to specify available firmware operations.
+ *
+ * A filled up structure can be registered with
+ * register_platform_firmware_ops().
+ */
+struct platform_firmware_ops {
+	/*
+	 * Enters CPU idle mode
+	 */
+	int (*do_idle)(void);
+	/*
+	 * Sets boot address of specified physical CPU
+	 */
+	int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
+	/*
+	 * Boots specified physical CPU
+	 */
+	int (*cpu_boot)(int cpu);
+	/*
+	 * Initializes L2 cache
+	 */
+	int (*l2x0_init)(void);
+};
+
+/* Global pointer for current firmware_ops structure, can't be NULL. */
+extern const struct platform_firmware_ops *platform_firmware_ops;
+
+/*
+ * call_platform_firmware_op(op, ...)
+ *
+ * Checks if firmware operation is present and calls it,
+ * otherwise returns -ENOSYS
+ */
+#define call_platform_firmware_op(op, ...)				\
+	((platform_firmware_ops->op) ?					\
+	platform_firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
+
+/*
+ * register_platform_firmware_ops(ops)
+ *
+ * A function to register platform firmware_ops struct.
+ */
+static inline
+void register_platform_firmware_ops(const struct platform_firmware_ops *ops)
+{
+	BUG_ON(!ops);
+
+	platform_firmware_ops = ops;
+}
+
+#endif