AArch32: Add API to invoke runtime service handler
authorSoby Mathew <[email protected]>
Thu, 5 May 2016 11:49:09 +0000 (12:49 +0100)
committerSoby Mathew <[email protected]>
Wed, 10 Aug 2016 11:35:46 +0000 (12:35 +0100)
This patch adds an API in runtime service framework to
invoke the registered handler corresponding to the SMC function
identifier. This is helpful for AArch32 because the number of
arguments required by the handler is more than registers
available as per AArch32 program calling conventions and
requires the use of stack. Hence this new API will do the
necessary argument setup and invoke the appropriate
handler. Although this API is primarily intended for AArch32,
it can be used for AArch64 as well.

Change-Id: Iefa15947fe5a1df55b0859886e677446a0fd7241

common/runtime_svc.c
include/common/runtime_svc.h
include/lib/aarch64/smcc_helpers.h

index b8af6cd846a6b7c33c86c6e54d019d81eb0892ef..df0d64ca7c58ede8b7dd7c6090281a90c35fe26c 100644 (file)
@@ -51,6 +51,34 @@ static rt_svc_desc_t *rt_svc_descs;
 #define RT_SVC_DECS_NUM                ((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\
                                        / sizeof(rt_svc_desc_t))
 
+/*******************************************************************************
+ * Function to invoke the registered `handle` corresponding to the smc_fid.
+ ******************************************************************************/
+uintptr_t handle_runtime_svc(uint32_t smc_fid,
+                            void *cookie,
+                            void *handle,
+                            unsigned int flags)
+{
+       u_register_t x1, x2, x3, x4;
+       int index, idx;
+       const rt_svc_desc_t *rt_svc_descs;
+
+       assert(handle);
+       idx = get_unique_oen_from_smc_fid(smc_fid);
+       assert(idx >= 0 && idx < MAX_RT_SVCS);
+
+       index = rt_svc_descs_indices[idx];
+       if (index < 0 || index >= RT_SVC_DECS_NUM)
+               SMC_RET1(handle, SMC_UNK);
+
+       rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
+
+       get_smc_params_from_ctx(handle, x1, x2, x3, x4);
+
+       return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie,
+                                               handle, flags);
+}
+
 /*******************************************************************************
  * Simple routine to sanity check a runtime service descriptor before using it
  ******************************************************************************/
index adafcee49d62280dde6325c6d8bb63cc7e11c716..514f334a252130737672ba52763725114aec34cf 100644 (file)
  * Constants to allow the assembler access a runtime service
  * descriptor
  */
+#ifdef AARCH32
+#define RT_SVC_SIZE_LOG2       4
+#define RT_SVC_DESC_INIT       8
+#define RT_SVC_DESC_HANDLE     12
+#else
 #define RT_SVC_SIZE_LOG2       5
-#define SIZEOF_RT_SVC_DESC     (1 << RT_SVC_SIZE_LOG2)
 #define RT_SVC_DESC_INIT       16
 #define RT_SVC_DESC_HANDLE     24
+#endif /* AARCH32 */
+#define SIZEOF_RT_SVC_DESC     (1 << RT_SVC_SIZE_LOG2)
+
 
 /*
  * The function identifier has 6 bits for the owning entity number and
@@ -123,10 +130,22 @@ CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \
                                        ((call_type & FUNCID_TYPE_MASK) \
                                         << FUNCID_OEN_WIDTH))
 
+/*
+ * This macro generates the unique owning entity number from the SMC Function
+ * ID.  This unique oen is used to access an entry in the
+ * 'rt_svc_descs_indices' array to invoke the corresponding runtime service
+ * handler during SMC handling.
+ */
+#define get_unique_oen_from_smc_fid(fid)               \
+       get_unique_oen(((fid) >> FUNCID_OEN_SHIFT),     \
+                       ((fid) >> FUNCID_TYPE_SHIFT))
+
 /*******************************************************************************
  * Function & variable prototypes
  ******************************************************************************/
 void runtime_svc_init(void);
+uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle,
+                                               unsigned int flags);
 extern uintptr_t __RT_SVC_DESCS_START__;
 extern uintptr_t __RT_SVC_DESCS_END__;
 void init_crash_reporting(void);
index 617a5bcecffff07bc3bae252500af26fcef97f91..6e6338392d3320bfaf7cdc32e5da92a6bfd30af3 100644 (file)
                         ((const uint32_t *) &(_uuid))[2],      \
                         ((const uint32_t *) &(_uuid))[3])
 
+/*
+ * Helper macro to retrieve the SMC parameters from cpu_context_t.
+ */
+#define get_smc_params_from_ctx(_hdl, _x1, _x2, _x3, _x4)      \
+       do {                                                    \
+               const gp_regs_t *regs = get_gpregs_ctx(_hdl);   \
+               _x1 = read_ctx_reg(regs, CTX_GPREG_X1);         \
+               _x2 = read_ctx_reg(regs, CTX_GPREG_X2);         \
+               _x3 = read_ctx_reg(regs, CTX_GPREG_X3);         \
+               _x4 = read_ctx_reg(regs, CTX_GPREG_X4);         \
+       } while (0)
+
 #endif /*__ASSEMBLY__*/
 #endif /* __SMCC_HELPERS_H__ */