SPM: Add critical section for IPC "wait" in backend
Add critical section for IPC "wait" ops in the backend,
since the thread state and asserted signal value of partition
may be changed by interrupt.
Also rename the arg name 'signals' to 'signal_mask' since it is
a set of signals to wait for.
Signed-off-by: Mingyang Sun <mingyang.sun@arm.com>
Change-Id: Ia12607fad1238d8ea443461fd220d949166f4638
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index fb9e4b3..8a0037e 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -202,11 +202,28 @@
return control;
}
-static void ipc_wait(struct partition_t *p_pt, psa_signal_t signals)
+static psa_signal_t ipc_wait(struct partition_t *p_pt, psa_signal_t signal_mask)
{
- (void)signals;
+ struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
+ psa_signal_t ret_signal;
- thrd_wait_on(&p_pt->waitobj, CURRENT_THREAD);
+ /*
+ * 'ipc_wait()' sets the waiting signal mask for partition, and
+ * blocks the partition thread state to wait for signals.
+ * These changes should be inside the ciritical section to avoid
+ * 'signal_waiting' or the thread state to be changed by interrupts
+ * while this function is reading or writing values.
+ */
+ CRITICAL_SECTION_ENTER(cs_assert);
+
+ ret_signal = p_pt->signals_asserted & signal_mask;
+ if (ret_signal == 0) {
+ p_pt->signals_waiting = signal_mask;
+ thrd_wait_on(&p_pt->waitobj, CURRENT_THREAD);
+ }
+ CRITICAL_SECTION_LEAVE(cs_assert);
+
+ return ret_signal;
}
static void ipc_wake_up(struct partition_t *p_pt, psa_signal_t signals)
diff --git a/secure_fw/spm/ffm/backend_sfn.c b/secure_fw/spm/ffm/backend_sfn.c
index 4c4ebbf..e102a8a 100644
--- a/secure_fw/spm/ffm/backend_sfn.c
+++ b/secure_fw/spm/ffm/backend_sfn.c
@@ -140,12 +140,12 @@
return thrd_start_scheduler(&CURRENT_THREAD);
}
-static void sfn_wait(struct partition_t *p_pt, psa_signal_t signals)
+static psa_signal_t sfn_wait(struct partition_t *p_pt, psa_signal_t signal_mask)
{
- while (!(p_pt->signals_waiting & p_pt->signals_asserted))
+ while (!(p_pt->signals_asserted & signal_mask))
;
- p_pt->signals_waiting &= ~signals;
+ return p_pt->signals_asserted & signal_mask;
}
static void sfn_wake_up(struct partition_t *p_pt, psa_signal_t signals)
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index d787dd2..40f2afe 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -463,15 +463,14 @@
}
/*
- * thrd_wait_on() blocks the caller thread if no signals are available.
- * In this case, the return value of this function is temporary set into
- * runtime context. After new signal(s) are available, the return value
- * is updated with the available signal(s) and blocked thread gets to run.
+ * backend_instance.wait() blocks the caller thread if no signals are
+ * available. In this case, the return value of this function is temporary
+ * set into runtime context. After new signal(s) are available, the return
+ * value is updated with the available signal(s) and blocked thread gets
+ * to run.
*/
- if (timeout == PSA_BLOCK &&
- (partition->signals_asserted & signal_mask) == 0) {
- partition->signals_waiting = signal_mask;
- backend_instance.wait(partition, signal_mask);
+ if (timeout == PSA_BLOCK) {
+ return backend_instance.wait(partition, signal_mask);
}
return partition->signals_asserted & signal_mask;
diff --git a/secure_fw/spm/include/ffm/backend.h b/secure_fw/spm/include/ffm/backend.h
index d430da5..61df7b7 100644
--- a/secure_fw/spm/include/ffm/backend.h
+++ b/secure_fw/spm/include/ffm/backend.h
@@ -45,7 +45,7 @@
* Runtime model-specific Partition wait operation.
* Put the Partition to a status that waits for signals.
*/
- void (*wait)(struct partition_t *p_pt, psa_signal_t signals);
+ psa_signal_t (*wait)(struct partition_t *p_pt, psa_signal_t signal_mask);
/*
* Runtime model-specific Partition wake up operation.