aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Bellows <greg.bellows@linaro.org>2015-03-12 16:22:41 -0500
committerGreg Bellows <greg.bellows@linaro.org>2015-03-12 16:22:41 -0500
commitbf0b51570e2bf123f0744430fa6fe9c98898b349 (patch)
treec5ad064f25c13f3441cc2ae9fdf9da82da948b28
parentc2dbdaae689c49e88251348376a83e596cd436aa (diff)
Fix-up SMC to better follow the ARM CC
Changed the SMC interface to better follow ARM's SMC calling convention. Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
-rw-r--r--aarch64/common/arm_builtins.h30
-rw-r--r--aarch64/common/armv8_exception.h30
-rw-r--r--aarch64/common/smc.h17
-rw-r--r--aarch64/common/svc.h2
-rw-r--r--aarch64/el0_ns/tztest.c1
-rw-r--r--aarch64/el1_common/el1.c5
-rw-r--r--aarch64/el1_s/el1_sec.c12
-rw-r--r--aarch64/el3/el3.c59
-rw-r--r--aarch64/el3/el3_exception.S19
9 files changed, 79 insertions, 96 deletions
diff --git a/aarch64/common/arm_builtins.h b/aarch64/common/arm_builtins.h
index 1ca14f9..4e4417e 100644
--- a/aarch64/common/arm_builtins.h
+++ b/aarch64/common/arm_builtins.h
@@ -1,36 +1,6 @@
#ifndef _ARM_BUILTINS_H
#define _ARM_BUILTINS_H
-extern void __smc(void *);
-extern void __svc(void *);
-/*
-#define __smc(_op) \
- asm volatile ( \
- "mov x0, %0\n" \
- "smc 0\n" \
- "mov %0, x0\n" \
- : "+r" (_op) \
- )
-
-#define __smc(_imm, _desc) \
- asm volatile ("mov x0, %1\n" \
- "smc #%0\n" \
- ::[imm] "+I" (_imm), "r" (_desc))
-*/
-
- /*
-#define __svc(_op) \
- asm volatile ( \
- "mov x0, %0\n" \
- "svc 0\n" \
- "mov %0, x0\n" \
- : "+r" (_op) \
- )
-#define __svc(_imm, _desc) \
- asm volatile ("mov x0, %1\n" \
- "svc #%0\n" \
- ::[imm] "I" (_imm), "r" (_desc))
- */
#define __exception_return(_x0) asm volatile ("eret\n")
#define __set_exception_return(_elr) \
asm volatile("msr elr_el1, %[elr]\n"::[elr] "r" (_elr))
diff --git a/aarch64/common/armv8_exception.h b/aarch64/common/armv8_exception.h
index da2b75f..85b2604 100644
--- a/aarch64/common/armv8_exception.h
+++ b/aarch64/common/armv8_exception.h
@@ -1,6 +1,19 @@
#ifndef _EXCEPTION_H
#define _EXCEPTION_H
+#define EC_UNKNOWN 0x00
+#define EC_SIMD 0x07
+#define EC_ILLEGAL_STATE 0x0E
+#define EC_SVC32 0x11
+#define EC_SMC32 0x13
+#define EC_SVC64 0x15
+#define EC_SMC64 0x17
+#define EC_IABORT_LOWER 0x20
+#define EC_IABORT 0x21
+#define EC_DABORT_LOWER 0x24
+#define EC_DABORT 0x25
+
+#ifndef __ASSEMBLY__
typedef union {
struct {
uint32_t dfsc : 6;
@@ -32,21 +45,6 @@ typedef union {
};
uint32_t raw;
} armv8_inst_abort_iss_t;
-
-typedef enum {
- EC_UNKNOWN = 0x00,
- EC_SIMD = 0x07,
- EC_ILLEGAL_STATE = 0x0E,
- EC_SVC32 = 0x11,
- EC_SMC32 = 0x13,
- EC_SVC64 = 0x15,
- EC_SMC64 = 0x17,
- EC_IABORT_LOWER = 0x20,
- EC_IABORT = 0x21,
- EC_DABORT_LOWER = 0x24,
- EC_DABORT = 0x25,
-} armv8_exception_code_t;
-
-
+#endif
#endif
diff --git a/aarch64/common/smc.h b/aarch64/common/smc.h
index c0f9bda..baadb73 100644
--- a/aarch64/common/smc.h
+++ b/aarch64/common/smc.h
@@ -13,21 +13,16 @@
#ifndef __ASSEMBLY__
#include "interop.h"
-typedef struct {
- int op;
- union {
- op_dispatch_t dispatch;
- op_map_mem_t map;
- };
+extern uint32_t __smc(uint32_t, void *);
+
+typedef union {
+ op_dispatch_t dispatch;
+ op_map_mem_t map;
} smc_op_desc_t;
extern smc_op_desc_t *smc_interop_buf;
-#define SMC_NO_DESC(_op) \
- do { \
- smc_interop_buf->op = (_op); \
- __smc(smc_interop_buf); \
- } while(0)
+#define SMC_NO_DESC(_op) __smc((_op), NULL)
#define SMC_EXIT() SMC_NO_DESC(SMC_OP_EXIT)
#define SMC_YIELD() SMC_NO_DESC(SMC_OP_YIELD)
diff --git a/aarch64/common/svc.h b/aarch64/common/svc.h
index 8f31ee6..255af5a 100644
--- a/aarch64/common/svc.h
+++ b/aarch64/common/svc.h
@@ -15,6 +15,8 @@
#define SVC_YIELD 9
#ifndef __ASSEMBLY__
+extern void __svc(void *);
+
typedef struct {
int op;
union {
diff --git a/aarch64/el0_ns/tztest.c b/aarch64/el0_ns/tztest.c
index 1287c17..59efb35 100644
--- a/aarch64/el0_ns/tztest.c
+++ b/aarch64/el0_ns/tztest.c
@@ -1,5 +1,4 @@
#include "libcflat.h"
-#include "arm_builtins.h"
#include "svc.h"
typedef struct {
diff --git a/aarch64/el1_common/el1.c b/aarch64/el1_common/el1.c
index 1a240d4..3a1f11a 100644
--- a/aarch64/el1_common/el1.c
+++ b/aarch64/el1_common/el1.c
@@ -156,12 +156,11 @@ void el1_map_secure(op_map_mem_t *map)
{
smc_op_desc_t *desc = (smc_op_desc_t *)smc_interop_buf;
- memcpy(&desc->map, map, sizeof(op_map_mem_t));
+ memcpy(desc, map, sizeof(op_map_mem_t));
- desc->op = SMC_OP_MAP;
desc->map.pa = el1_lookup_pa(desc->map.va);
- __smc(desc);
+ __smc(SMC_OP_MAP, desc);
}
void el1_handle_exception(uint64_t ec, uint64_t iss, svc_op_desc_t *desc)
diff --git a/aarch64/el1_s/el1_sec.c b/aarch64/el1_s/el1_sec.c
index 43b828d..09cc9f9 100644
--- a/aarch64/el1_s/el1_sec.c
+++ b/aarch64/el1_s/el1_sec.c
@@ -8,10 +8,12 @@ extern void el1_map_pa(uintptr_t vaddr, uintptr_t paddr);
void el1_sec_smc_loop()
{
smc_op_desc_t *desc = smc_interop_buf;
+ uint32_t op = SMC_OP_YIELD;
+
printf("EL1_S: In loop\n");
- while (desc->op != SMC_OP_EXIT) {
- switch (desc->op) {
+ while (op != SMC_OP_EXIT) {
+ switch (op) {
case SMC_OP_MAP:
printf("EL1_S: Doing a MAP desc = %p\n", desc);
el1_map_pa((uintptr_t)(desc->map.va), (uintptr_t)(desc->map.pa));
@@ -20,12 +22,12 @@ void el1_sec_smc_loop()
printf("EL1_S: Doing a YIELD desc = %p\n", desc);
break;
default:
- printf("Unrecognized SMC opcode %d. Exiting ...\n", desc->op);
+ printf("Unrecognized SMC opcode %d. Exiting ...\n", op);
SMC_EXIT();
break;
}
- SMC_YIELD();
+ op = __smc(op, desc);
}
SMC_EXIT();
@@ -33,7 +35,5 @@ void el1_sec_smc_loop()
void el1_init_el0()
{
- SMC_YIELD();
-
el1_sec_smc_loop();
}
diff --git a/aarch64/el3/el3.c b/aarch64/el3/el3.c
index 5a3d1cb..4ee1b4e 100644
--- a/aarch64/el3/el3.c
+++ b/aarch64/el3/el3.c
@@ -183,7 +183,39 @@ void el3_map_mem(op_map_mem_t *map)
*/
}
-int el3_handle_exception(uint64_t ec, uint64_t iss, smc_op_desc_t *desc)
+int el3_handle_smc(uint64_t ec, uint64_t op, smc_op_desc_t *desc)
+{
+ assert(ec == EC_SMC64);
+
+ switch (op) {
+ case SMC_OP_YIELD:
+ DEBUG_MSG("took an SMC(SMC_YIELD) exception\n");
+ return 1;
+ break;
+ case SMC_OP_DISPATCH_MONITOR:
+ DEBUG_MSG("took an smc(SMC_OP_DSPATCH_MONITOR) exception\n");
+ el3_dispatch((op_dispatch_t *)&desc->dispatch);
+ break;
+ case SMC_OP_MAP:
+ DEBUG_MSG("took an smc(SMC_OP_MAP) exception\n");
+ el3_map_mem((op_map_mem_t *)&desc->map);
+ return 1;
+ break;
+ case SMC_OP_NOOP:
+ DEBUG_MSG("took an smc(SMC_OP_NOOP) exception\n");
+ break;
+ case SMC_OP_EXIT:
+ el3_shutdown();
+ break;
+ default:
+ printf("Unrecognized AArch64 SMC opcode: iss = %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+int el3_handle_exception(uint64_t ec, uint64_t iss)
{
armv8_data_abort_iss_t dai = {.raw = iss};
uint64_t elr, far;
@@ -193,31 +225,6 @@ int el3_handle_exception(uint64_t ec, uint64_t iss, smc_op_desc_t *desc)
switch (ec) {
case EC_SMC64: /* SMC from aarch64 */
- switch (desc->op) {
- case SMC_OP_YIELD:
- DEBUG_MSG("took an SMC(SMC_YIELD) exception\n");
- return 1;
- break;
- case SMC_OP_DISPATCH_MONITOR:
- DEBUG_MSG("took an smc(SMC_OP_DSPATCH_MONITOR) exception\n");
- el3_dispatch((op_dispatch_t *)&desc->dispatch);
- break;
- case SMC_OP_MAP:
- DEBUG_MSG("took an smc(SMC_OP_MAP) exception\n");
- el3_map_mem((op_map_mem_t *)&desc->map);
- return 1;
- break;
- case SMC_OP_NOOP:
- DEBUG_MSG("took an smc(SMC_OP_NOOP) exception\n");
- break;
- case SMC_OP_EXIT:
- el3_shutdown();
- break;
- default:
- printf("Unrecognized AArch64 SMC opcode: iss = %d\n", iss);
- break;
- }
- break;
case EC_IABORT_LOWER:
printf("Instruction abort at lower level: far = %0lx\n", far);
break;
diff --git a/aarch64/el3/el3_exception.S b/aarch64/el3/el3_exception.S
index 03397b7..cbed1a7 100644
--- a/aarch64/el3/el3_exception.S
+++ b/aarch64/el3/el3_exception.S
@@ -1,3 +1,7 @@
+#define __ASSEMBLY__
+#include "armv8_exception.h"
+#undef __ASSEMBLY__
+
.section .vectors
.align 12 // Align to vector table size (0x800)
.globl el3_vectors
@@ -25,12 +29,21 @@ el3_sync_exception_lower64:
mov x1, #0xffffff
and x1, x1, x0
lsr x0, x0, #26
+ cmp x0, #EC_SMC64
+ b.eq el3_sync_exception_lower64_smc
+ cmp x0, #EC_SMC32
+ b.eq el3_sync_exception_lower64_smc
bl el3_handle_exception
- mov x3, x0
ldp x0, x1, [sp], #16
ldp x30, x2, [sp], #16
- cbz x3, el3_sync_exception_lower64_done
- b monitor_switch
+ b el3_sync_exception_lower64_done
+el3_sync_exception_lower64_smc:
+ ldp x1, x2, [sp] /* Fetch our inputs as SMC args */
+ bl el3_handle_smc
+ cbz x0, el3_sync_exception_lower64_done
+ ldp x0, x1, [sp], #16
+ ldp x30, x2, [sp], #16
+ b monitor_switch /* This never returns, erets */
el3_sync_exception_lower64_done:
eret
.align 7