aboutsummaryrefslogtreecommitdiffstats
path: root/bl31/aarch64/runtime_exceptions.S
diff options
context:
space:
mode:
Diffstat (limited to 'bl31/aarch64/runtime_exceptions.S')
-rw-r--r--bl31/aarch64/runtime_exceptions.S87
1 files changed, 67 insertions, 20 deletions
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 60be93274..1c3ed3f33 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -11,6 +11,7 @@
#include <interrupt_mgmt.h>
#include <platform_def.h>
#include <runtime_svc.h>
+#include <smccc.h>
.globl runtime_exceptions
@@ -289,6 +290,37 @@ vector_entry serror_aarch32
/* ---------------------------------------------------------------------
+ * This macro takes an argument in x16 that is the index in the
+ * 'rt_svc_descs_indices' array, checks that the value in the array is
+ * valid, and loads in x15 the pointer to the handler of that service.
+ * ---------------------------------------------------------------------
+ */
+ .macro load_rt_svc_desc_pointer
+ /* Load descriptor index from array of indices */
+ adr x14, rt_svc_descs_indices
+ ldrb w15, [x14, x16]
+
+#if SMCCC_MAJOR_VERSION == 1
+ /* Any index greater than 127 is invalid. Check bit 7. */
+ tbnz w15, 7, smc_unknown
+#elif SMCCC_MAJOR_VERSION == 2
+ /* Verify that the top 3 bits of the loaded index are 0 (w15 <= 31) */
+ cmp w15, #31
+ b.hi smc_unknown
+#endif /* SMCCC_MAJOR_VERSION */
+
+ /*
+ * Get the descriptor using the index
+ * x11 = (base + off), w15 = index
+ *
+ * handler = (base + off) + (index << log2(size))
+ */
+ adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+ lsl w10, w15, #RT_SVC_SIZE_LOG2
+ ldr x15, [x11, w10, uxtw]
+ .endm
+
+ /* ---------------------------------------------------------------------
* The following code handles secure monitor calls.
* Depending upon the execution state from where the SMC has been
* invoked, it frees some general purpose registers to perform the
@@ -311,48 +343,63 @@ smc_handler64:
* now). x6 will point to the context structure (SP_EL3) and x7 will
* contain flags we need to pass to the handler.
*
- * Save x4-x29 and sp_el0. Refer to SMCCC v1.1.
+ * Save x4-x29 and sp_el0.
*/
save_x4_to_x29_sp_el0
mov x5, xzr
mov x6, sp
+#if SMCCC_MAJOR_VERSION == 1
+
/* Get the unique owning entity number */
ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH
ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH
orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH
- adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+ load_rt_svc_desc_pointer
- /* Load descriptor index from array of indices */
- adr x14, rt_svc_descs_indices
- ldrb w15, [x14, x16]
+#elif SMCCC_MAJOR_VERSION == 2
+
+ /* Bit 31 must be set */
+ tbz x0, #FUNCID_TYPE_SHIFT, smc_unknown
/*
- * Restore the saved C runtime stack value which will become the new
- * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context'
- * structure prior to the last ERET from EL3.
+ * Check MSB of namespace to decide between compatibility/vendor and
+ * SPCI/SPRT
*/
- ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+ tbz x0, #(FUNCID_NAMESPACE_SHIFT + 1), compat_or_vendor
+
+ /* Namespaces SPRT and SPCI currently unimplemented */
+ b smc_unknown
+
+compat_or_vendor:
+
+ /* Namespace is b'00 (compatibility) or b'01 (vendor) */
/*
- * Any index greater than 127 is invalid. Check bit 7 for
- * a valid index
+ * Add the LSB of the namespace (bit [28]) to the OEN [27:24] to create
+ * a 5-bit index into the rt_svc_descs_indices array.
+ *
+ * The low 16 entries of the rt_svc_descs_indices array correspond to
+ * OENs of the compatibility namespace and the top 16 entries of the
+ * array are assigned to the vendor namespace descriptor.
*/
- tbnz w15, 7, smc_unknown
+ ubfx x16, x0, #FUNCID_OEN_SHIFT, #(FUNCID_OEN_WIDTH + 1)
- /* Switch to SP_EL0 */
- msr spsel, #0
+ load_rt_svc_desc_pointer
+
+#endif /* SMCCC_MAJOR_VERSION */
/*
- * Get the descriptor using the index
- * x11 = (base + off), x15 = index
- *
- * handler = (base + off) + (index << log2(size))
+ * Restore the saved C runtime stack value which will become the new
+ * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context'
+ * structure prior to the last ERET from EL3.
*/
- lsl w10, w15, #RT_SVC_SIZE_LOG2
- ldr x15, [x11, w10, uxtw]
+ ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+
+ /* Switch to SP_EL0 */
+ msr spsel, #0
/*
* Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world