From f89fe08c7227fc4fa4bc40ab8d0e1eacca6c20f0 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Tue, 6 Aug 2024 14:59:07 +0200 Subject: executor: arm64: add SYZOS_API_SMC Provide an API call to invoke the ARM64 Secure Monitor Call instruction with user-supplied function id and 5 parameters passed in registers x1-x5. For now only `smc #0` is invoked, although in the future we may want to pass other (reserved) immediate values to SMC. --- executor/common_kvm_arm64_syzos.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'executor/common_kvm_arm64_syzos.h') diff --git a/executor/common_kvm_arm64_syzos.h b/executor/common_kvm_arm64_syzos.h index 1541a2b58..104a07945 100644 --- a/executor/common_kvm_arm64_syzos.h +++ b/executor/common_kvm_arm64_syzos.h @@ -16,6 +16,7 @@ typedef enum { SYZOS_API_UEXIT, SYZOS_API_CODE, SYZOS_API_MSR, + SYZOS_API_SMC, SYZOS_API_STOP, // Must be the last one } syzos_api_id; @@ -39,9 +40,16 @@ struct api_call_code { uint32 insns[]; }; +struct api_call_smc { + struct api_call_header header; + uint32 smc_id; + uint64 params[5]; +}; + static void guest_uexit(uint64 exit_code); static void guest_execute_code(uint32* insns, uint64 size); static void guest_handle_msr(uint64 reg, uint64 val); +static void guest_handle_smc(struct api_call_smc* cmd); // Main guest function that performs necessary setup and passes the control to the user-provided // payload. @@ -71,6 +79,10 @@ GUEST_CODE static void guest_main(uint64 size) guest_handle_msr(ccmd->args[0], ccmd->args[1]); break; } + case SYZOS_API_SMC: { + guest_handle_smc((struct api_call_smc*)cmd); + break; + } } addr += cmd->size; size -= cmd->size; @@ -121,3 +133,27 @@ guest_handle_msr(uint64 reg, uint64 val) : [val] "r"(val), [pc] "r"(insn) : "x0", "x30", "memory"); } + +// See "SMC Calling Convention", https://documentation-service.arm.com/static/5f8ea482f86e16515cdbe3c6 +GUEST_CODE static void guest_handle_smc(struct api_call_smc* cmd) +{ + asm volatile( + "mov x0, %[smc_id]\n" + "mov x1, %[arg1]\n" + "mov x2, %[arg2]\n" + "mov x3, %[arg3]\n" + "mov x4, %[arg4]\n" + "mov x5, %[arg5]\n" + // TODO(glider): it could be interesting to pass other immediate values here, although + // they are ignored as per the calling convention. + "smc #0\n" + : // Ignore the outputs for now + : [smc_id] "r"((uint32)cmd->smc_id), + [arg1] "r"(cmd->params[0]), [arg2] "r"(cmd->params[1]), + [arg3] "r"(cmd->params[2]), [arg4] "r"(cmd->params[3]), + [arg5] "r"(cmd->params[4]) + : "x0", "x1", "x2", "x3", "x4", "x5", + // These registers are not used above, but may be clobbered by the SMC call. + "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", + "memory"); +} -- cgit mrf-deployment