[U-Boot] [PATCH 2/2] ARM: tegra: support running in non-secure mode

Stephen Warren swarren at wwwdotorg.org
Tue Jan 20 00:25:52 CET 2015


From: Stephen Warren <swarren at nvidia.com>

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 at nvidia.com>
---
 README                               |  7 +++++++
 arch/arm/cpu/tegra-common/board.c    | 19 +++++++++++++++++++
 arch/arm/cpu/tegra-common/clock.c    |  6 +++++-
 arch/arm/include/asm/arch-tegra/ap.h |  4 ++++
 board/nvidia/common/board.c          |  9 +++++++++
 5 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/README b/README
index fefa71c0a6c5..4d4ffc9c495f 100644
--- a/README
+++ b/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
diff --git a/arch/arm/cpu/tegra-common/board.c b/arch/arm/cpu/tegra-common/board.c
index 87511a31df18..0ebaf1932556 100644
--- a/arch/arm/cpu/tegra-common/board.c
+++ b/arch/arm/cpu/tegra-common/board.c
@@ -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)
 {
diff --git a/arch/arm/cpu/tegra-common/clock.c b/arch/arm/cpu/tegra-common/clock.c
index 11c7435505c1..7c274b5f9940 100644
--- a/arch/arm/cpu/tegra-common/clock.c
+++ b/arch/arm/cpu/tegra-common/clock.c
@@ -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)
diff --git a/arch/arm/include/asm/arch-tegra/ap.h b/arch/arm/include/asm/arch-tegra/ap.h
index 5c8be94d9772..ca40e4e0bce6 100644
--- a/arch/arm/include/asm/arch-tegra/ap.h
+++ b/arch/arm/include/asm/arch-tegra/ap.h
@@ -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
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 80ef8fdcb23b..018dddba1558 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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>
@@ -180,6 +181,14 @@ int board_late_init(void)
 	/* 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;
 }
 
-- 
1.9.1



More information about the U-Boot mailing list