From 3d732e23e71343f2ba18d456c8f2163015209768 Mon Sep 17 00:00:00 2001 From: Jeenu Viswambharan Date: Wed, 4 Oct 2017 12:21:34 +0100 Subject: BL31: Program Priority Mask for SMC handling On GICv3 systems, as a side effect of adding provision to handle EL3 interrupts (unconditionally routing FIQs to EL3), pending Non-secure interrupts (signalled as FIQs) may preempt execution in lower Secure ELs [1]. This will inadvertently disrupt the semantics of Fast SMC (previously called Atomic SMC) calls. To retain semantics of Fast SMCs, the GIC PMR must be programmed to prevent Non-secure interrupts from preempting Secure execution. To that effect, two new functions in the Exception Handling Framework subscribe to events introduced in an earlier commit: - Upon 'cm_exited_normal_world', the Non-secure PMR is stashed, and the PMR is programmed to the highest Non-secure interrupt priority. - Upon 'cm_entering_normal_world', the previously stashed Non-secure PMR is restored. The above sequence however prevents Yielding SMCs from being preempted by Non-secure interrupts as intended. To facilitate this, the public API exc_allow_ns_preemption() is introduced that programs the PMR to the original Non-secure PMR value. Another API exc_is_ns_preemption_allowed() is also introduced to check if exc_allow_ns_preemption() had been called previously. API documentation to follow. [1] On GICv2 systems, this isn't a problem as, unlike GICv3, pending NS IRQs during Secure execution are signalled as IRQs, which aren't routed to EL3. Change-Id: Ief96b162b0067179b1012332cd991ee1b3051dd0 Signed-off-by: Jeenu Viswambharan --- include/bl31/ehf.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/bl31') diff --git a/include/bl31/ehf.h b/include/bl31/ehf.h index 142b4c0aa..be8c957cc 100644 --- a/include/bl31/ehf.h +++ b/include/bl31/ehf.h @@ -55,6 +55,9 @@ typedef struct { /* Priority mask value before any priority levels were active */ uint8_t init_pri_mask; + + /* Non-secure priority mask value stashed during Secure execution */ + uint8_t ns_pri_mask; } __aligned(sizeof(uint64_t)) pe_exc_data_t; typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, @@ -79,6 +82,8 @@ void ehf_init(void); void ehf_activate_priority(unsigned int priority); void ehf_deactivate_priority(unsigned int priority); void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler); +void ehf_allow_ns_preemption(void); +unsigned int ehf_is_ns_preemption_allowed(void); #endif /* __ASSEMBLY__ */ -- cgit v1.2.3