ARM: tegra: support running in non-secure mode
When the CPU is in non-secure (NS) mode (when running U-Boot under a
secure monitor), certain actions cannot be taken, since they would need
to write to secure-only registers. One example is configuring the ARM
architectural timer's CNTFRQ register.
We could support this in one of two ways:
1) Compile twice, once for secure mode (in which case anything goes) and
once for non-secure mode (in which case certain actions are disabled).
This complicates things, since everyone needs to keep track of
different U-Boot binaries for different situations.
2) Detect NS mode at run-time, and optionally skip any impossible actions.
This has the advantage of a single U-Boot binary working in all cases.
(2) is not possible on ARM in general, since there's no architectural way
to detect secure-vs-non-secure. However, there is a Tegra-specific way to
detect this.
This patches uses that feature to detect secure vs. NS mode on Tegra, and
uses that to:
* Skip the ARM arch timer initialization.
* Set/clear an environment variable so that boot scripts can take
different action depending on which mode the CPU is in. This might be
something like:
if CPU is secure:
load secure monitor code into RAM.
boot secure monitor.
secure monitor will restart (a new copy of) U-Boot in NS mode.
else:
execute normal boot process
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
This commit is contained in:
committed by
Tom Warren
parent
026baff755
commit
73c38934da
7
README
7
README
@@ -621,6 +621,13 @@ The following options need to be configured:
|
||||
exists, unlike the similar options in the Linux kernel. Do not
|
||||
set these options unless they apply!
|
||||
|
||||
- Tegra SoC options:
|
||||
CONFIG_TEGRA_SUPPORT_NON_SECURE
|
||||
|
||||
Support executing U-Boot in non-secure (NS) mode. Certain
|
||||
impossible actions will be skipped if the CPU is in NS mode,
|
||||
such as ARM architectural timer initialization.
|
||||
|
||||
- Driver Model
|
||||
Driver model is a new framework for devices in U-Boot
|
||||
introduced in early 2014. U-Boot is being progressively
|
||||
|
||||
@@ -74,3 +74,7 @@ static inline void config_vpr(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||
bool tegra_cpu_is_non_secure(void);
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <asm/arch/funcmux.h>
|
||||
#include <asm/arch/mc.h>
|
||||
#include <asm/arch/tegra.h>
|
||||
#include <asm/arch-tegra/ap.h>
|
||||
#include <asm/arch-tegra/board.h>
|
||||
#include <asm/arch-tegra/pmc.h>
|
||||
#include <asm/arch-tegra/sys_proto.h>
|
||||
@@ -28,6 +29,24 @@ enum {
|
||||
UART_COUNT = 5,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||
#if !defined(CONFIG_TEGRA124)
|
||||
#error tegra_cpu_is_non_secure has only been validated on Tegra124
|
||||
#endif
|
||||
bool tegra_cpu_is_non_secure(void)
|
||||
{
|
||||
/*
|
||||
* This register reads 0xffffffff in non-secure mode. This register
|
||||
* only implements bits 31:20, so the lower bits will always read 0 in
|
||||
* secure mode. Thus, the lower bits are an indicator for secure vs.
|
||||
* non-secure mode.
|
||||
*/
|
||||
struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE;
|
||||
uint32_t mc_s_cfg0 = readl(&mc->mc_security_cfg0);
|
||||
return (mc_s_cfg0 & 1) == 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the RAM size directly from the memory controller */
|
||||
unsigned int query_sdram_size(void)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/tegra.h>
|
||||
#include <asm/arch-tegra/ap.h>
|
||||
#include <asm/arch-tegra/clk_rst.h>
|
||||
#include <asm/arch-tegra/timer.h>
|
||||
#include <div64.h>
|
||||
@@ -573,7 +574,10 @@ void clock_init(void)
|
||||
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
|
||||
|
||||
/* Do any special system timer/TSC setup */
|
||||
arch_timer_init();
|
||||
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||
if (!tegra_cpu_is_non_secure())
|
||||
#endif
|
||||
arch_timer_init();
|
||||
}
|
||||
|
||||
static void set_avp_clock_source(u32 src)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asm/arch/pwm.h>
|
||||
#endif
|
||||
#include <asm/arch/tegra.h>
|
||||
#include <asm/arch-tegra/ap.h>
|
||||
#include <asm/arch-tegra/board.h>
|
||||
#include <asm/arch-tegra/clk_rst.h>
|
||||
#include <asm/arch-tegra/pmc.h>
|
||||
@@ -179,6 +180,14 @@ int board_late_init(void)
|
||||
#ifdef CONFIG_LCD
|
||||
/* Make sure we finish initing the LCD */
|
||||
tegra_lcd_check_next_stage(gd->fdt_blob, 1);
|
||||
#endif
|
||||
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||
if (tegra_cpu_is_non_secure()) {
|
||||
printf("CPU is in NS mode\n");
|
||||
setenv("cpu_ns_mode", "1");
|
||||
} else {
|
||||
setenv("cpu_ns_mode", "");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user