lib: sm: Add TRUSTY_FFA_MSG_IS_IDLE direct message

Add a new FF-A direct message to check whether Trusty
is idle on the current CPU. This is used by the bootloader
to determine whether it should call into Trusty again
with FFA_RUN or not.

Bug: 28405701
Change-Id: If6f3f11716dfe6397c356b60833a0c05381c0220
diff --git a/lib/sm/include/lib/sm/smcall.h b/lib/sm/include/lib/sm/smcall.h
index 8486a11..68aa45d 100644
--- a/lib/sm/include/lib/sm/smcall.h
+++ b/lib/sm/include/lib/sm/smcall.h
@@ -224,4 +224,21 @@
  */
 #define TRUSTY_FFA_MSG_RUN_NOPCALL (3)
 
+/**
+ * TRUSTY_FFA_MSG_IS_IDLE - Check if Trusty is idle on the current CPU.
+ *
+ * Return:
+ * * 1 in @r3 if the current CPU is idle
+ * * 0 if Trusty is busy (e.g. was interrupted)
+ * * One of the libsm error codes in case of error
+ *
+ * The non-secure scheduler needs to know if Trusty is idle to determine
+ * whether to give it more CPU cycles when it gets preempted. On Linux,
+ * we use the shadow priority but that requires sharing the sched-share state
+ * between NS and Trusty. %TRUSTY_FFA_MSG_IS_IDLE is a backup direct message
+ * that returns the same information to environments where this structure
+ * is not already shared, e.g., in bootloaders.
+ */
+#define TRUSTY_FFA_MSG_IS_IDLE (4)
+
 #endif /* __LIB_SM_SMCALL_H */
diff --git a/lib/sm/sm.c b/lib/sm/sm.c
index f19f7af..9f46454 100644
--- a/lib/sm/sm.c
+++ b/lib/sm/sm.c
@@ -244,6 +244,7 @@
 static long sm_ffa_handle_direct_req(long ret, struct smc_ret8* regs) {
     struct smc32_args args;
     uint16_t client_id = (regs->r1 >> 16) & 0xFFFFU;
+    uint cpu = arch_curr_cpu_num();
 
     switch (regs->r3) {
     case TRUSTY_FFA_MSG_RUN_FASTCALL:
@@ -306,6 +307,9 @@
         }
         return ret;
 
+    case TRUSTY_FFA_MSG_IS_IDLE:
+        return get_current_thread() == nsidlethreads[cpu];
+
     default:
         dprintf(CRITICAL,
                 "Unsupported FF-A message from client %" PRIu16 ": %lx\n",