27
27
#include "halt.h"
28
28
#include "vmpu.h"
29
29
30
+ /* Wrap a function call into an atomic section with IRQ state restoration. */
31
+ #define atomic_call_wrapper (fn ) { \
32
+ uint32_t primask = __get_PRIMASK(); \
33
+ __disable_irq(); \
34
+ fn; \
35
+ if (!(primask & 0x01)) { \
36
+ __enable_irq(); \
37
+ } \
38
+ }
39
+
30
40
/* By default a maximum of 16 threads are allowed. This can only be overridden
31
41
* by the porting engineer for the current platform. */
32
42
#ifndef UVISOR_EXPORT_TABLE_THREADS_MAX_COUNT
@@ -584,6 +594,18 @@ static void thread_switch(void * c)
584
594
}
585
595
}
586
596
597
+ /* uVisor expects all calls to its API to be executed in the highest priority
598
+ * interrupt (SVC) since they are not re-entrant.
599
+ * If this is not the case, we need to make sure that no other interrupt can
600
+ * preempt these calls by wrapping them in an atomic section.
601
+ */
602
+ static void thread_switch_atomic (void * c )
603
+ {
604
+ atomic_call_wrapper (
605
+ thread_switch (c )
606
+ );
607
+ }
608
+
587
609
static void boxes_init (void )
588
610
{
589
611
/* Tell uVisor to call the uVisor lib box_init function for each box with
@@ -606,7 +628,7 @@ const TUvisorExportTable __uvisor_export_table = {
606
628
.pre_start = boxes_init ,
607
629
.thread_create = thread_create ,
608
630
.thread_destroy = thread_destroy ,
609
- .thread_switch = thread_switch ,
631
+ .thread_switch = thread_switch_atomic ,
610
632
},
611
633
.pool = {
612
634
.init = uvisor_pool_init ,
0 commit comments