diff options
author | Greg Bellows <greg.bellows@linaro.org> | 2015-03-12 16:22:41 -0500 |
---|---|---|
committer | Greg Bellows <greg.bellows@linaro.org> | 2015-03-12 16:22:41 -0500 |
commit | bf0b51570e2bf123f0744430fa6fe9c98898b349 (patch) | |
tree | c5ad064f25c13f3441cc2ae9fdf9da82da948b28 | |
parent | c2dbdaae689c49e88251348376a83e596cd436aa (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.h | 30 | ||||
-rw-r--r-- | aarch64/common/armv8_exception.h | 30 | ||||
-rw-r--r-- | aarch64/common/smc.h | 17 | ||||
-rw-r--r-- | aarch64/common/svc.h | 2 | ||||
-rw-r--r-- | aarch64/el0_ns/tztest.c | 1 | ||||
-rw-r--r-- | aarch64/el1_common/el1.c | 5 | ||||
-rw-r--r-- | aarch64/el1_s/el1_sec.c | 12 | ||||
-rw-r--r-- | aarch64/el3/el3.c | 59 | ||||
-rw-r--r-- | aarch64/el3/el3_exception.S | 19 |
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 |