[U-Boot] [PATCH v2 11/12] tegra124: Reserve secure RAM using MC_SECURITY_CFG{0, 1}_0

Mark Rutland
2015-02-16T13:49:20Z

On Mon, Feb 16, 2015 at 12:54:48PM +0000, Jan Kiszka wrote:
> From: Ian Campbell <ijc@hellion.org.uk>
>
> These registers can be used to prevent non-secure world from accessing a
> megabyte aligned region of RAM, use them to protect the u-boot secure monitor
> code.

What happens if the CPU tried to read this memory from the non-secure
world? If the OS has it mapped then the CPU could perform speculative
reads at any point in time.

If that can raise an abort then the OS needs to not map the region.

I take it U-Boot uses a secure mapping for the region (which I believe
should avoid the mismatched attributes issue I mentioned in my other
reply).

Thanks,
Mark.

> At first I tried to do this from s_init(), however this inexplicably causes
> u-boot's networking (e.g. DHCP) to fail, while networking under Linux was fine.
>
> So instead I have added a new weak arch function protect_secure_section()
> called from relocate_secure_section() and reserved the region there. This is
> better overall since it defers the reservation until after the sec vs. non-sec
> decision (which can be influenced by an envvar) has been made when booting the
> os.
>
> Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> arch/arm/cpu/armv7/virt-v7.c | 5 +++++
> arch/arm/cpu/tegra-common/ap.c | 15 +++++++++++++++
> arch/arm/include/asm/system.h | 1 +
> 3 files changed, 21 insertions(+)
>
> diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
> index b69fd37..eb6195c 100644
> --- a/arch/arm/cpu/armv7/virt-v7.c
> +++ b/arch/arm/cpu/armv7/virt-v7.c
> @@ -46,6 +46,10 @@ static unsigned long get_gicd_base_address(void)
> #endif
> }
>
> +/* Define a specific version of this function to enable any available
> + * hardware protections for the reserved region */
> +void __weak protect_secure_section(void) {}
> +
> static void relocate_secure_section(void)
> {
> #ifdef CONFIG_ARMV7_SECURE_BASE
> @@ -54,6 +58,7 @@ static void relocate_secure_section(void)
> memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz);
> flush_dcache_range(CONFIG_ARMV7_SECURE_BASE,
> CONFIG_ARMV7_SECURE_BASE + sz + 1);
> + protect_secure_section();
> invalidate_icache_all();
> #endif
> }
> diff --git a/arch/arm/cpu/tegra-common/ap.c b/arch/arm/cpu/tegra-common/ap.c
> index a17dfd1..f1d3070 100644
> --- a/arch/arm/cpu/tegra-common/ap.c
> +++ b/arch/arm/cpu/tegra-common/ap.c
> @@ -10,6 +10,7 @@
> #include <common.h>
> #include <asm/io.h>
> #include <asm/arch/gp_padctrl.h>
> +#include <asm/arch/mc.h>
> #include <asm/arch-tegra/ap.h>
> #include <asm/arch-tegra/clock.h>
> #include <asm/arch-tegra/fuse.h>
> @@ -154,6 +155,20 @@ static void init_pmc_scratch(void)
> writel(odmdata, &pmc->pmc_scratch20);
> }
>
> +#ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE
> +void protect_secure_section(void)
> +{
> + struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE;
> +
> + /* Must be MB aligned */
> + BUILD_BUG_ON(CONFIG_ARMV7_SECURE_BASE & 0xFFFFF);
> + BUILD_BUG_ON(CONFIG_ARMV7_SECURE_RESERVE_SIZE & 0xFFFFF);
> +
> + writel(CONFIG_ARMV7_SECURE_BASE, &mc->mc_security_cfg0);
> + writel(CONFIG_ARMV7_SECURE_RESERVE_SIZE>>20, &mc->mc_security_cfg1);
> +}
> +#endif
> +
> void s_init(void)
> {
> /* Init PMC scratch memory */
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index 89f2294..21be69d 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -76,6 +76,7 @@ void armv8_switch_to_el1(void);
> void gic_init(void);
> void gic_send_sgi(unsigned long sgino);
> void wait_for_wakeup(void);
> +void protect_secure_region(void);
> void smp_kick_all_cpus(void);
>
> void flush_l3_cache(void);
> --
> 2.1.4
>
>