mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: ffa: Add FFA_RUN support
Add FFA_RUN support and remove mention that YIELD and INTERRUPT are not supported in the comment as we will now return them. Make FFA_FEATURE answer supported for RUN, YIELD and INTERRUPT. Share the SMCCC plumbing used by SEND_DIRECT and RUN via a common ffa_finish_direct_req_run() helper so canonical success and error cases are handled in one place. The dispatcher now routes FFA_RUN through ffa_handle_run(), and direct requests bail out early if a guest targets itself or a non-secure endpoint. This simplifies the direct path while adding support for INTERRUPT or YIELD answers from secure world. Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
This commit is contained in:
1 parent
5c85600270
commit
7a90dad8de
3 files changed
+87
-34
No files matched your search
@@ -24,9 +24,6 @@
|
||||
* o FFA_MEM_DONATE_* and FFA_MEM_LEND_* - Used when tranferring ownership
|
||||
* or access of a memory region
|
||||
* o FFA_MSG_SEND2 and FFA_MSG_WAIT - Used for indirect messaging
|
||||
* o FFA_MSG_YIELD
|
||||
* o FFA_INTERRUPT - Used to report preemption
|
||||
* o FFA_RUN
|
||||
*
|
||||
* Limitations in the implemented FF-A interfaces:
|
||||
* o FFA_RXTX_MAP_*:
|
||||
@@ -266,6 +263,9 @@ static void handle_features(struct cpu_user_regs *regs)
|
||||
case FFA_MSG_SEND_DIRECT_REQ_32:
|
||||
case FFA_MSG_SEND_DIRECT_REQ_64:
|
||||
case FFA_MSG_SEND2:
|
||||
case FFA_RUN:
|
||||
case FFA_INTERRUPT:
|
||||
case FFA_MSG_YIELD:
|
||||
ffa_set_regs_success(regs, 0, 0);
|
||||
break;
|
||||
case FFA_MEM_SHARE_64:
|
||||
@@ -353,6 +353,9 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
|
||||
case FFA_MSG_SEND_DIRECT_REQ_64:
|
||||
ffa_handle_msg_send_direct_req(regs, fid);
|
||||
return true;
|
||||
case FFA_RUN:
|
||||
ffa_handle_run(regs, fid);
|
||||
return true;
|
||||
case FFA_MSG_SEND2:
|
||||
e = ffa_handle_msg_send2(regs);
|
||||
break;
|
||||
|
||||
+80
-31
@@ -21,42 +21,74 @@ struct ffa_part_msg_rxtx {
|
||||
uint32_t msg_size;
|
||||
};
|
||||
|
||||
void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid)
|
||||
static void ffa_finish_direct_req_run(struct cpu_user_regs *regs,
|
||||
struct arm_smccc_1_2_regs *req)
|
||||
{
|
||||
struct arm_smccc_1_2_regs arg = { .a0 = fid, };
|
||||
struct arm_smccc_1_2_regs resp = { };
|
||||
struct domain *d = current->domain;
|
||||
uint32_t src_dst;
|
||||
uint64_t mask;
|
||||
|
||||
if ( smccc_is_conv_64(fid) )
|
||||
arm_smccc_1_2_smc(req, &resp);
|
||||
|
||||
switch ( resp.a0 )
|
||||
{
|
||||
case FFA_ERROR:
|
||||
case FFA_SUCCESS_32:
|
||||
case FFA_SUCCESS_64:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_32:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_64:
|
||||
case FFA_MSG_YIELD:
|
||||
case FFA_INTERRUPT:
|
||||
break;
|
||||
default:
|
||||
/* Bad fid, report back to the caller. */
|
||||
ffa_set_regs_error(regs, FFA_RET_ABORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( smccc_is_conv_64(resp.a0) )
|
||||
mask = GENMASK_ULL(63, 0);
|
||||
else
|
||||
mask = GENMASK_ULL(31, 0);
|
||||
|
||||
ffa_set_regs(regs, resp.a0, resp.a1 & mask, resp.a2 & mask, resp.a3 & mask,
|
||||
resp.a4 & mask, resp.a5 & mask, resp.a6 & mask,
|
||||
resp.a7 & mask);
|
||||
}
|
||||
|
||||
void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid)
|
||||
{
|
||||
struct arm_smccc_1_2_regs arg = { .a0 = fid, };
|
||||
struct domain *d = current->domain;
|
||||
uint32_t src_dst;
|
||||
uint64_t mask;
|
||||
int32_t ret;
|
||||
|
||||
if ( !ffa_fw_supports_fid(fid) )
|
||||
{
|
||||
resp.a0 = FFA_ERROR;
|
||||
resp.a2 = FFA_RET_NOT_SUPPORTED;
|
||||
ret = FFA_RET_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
src_dst = get_user_reg(regs, 1);
|
||||
if ( (src_dst >> 16) != ffa_get_vm_id(d) )
|
||||
if ( (src_dst >> 16) != ffa_get_vm_id(d) ||
|
||||
(src_dst & GENMASK(15,0)) == ffa_get_vm_id(d) )
|
||||
{
|
||||
resp.a0 = FFA_ERROR;
|
||||
resp.a2 = FFA_RET_INVALID_PARAMETERS;
|
||||
ret = FFA_RET_INVALID_PARAMETERS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* we do not support direct messages to VMs */
|
||||
if ( !FFA_ID_IS_SECURE(src_dst & GENMASK(15,0)) )
|
||||
{
|
||||
resp.a0 = FFA_ERROR;
|
||||
resp.a2 = FFA_RET_NOT_SUPPORTED;
|
||||
ret = FFA_RET_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( smccc_is_conv_64(fid) )
|
||||
mask = GENMASK_ULL(63, 0);
|
||||
else
|
||||
mask = GENMASK_ULL(31, 0);
|
||||
|
||||
arg.a1 = src_dst;
|
||||
arg.a2 = get_user_reg(regs, 2) & mask;
|
||||
arg.a3 = get_user_reg(regs, 3) & mask;
|
||||
@@ -65,27 +97,11 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid)
|
||||
arg.a6 = get_user_reg(regs, 6) & mask;
|
||||
arg.a7 = get_user_reg(regs, 7) & mask;
|
||||
|
||||
arm_smccc_1_2_smc(&arg, &resp);
|
||||
switch ( resp.a0 )
|
||||
{
|
||||
case FFA_ERROR:
|
||||
case FFA_SUCCESS_32:
|
||||
case FFA_SUCCESS_64:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_32:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_64:
|
||||
break;
|
||||
default:
|
||||
/* Bad fid, report back to the caller. */
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.a0 = FFA_ERROR;
|
||||
resp.a1 = src_dst;
|
||||
resp.a2 = FFA_RET_ABORTED;
|
||||
}
|
||||
ffa_finish_direct_req_run(regs, &arg);
|
||||
return;
|
||||
|
||||
out:
|
||||
ffa_set_regs(regs, resp.a0, resp.a1 & mask, resp.a2 & mask, resp.a3 & mask,
|
||||
resp.a4 & mask, resp.a5 & mask, resp.a6 & mask,
|
||||
resp.a7 & mask);
|
||||
ffa_set_regs_error(regs, ret);
|
||||
}
|
||||
|
||||
static int32_t ffa_msg_send2_vm(uint16_t dst_id, const void *src_buf,
|
||||
@@ -217,3 +233,36 @@ out:
|
||||
ffa_tx_release(src_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ffa_handle_run(struct cpu_user_regs *regs, uint32_t fid)
|
||||
{
|
||||
struct arm_smccc_1_2_regs arg = { .a0 = fid, };
|
||||
uint32_t dst = get_user_reg(regs, 1);
|
||||
int32_t ret;
|
||||
|
||||
if ( !ffa_fw_supports_fid(fid) )
|
||||
{
|
||||
ret = FFA_RET_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not support FFA_RUN to VMs.
|
||||
* Destination endpoint ID is in bits [31:16], bits[15:0] contain the
|
||||
* vCPU ID.
|
||||
*/
|
||||
if ( !FFA_ID_IS_SECURE(dst >> 16) )
|
||||
{
|
||||
ret = FFA_RET_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
arg.a1 = dst;
|
||||
|
||||
ffa_finish_direct_req_run(regs, &arg);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
ffa_set_regs_error(regs, ret);
|
||||
}
|
||||
@@ -475,6 +475,7 @@ static inline void ffa_raise_rx_buffer_full(struct domain *d)
|
||||
|
||||
void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid);
|
||||
int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs);
|
||||
void ffa_handle_run(struct cpu_user_regs *regs, uint32_t fid);
|
||||
|
||||
#ifdef CONFIG_FFA_VM_TO_VM
|
||||
static inline uint16_t get_ffa_vm_count(void)
|
||||
|
||||