blob: c65816f5c9b7b6a1fb21ae1071627b136530b725 [file] [log] [blame]
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CACTUS_TEST_CMDS
#define CACTUS_TEST_CMDS
#include <debug.h>
#include <ffa_helpers.h>
#include <spm_common.h>
/**
* Success and error return to be sent over a msg response.
*/
#define CACTUS_SUCCESS U(0)
#define CACTUS_ERROR U(-1)
/**
* Error codes.
*/
#define CACTUS_ERROR_INVALID U(1)
#define CACTUS_ERROR_TEST U(2)
#define CACTUS_ERROR_FFA_CALL U(3)
#define CACTUS_ERROR_UNHANDLED U(4)
/**
* Get command from struct smc_ret_values.
*/
static inline uint64_t cactus_get_cmd(smc_ret_values ret)
{
return (uint64_t)ret.ret3;
}
/**
* Template for commands to be sent to CACTUS partitions over direct
* messages interfaces.
*/
static inline smc_ret_values cactus_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t cmd, uint64_t val0,
uint64_t val1, uint64_t val2, uint64_t val3)
{
return ffa_msg_send_direct_req64(source, dest, cmd, val0, val1, val2,
val3);
}
/**
* Template for responses to Cactus commands.
* 'cactus_send_response' is the template for custom responses, in case there is
* a need to propagate more than one value in the response of a command.
*/
static inline smc_ret_values cactus_send_response(
ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t resp, uint32_t val0,
uint64_t val1, uint64_t val2, uint64_t val3)
{
return ffa_msg_send_direct_resp64(source, dest, resp, val0, val1,
val2, val3);
}
/**
* For responses of one value only.
*/
static inline smc_ret_values cactus_response(
ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t response)
{
return ffa_msg_send_direct_resp64(source, dest, response, 0, 0, 0, 0);
}
static inline uint32_t cactus_get_response(smc_ret_values ret)
{
return (uint32_t)ret.ret3;
}
/**
* In a successful test, in case the SP needs to propagate an extra value
* to conclude the test.
* If more arguments are needed, a custom response should be defined for the
* specific test.
*/
static inline smc_ret_values cactus_success_resp(
ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t value)
{
return cactus_send_response(source, dest, CACTUS_SUCCESS, value,
0, 0, 0);
}
/**
* In case the test fails on the SP side, the 'error_code' should help specify
* the reason, which can be specific to the test, or general ones as defined
* in the error code list.
*/
static inline smc_ret_values cactus_error_resp(
ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t error_code)
{
return cactus_send_response(source, dest, CACTUS_ERROR, error_code,
0, 0, 0);
}
static inline uint32_t cactus_error_code(smc_ret_values ret)
{
return (uint32_t) ret.ret4;
}
#define PRINT_CMD(smc_ret) \
VERBOSE("cmd %lx; args: %lx, %lx, %lx, %lx\n", \
smc_ret.ret3, smc_ret.ret4, smc_ret.ret5, \
smc_ret.ret6, smc_ret.ret7)
/**
* With this test command the sender transmits a 64-bit value that it then
* expects to receive on the respective command response.
*
* The id is the hex representation of the string 'echo'.
*/
#define CACTUS_ECHO_CMD U(0x6563686f)
static inline smc_ret_values cactus_echo_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t echo_val)
{
return cactus_send_cmd(source, dest, CACTUS_ECHO_CMD, echo_val, 0, 0,
0);
}
static inline uint64_t cactus_echo_get_val(smc_ret_values ret)
{
return (uint64_t)ret.ret4;
}
/**
* Command to request a cactus secure partition to send an echo command to
* another partition.
*
* The sender of this command expects to receive CACTUS_SUCCESS if the requested
* echo interaction happened successfully, or CACTUS_ERROR otherwise.
*/
#define CACTUS_REQ_ECHO_CMD (CACTUS_ECHO_CMD + 1)
static inline smc_ret_values cactus_req_echo_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t echo_dest,
uint64_t echo_val)
{
return cactus_send_cmd(source, dest, CACTUS_REQ_ECHO_CMD, echo_val,
echo_dest, 0, 0);
}
static inline ffa_vm_id_t cactus_req_echo_get_echo_dest(smc_ret_values ret)
{
return (ffa_vm_id_t)ret.ret5;
}
/**
* Command to create a cyclic dependency between SPs, which could result in
* a deadlock. This aims at proving such scenario cannot happen.
* If the deadlock happens, the system will just hang.
* If the deadlock is prevented, the last partition to use the command will
* send response CACTUS_SUCCESS.
*
* The id is the hex representation of the string 'dead'.
*/
#define CACTUS_DEADLOCK_CMD U(0x64656164)
static inline smc_ret_values cactus_deadlock_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest)
{
return cactus_send_cmd(source, dest, CACTUS_DEADLOCK_CMD, next_dest, 0,
0, 0);
}
static inline ffa_vm_id_t cactus_deadlock_get_next_dest(smc_ret_values ret)
{
return (ffa_vm_id_t)ret.ret4;
}
/**
* Command to request a sequence CACTUS_DEADLOCK_CMD between the partitions
* of specified IDs.
*/
#define CACTUS_REQ_DEADLOCK_CMD (CACTUS_DEADLOCK_CMD + 1)
static inline smc_ret_values cactus_req_deadlock_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest1,
ffa_vm_id_t next_dest2)
{
return cactus_send_cmd(source, dest, CACTUS_REQ_DEADLOCK_CMD,
next_dest1, next_dest2, 0, 0);
}
/* To get next_dest1 use CACTUS_DEADLOCK_GET_NEXT_DEST */
static inline ffa_vm_id_t cactus_deadlock_get_next_dest2(smc_ret_values ret)
{
return (ffa_vm_id_t)ret.ret5;
}
/**
* Command to notify cactus of a memory management operation. The cmd value
* should be the memory management smc function id.
*
* The id is the hex representation of the string "mem"
*/
#define CACTUS_MEM_SEND_CMD U(0x6d656d)
static inline smc_ret_values cactus_mem_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
ffa_memory_handle_t handle)
{
return cactus_send_cmd(source, dest, CACTUS_MEM_SEND_CMD, mem_func,
handle, 0, 0);
}
static inline ffa_memory_handle_t cactus_mem_send_get_handle(smc_ret_values ret)
{
return (ffa_memory_handle_t)ret.ret5;
}
/**
* Command to request a memory management operation. The 'mem_func' argument
* identifies the operation that is to be performend, and 'receiver' is the id
* of the partition to receive the memory region.
*
* The command id is the hex representation of the string "memory".
*/
#define CACTUS_REQ_MEM_SEND_CMD U(0x6d656d6f7279)
static inline smc_ret_values cactus_req_mem_send_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
ffa_vm_id_t receiver)
{
return cactus_send_cmd(source, dest, CACTUS_REQ_MEM_SEND_CMD, mem_func,
receiver, 0, 0);
}
static inline uint32_t cactus_req_mem_send_get_mem_func(smc_ret_values ret)
{
return (uint32_t)ret.ret4;
}
static inline ffa_vm_id_t cactus_req_mem_send_get_receiver(smc_ret_values ret)
{
return (ffa_vm_id_t)ret.ret5;
}
/**
* Request to fill SIMD vectors with dummy values with purpose to check a
* save/restore routine during the context switches between secure world and
* normal world.
*
* The command id is the hex representation of the string "SIMD"
*/
#define CACTUS_REQ_SIMD_FILL_CMD U(0x53494d44)
static inline smc_ret_values cactus_req_simd_fill_send_cmd(
ffa_vm_id_t source, ffa_vm_id_t dest)
{
return cactus_send_cmd(source, dest, CACTUS_REQ_SIMD_FILL_CMD, 0, 0, 0,
0);
}
/**
* Pairs a command id with a function call, to handle the command ID.
*/
struct cactus_cmd_handler {
const uint64_t id;
smc_ret_values (*fn)(const smc_ret_values *args,
struct mailbox_buffers *mb);
};
/**
* Helper to create the name of a handler function.
*/
#define CACTUS_HANDLER_FN_NAME(name) cactus_##name##_handler
/**
* Define handler's function signature.
*/
#define CACTUS_HANDLER_FN(name) \
static smc_ret_values CACTUS_HANDLER_FN_NAME(name)( \
const smc_ret_values *args, struct mailbox_buffers *mb)
/**
* Helper to define Cactus command handler, and pair it with a command ID.
* It also creates a table with this information, to be traversed by
* 'cactus_handle_cmd' function.
*/
#define CACTUS_CMD_HANDLER(name, ID) \
CACTUS_HANDLER_FN(name); \
struct cactus_cmd_handler name __section(".cactus_handler") = { \
.id = ID, .fn = CACTUS_HANDLER_FN_NAME(name), \
}; \
CACTUS_HANDLER_FN(name)
bool cactus_handle_cmd(smc_ret_values *cmd_args, smc_ret_values *ret,
struct mailbox_buffers *mb);
#endif