Subject: Multi-platform, and secure-only ARM errata workarounds

From: [email-masked] (Stephen Warren)
Date: Fri, 01 Mar 2013 10:37:27 -0700

On 02/26/2013 11:11 AM, Russell King - ARM Linux wrote:
...
> The whole errata business is a total nightmare - and it gets much worse
> with the advent of multi-SoC kernels.  We don't have an answer to this
> other than disabling these troublesome errata and requiring the code
> which comes before the kernel to do whatever is necessary.

So for the initial boot, I can see that the bootloader can apply any
WARs that are required, irrespective of whether the code that comes
before the kernel is a secure monitor, a regular bootloader and/or
whether the kernel ends up running in secure or normal world.

I have one question on this case though: For erratum 751472 (An
interrupted ICIALLUIS operation may prevent the completion of a
following broadcasted operation), one of our engineers asserts:

This is valid only for SMP configurations and since bootloader has only
one CPU (CPU0) up and running, this is not valid for Bootloader.

Is that assertion correct? I assume that the WAR can be enabled
irrespective of whether SMP is actively in use, and shouldn't negatively
affect single-CPU operation in the bootloader. Hence, the bootloader or
secure monitor should always apply this WAR.

Now on to other scenarios: What about booting secondary CPUs, in cases
such as: initial kernel boot, CPU hotplug, CPU power saving.

Since some of the bits that enable WARs are banked per CPU, the WAR
needs to be enabled by code running on each individual CPU, each time
it's powered on. When a secure monitor exists, the CPU will boot through
it (at least on Tegra, there is a single register that defines the boot
vector for all CPUs; I don't know if that fact is ARM-architectural or
not), so the secure monitor can apply the WAR if needed. However, when
there is no secure monitor and the kernel runs in secure world, the
kernel would have to apply those WARs, since the only code that runs is
in the kernel.

But that leads to the question: How does the secondary CPU boot vector
code in the kernel know whether it can/should apply the WARs? It only
can if the kernel is running in secure mode, and that isn't always the
case, and there's no easy way to detect this at run-time. (It usually is
with any upstream SW, but we presumably want to support running the
upstream kernel on boards that were repurposed and have a secure monitor).

Apparently, the solution we have downstream is a Kconfig option that
selects whether the kernel should support running in secure world or
normal world, and hence whether to apply the WARs or not. Obviously that
won't work well with a multi-platform kernel.

The solutions that come to mind are:

1)

Assume that Tegra kernels always run in secure world, and so the WARs
can be applied in the Tegra-specific secondary CPU boot code. The
bootloader would still have to apply WARs for the initial CPU0 boot,
since the kernel code for that is common, so we can't assume we're
running in secure mode there. I guess that upstream we have no support
for running under a secure monitor on Tegra yet though, so perhaps this
isn't so bad (e.g. we don't make an SMC call to set the CPU boot vector,
but rather just write to the register directly). Still, making this
assumption would only be a temporary solution until we actually do
support running under a secure monitor upstream.

2)

Assume that we're always running in normal world, and mandate that a
secure monitor must exist, and push the WARs into it. That would require
implementing a simple secure monitor and using it for the cases where
one otherwise wouldn't exist.

Neither seems entirely ideal.

Perhaps one more option: I wonder if we can play games like reading the
CPU boot vector register; if it's equal to the kernel's value then we
must have been running in secure mode since we wrote it, but otherwise
we must have booted through a secure monitor?