4040 * For the 'lock kernel scheduler' approach to work thoroughly, we must also
4141 * address some side issues:
4242 *
43- * - Prohibit NS secure call from ISR except SVC, so non-preemptive doesn't break.
44- * - Allow NS secure call in SVC context because it is synchronous. Here, we lock
45- * interrupt instead of kernel scheduler because svcRtxKernelLock()/svcRtxKernelRestoreLock(...)
46- * are inaccessible outside rtx_kernel.c. Currently, this is rare case and would cause
47- * little trouble (see known paths below).
48- * - Call into secure world straight in interrupt-disabled context. When in
49- * interrupt-disabled context, NS secure call is guaranteed to be non-preemptive
50- * naturally.
51- * - Call into secure world straight at pre-rtos stage. When at pre-rtos stage,
43+ * - NOT SUPPORT NS secure call from ISR except SVC (rtos/baremetal)
44+ * - Support NS secure call in SVC context conditionally (rtos/baremetal)
45+ * - For rtos profile, lock interrupt instead of kernel scheduler because
46+ * svcRtxKernelLock()/svcRtxKernelRestoreLock(...) are inaccessible
47+ * outside rtx_kernel.c. Currently, this is rare case and would cause
48+ * little trouble (see known paths below).
49+ * - For baremetal profile, NS secure call is guaranteed to be non-preemptive
50+ * naturally.
51+ * NOTE: However, per test, TF-M doesn't allow call in SVC context anymore.
52+ * It will trap this as error and possibly reboot the system, except for
53+ * secure context calls like TZ_InitContextSystem_S and firends.
54+ * - Call into secure world straight in interrupt-disabled context (rtos/baremetal)
5255 * NS secure call is guaranteed to be non-preemptive naturally.
53- * - osKernelLock() will error when kernel state is 'osKernelSuspended'. Address
54- * it separately. Known path of NS secure call when kernel state is 'osKernelSuspended':
55- * - default idle thread > osKernelSuspend() > lp_ticker_init > SYS_ResetModule_S/
56- * CLK_SetModuleClock_S/CLK_EnableModuleClock_S
56+ * - Call into secure world straight at pre-rtos stage (rtos)
57+ * NS secure call is guaranteed to be non-preemptive naturally.
58+ * - osKernelLock() will error when kernel state is 'osKernelSuspended' (rtos).
59+ * Address it separately. Known path of NS secure call when kernel state is
60+ * 'osKernelSuspended':
61+ * default idle thread > osKernelSuspend() > lp_ticker_init > SYS_ResetModule_S/
62+ * CLK_SetModuleClock_S/CLK_EnableModuleClock_S
5763 *
5864 * Known paths of NS secure call in interrupt-disabled context:
5965 * - mbed-os/platform/mbed_sleep_manager.c > sleep_manager_sleep_auto >
6571 * CLK_IsRTCClockEnabled_S
6672 *
6773 * Known paths of NS secure call in SVC context:
68- * - In tickless mode, osKernelStart > svcRtxKernelStart > OS_Tick_Enable >
74+ * - In MBED_TICKLESS mode, osKernelStart > svcRtxKernelStart > OS_Tick_Enable >
6975 * us_ticker_init/lp_ticker_init > SYS_ResetModule_S/CLK_SetModuleClock_S/
7076 * CLK_EnableModuleClock_S
77+ * NOTE: Per above SVC test, this means MBED_TICKLESS mode is not supported.
7178 */
7279
7380struct ns_interface_state
@@ -87,34 +94,51 @@ int32_t tfm_ns_interface_dispatch(veneer_fn fn,
8794 /* Prohibit NS secure call from ISR except SVC, so non-preemptive doesn't break */
8895 uint32_t ipsr = __get_IPSR ();
8996 if (ipsr == 11U ) {
90- /* Allow NS secure call in SVC context because it is synchronous. Here,
91- * we lock interrupt instead of kernel scheduler because svcRtxKernelLock()/
92- * svcRtxKernelRestoreLock(...) are inaccessible outside rtx_kernel.c. */
97+ /* Support NS secure call in SVC context */
98+ #if MBED_CONF_RTOS_PRESENT
99+ /*
100+ * Lock interrupt instead of kernel scheduler because svcRtxKernelLock()/
101+ * svcRtxKernelRestoreLock(...) are inaccessible outside rtx_kernel.c
102+ */
93103 core_util_critical_section_enter ();
94104 int32_t result = fn (arg0 , arg1 , arg2 , arg3 );
95105 core_util_critical_section_exit ();
96106
97107 return result ;
108+ #else
109+ /*
110+ * Call into secure world straight for baremetal because NS secure
111+ * call is non-preemptive naturally
112+ */
113+ return fn (arg0 , arg1 , arg2 , arg3 );
114+ #endif
98115 } else if (ipsr ) {
99116 MBED_ERROR1 (MBED_MAKE_ERROR (MBED_MODULE_KERNEL , MBED_ERROR_CODE_PROHIBITED_IN_ISR_CONTEXT ), "Prohibited in ISR context" , (uintptr_t ) fn );
100117 }
101118
102- /* Call into secure world straight in interrupt-disabled context because
103- * NS secure call is non-preemptive naturally */
119+ /*
120+ * Call into secure world straight in interrupt-disabled context because
121+ * NS secure call is non-preemptive naturally
122+ */
104123 if (!core_util_are_interrupts_enabled ()) {
105124 return fn (arg0 , arg1 , arg2 , arg3 );
106125 }
107126
127+ #if MBED_CONF_RTOS_PRESENT
108128 osKernelState_t kernel_state = osKernelGetState ();
109129
110- /* Call into secure world straight at pre-rtos stage because NS secure
111- * call is non-preemptive naturally */
130+ /*
131+ * Call into secure world straight at pre-rtos stage because NS secure
132+ * call is non-preemptive naturally
133+ */
112134 if (kernel_state == osKernelInactive || kernel_state == osKernelReady ) {
113135 return fn (arg0 , arg1 , arg2 , arg3 );
114136 }
115137
116- /* osKernelLock() will error when kernel state is 'osKernelSuspended'. Address
117- * it separately. */
138+ /*
139+ * osKernelLock() will error when kernel state is 'osKernelSuspended'. Address
140+ * it separately.
141+ */
118142 if (kernel_state == osKernelSuspended ) {
119143 return fn (arg0 , arg1 , arg2 , arg3 );
120144 } else if (kernel_state == osKernelError ) {
@@ -139,6 +163,13 @@ int32_t tfm_ns_interface_dispatch(veneer_fn fn,
139163 MBED_ASSERT (lock_state >= 0 );
140164
141165 return result ;
166+ #else
167+ /*
168+ * Call into secure world straight for baremetal because NS secure
169+ * call is non-preemptive naturally
170+ */
171+ return fn (arg0 , arg1 , arg2 , arg3 );
172+ #endif
142173}
143174
144175/* Override tfm_ns_lock_init()
0 commit comments