From: Stephen Warren Date: Mon, 19 Jan 2015 23:25:52 +0000 (-0700) Subject: ARM: tegra: support running in non-secure mode X-Git-Tag: v2015.04-rc4~31^2~15 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=73c38934daa10b518b20f2d21298fc8a8226843b;p=u-boot 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 Signed-off-by: Tom Warren --- diff --git a/README b/README index ba57dc5617..8a4c5a721e 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/include/asm/arch-tegra/ap.h b/arch/arm/include/asm/arch-tegra/ap.h index 5c8be94d97..ca40e4e0bc 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/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index 87511a31df..0ebaf19325 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -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/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 11c7435505..7c274b5f99 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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/board/nvidia/common/board.c b/board/nvidia/common/board.c index 80ef8fdcb2..018dddba15 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -21,6 +21,7 @@ #include #endif #include +#include #include #include #include @@ -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; }