diff options
author | Etienne Carriere <etienne.carriere@st.com> | 2017-08-09 15:48:53 +0200 |
---|---|---|
committer | Etienne Carriere <etienne.carriere@st.com> | 2017-08-09 15:48:53 +0200 |
commit | 71816096da8e5612cece752d813e10580df9f141 (patch) | |
tree | ead9a6012f806050f68efc5e343e2924a0efb9ba /bl32/sp_min | |
parent | 2f860c7815c648393f0604c872d5b39546da6419 (diff) |
bl32: add secure interrupt handling in AArch32 sp_min
Add support for a minimal secure interrupt service in sp_min for
the AArch32 implementation. Hard code that only FIQs are handled.
Introduce bolean build directive SP_MIN_WITH_SECURE_FIQ to enable
FIQ handling from SP_MIN.
Configure SCR[FIQ] and SCR[FW] from generic code for both cold and
warm boots to handle FIQ in secure state from monitor.
Since SP_MIN architecture, FIQ are always trapped when system executes
in non secure state. Hence discard relay of the secure/non-secure
state in the FIQ handler.
Change-Id: I1f7d1dc7b21f6f90011b7f3fcd921e455592f5e7
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
Diffstat (limited to 'bl32/sp_min')
-rw-r--r-- | bl32/sp_min/aarch32/entrypoint.S | 59 | ||||
-rw-r--r-- | bl32/sp_min/sp_min.mk | 6 | ||||
-rw-r--r-- | bl32/sp_min/sp_min_main.c | 16 | ||||
-rw-r--r-- | bl32/sp_min/sp_min_private.h | 1 |
4 files changed, 81 insertions, 1 deletions
diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S index b3fccdec..d868c53d 100644 --- a/bl32/sp_min/aarch32/entrypoint.S +++ b/bl32/sp_min/aarch32/entrypoint.S @@ -18,6 +18,17 @@ .globl sp_min_entrypoint .globl sp_min_warm_entrypoint + .macro route_fiq_to_sp_min reg + /* ----------------------------------------------------- + * FIQs are secure interrupts trapped by Monitor and non + * secure is not allowed to mask the FIQs. + * ----------------------------------------------------- + */ + ldcopr \reg, SCR + orr \reg, \reg, #SCR_FIQ_BIT + bic \reg, \reg, #SCR_FW_BIT + stcopr \reg, SCR + .endm vector_base sp_min_vector_table b sp_min_entrypoint @@ -27,7 +38,7 @@ vector_base sp_min_vector_table b plat_panic_handler /* Data abort */ b plat_panic_handler /* Reserved */ b plat_panic_handler /* IRQ */ - b plat_panic_handler /* FIQ */ + b handle_fiq /* FIQ */ /* @@ -92,6 +103,10 @@ func sp_min_entrypoint mov r1, #0 #endif /* RESET_TO_SP_MIN */ +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r4 +#endif + bl sp_min_early_platform_setup bl sp_min_plat_arch_setup @@ -166,6 +181,44 @@ func handle_smc endfunc handle_smc /* + * Secure Interrupts handling function for SP_MIN. + */ +func handle_fiq +#if !SP_MIN_WITH_SECURE_FIQ + b plat_panic_handler +#else + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + + smcc_save_gp_mode_regs + + /* + * AArch32 architectures need to clear the exclusive access when + * entering Monitor mode. + */ + clrex + + /* load run-time stack */ + mov r2, sp + ldr sp, [r2, #SMC_CTX_SP_MON] + + /* Switch to Secure Mode */ + ldr r0, [r2, #SMC_CTX_SCR] + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + push {r2, r3} + bl sp_min_fiq + pop {r0, r3} + + b sp_min_exit +#endif +endfunc handle_fiq + +/* * The Warm boot entrypoint for SP_MIN. */ func sp_min_warm_entrypoint @@ -213,6 +266,10 @@ func sp_min_warm_entrypoint mov r0, #DISABLE_DCACHE bl bl32_plat_enable_mmu +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r0 +#endif + #if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY ldcopr r0, SCTLR orr r0, r0, #SCTLR_C_BIT diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk index f6e58e97..39588ce7 100644 --- a/bl32/sp_min/sp_min.mk +++ b/bl32/sp_min/sp_min.mk @@ -37,3 +37,9 @@ endif RESET_TO_SP_MIN := 0 $(eval $(call add_define,RESET_TO_SP_MIN)) $(eval $(call assert_boolean,RESET_TO_SP_MIN)) + +# Flag to allow SP_MIN to handle FIQ interrupts in monitor mode. The platform +# port is free to override this value. It is default disabled. +SP_MIN_WITH_SECURE_FIQ ?= 0 +$(eval $(call add_define,SP_MIN_WITH_SECURE_FIQ)) +$(eval $(call assert_boolean,SP_MIN_WITH_SECURE_FIQ)) diff --git a/bl32/sp_min/sp_min_main.c b/bl32/sp_min/sp_min_main.c index 1c83cbe1..06b0f333 100644 --- a/bl32/sp_min/sp_min_main.c +++ b/bl32/sp_min/sp_min_main.c @@ -207,3 +207,19 @@ void sp_min_warm_boot(void) copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)), next_smc_ctx); } + +#if SP_MIN_WITH_SECURE_FIQ +/****************************************************************************** + * This function is invoked on secure interrupts. By construction of the + * SP_MIN, secure interrupts can only be handled when core executes in non + * secure state. + *****************************************************************************/ +void sp_min_fiq(void) +{ + uint32_t id; + + id = plat_ic_acknowledge_interrupt(); + sp_min_plat_fiq_handler(id); + plat_ic_end_of_interrupt(id); +} +#endif /* SP_MIN_WITH_SECURE_FIQ */ diff --git a/bl32/sp_min/sp_min_private.h b/bl32/sp_min/sp_min_private.h index 97185b91..1836af98 100644 --- a/bl32/sp_min/sp_min_private.h +++ b/bl32/sp_min/sp_min_private.h @@ -10,5 +10,6 @@ void sp_min_warm_entrypoint(void); void sp_min_main(void); void sp_min_warm_boot(void); +void sp_min_fiq(void); #endif /* __SP_MIN_H__ */ |