1
0
Fork 0

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>
utp
Stephen Warren 2015-01-19 16:25:52 -07:00 committed by Tom Warren
parent 026baff755
commit 73c38934da
5 changed files with 44 additions and 1 deletions

7
README
View File

@ -621,6 +621,13 @@ The following options need to be configured:
exists, unlike the similar options in the Linux kernel. Do not exists, unlike the similar options in the Linux kernel. Do not
set these options unless they apply! 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
Driver model is a new framework for devices in U-Boot Driver model is a new framework for devices in U-Boot
introduced in early 2014. U-Boot is being progressively introduced in early 2014. U-Boot is being progressively

View File

@ -74,3 +74,7 @@ static inline void config_vpr(void)
{ {
} }
#endif #endif
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
bool tegra_cpu_is_non_secure(void);
#endif

View File

@ -11,6 +11,7 @@
#include <asm/arch/funcmux.h> #include <asm/arch/funcmux.h>
#include <asm/arch/mc.h> #include <asm/arch/mc.h>
#include <asm/arch/tegra.h> #include <asm/arch/tegra.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/board.h> #include <asm/arch-tegra/board.h>
#include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/sys_proto.h> #include <asm/arch-tegra/sys_proto.h>
@ -28,6 +29,24 @@ enum {
UART_COUNT = 5, 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 */ /* Read the RAM size directly from the memory controller */
unsigned int query_sdram_size(void) unsigned int query_sdram_size(void)
{ {

View File

@ -20,6 +20,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/clock.h> #include <asm/arch/clock.h>
#include <asm/arch/tegra.h> #include <asm/arch/tegra.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/clk_rst.h> #include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/timer.h> #include <asm/arch-tegra/timer.h>
#include <div64.h> #include <div64.h>
@ -573,7 +574,10 @@ void clock_init(void)
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]); debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
/* Do any special system timer/TSC setup */ /* 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) static void set_avp_clock_source(u32 src)

View File

@ -21,6 +21,7 @@
#include <asm/arch/pwm.h> #include <asm/arch/pwm.h>
#endif #endif
#include <asm/arch/tegra.h> #include <asm/arch/tegra.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/board.h> #include <asm/arch-tegra/board.h>
#include <asm/arch-tegra/clk_rst.h> #include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/pmc.h>
@ -179,6 +180,14 @@ int board_late_init(void)
#ifdef CONFIG_LCD #ifdef CONFIG_LCD
/* Make sure we finish initing the LCD */ /* Make sure we finish initing the LCD */
tegra_lcd_check_next_stage(gd->fdt_blob, 1); 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 #endif
return 0; return 0;
} }