blob: 35c83019df31c9a1887d60f4cbb1f5ab89c8d433 [file] [log] [blame]
/*
* Copyright (c) 2024 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ffa_helpers.h"
#include "spm_common.h"
#include "tftf_lib.h"
#include <debug.h>
#include <smccc.h>
#include <arch_helpers.h>
#include <cactus_test_cmds.h>
#include <ffa_endpoints.h>
#include <ffa_svc.h>
#include <host_realm_helper.h>
#include <platform.h>
#include <spm_test_helpers.h>
#include <test_helpers.h>
static const struct ffa_uuid expected_sp_uuids[] = {
{PRIMARY_UUID},
};
const char expected_msg[] = "Testing FF-A message.";
/*
*
* Used as the RX/TX buffers belonging to VM 1 in the forwarding FFA_RXTX_MAP
* tests.
*/
static __aligned(PAGE_SIZE) uint8_t vm1_rx_buffer[PAGE_SIZE];
static __aligned(PAGE_SIZE) uint8_t vm1_tx_buffer[PAGE_SIZE];
test_result_t test_ffa_indirect_message_sp_to_vm(void)
{
struct ffa_value ret;
struct mailbox_buffers mb;
ffa_id_t header_sender;
const ffa_id_t vm_id = 1;
const ffa_id_t sender = SP_ID(1);
char msg[300];
/**********************************************************************
* Check SPMC has ffa_version and expected FF-A endpoints are deployed.
**********************************************************************/
CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
GET_TFTF_MAILBOX(mb);
ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
vm1_tx_buffer);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
vm1_tx_buffer, vm1_tx_buffer, vm_id);
return TEST_RESULT_FAIL;
}
ret = ffa_notification_bitmap_create(vm_id, PLATFORM_CORE_COUNT);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to create bitmap for vm %x\n", vm_id);
return TEST_RESULT_FAIL;
}
/* Request SP to send message. */
ret = cactus_req_ind_msg_send_cmd(
HYP_ID, sender, vm_id, sender, 0);
if (!is_ffa_direct_response(ret) &&
cactus_get_response(ret) != CACTUS_SUCCESS) {
return TEST_RESULT_FAIL;
}
if (!receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
&header_sender, vm_id, 0)) {
return TEST_RESULT_FAIL;
}
if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
return TEST_RESULT_FAIL;
}
if (header_sender != sender) {
ERROR("Unexpected endpoints. Sender: %x Expected: %x\n",
header_sender, sender);
return TEST_RESULT_FAIL;
}
ret = ffa_notification_bitmap_destroy(vm_id);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
return TEST_RESULT_FAIL;
}
ret = ffa_rxtx_unmap_with_id(vm_id);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}
/**
* Test message sent from SP to VM when VM's RX is realm, the operation fails
* smoothly.
*/
test_result_t test_ffa_indirect_message_sp_to_vm_rx_realm_fail(void)
{
struct ffa_value ret;
struct mailbox_buffers mb;
const ffa_id_t vm_id = 1;
const ffa_id_t sender = SP_ID(1);
ffa_id_t header_sender;
u_register_t ret_rmm;
char msg[300];
if (get_armv9_2_feat_rme_support() == 0U) {
return TEST_RESULT_SKIPPED;
}
/**********************************************************************
* Check SPMC has ffa_version and expected FF-A endpoints are deployed.
**********************************************************************/
CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
GET_TFTF_MAILBOX(mb);
/* Map RXTX buffers into SPMC translation. */
ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
vm1_tx_buffer);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
vm1_rx_buffer, vm1_tx_buffer, vm_id);
return TEST_RESULT_FAIL;
}
/*
* Create bitmap only to then demonstrate that the message can't
* be sent, as there are no pending notifications to the VM.
*/
ret = ffa_notification_bitmap_create(vm_id, PLATFORM_CORE_COUNT);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to create bitmap for vm %x\n", vm_id);
return TEST_RESULT_FAIL;
}
/*
* Delegate RX buffer of VM to realm.
*/
ret_rmm = host_rmi_granule_delegate((u_register_t)vm1_rx_buffer);
if (ret_rmm != 0UL) {
INFO("Delegate operation returns %#lx for address %p\n",
ret_rmm, mb.send);
return TEST_RESULT_FAIL;
}
/* Request SP to send message. */
ret = cactus_req_ind_msg_send_cmd(
HYP_ID, sender, vm_id, sender, 0);
if (!is_ffa_direct_response(ret) &&
cactus_get_response(ret) != FFA_ERROR_ABORTED) {
return TEST_RESULT_FAIL;
}
/* Undelegate to reestablish the same security state for PAS. */
ret_rmm = host_rmi_granule_undelegate((u_register_t)vm1_rx_buffer);
if (ret_rmm != 0UL) {
INFO("Undelegate operation returns %#lx for address %p\n",
ret_rmm, mb.send);
return TEST_RESULT_FAIL;
}
/* Expect that attempting to receive message shall fail. */
if (receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
NULL, vm_id, 0)) {
return TEST_RESULT_FAIL;
}
/*
* Redo the test so we check after undelegating the memory.
* After undelegating, the SPMC should be able to complete the
* operation.
*/
ret = cactus_req_ind_msg_send_cmd(
HYP_ID, sender, vm_id, sender, 0);
if (!is_ffa_direct_response(ret) &&
cactus_get_response(ret) != CACTUS_SUCCESS) {
return TEST_RESULT_FAIL;
}
if (!receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
&header_sender, vm_id, 0)) {
return TEST_RESULT_FAIL;
}
if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
return TEST_RESULT_FAIL;
}
if (header_sender != sender) {
ERROR("Unexpected endpoints. Sender: %x Expected: %x\n",
header_sender, sender);
return TEST_RESULT_FAIL;
}
/* Cleaning up after the test: */
/* Destroy bitmap of VM. */
ret = ffa_notification_bitmap_destroy(vm_id);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to destroy bitmap for vm %x\n", vm_id);
return TEST_RESULT_FAIL;
}
/* Unmap RXTX buffers into SPMC translation. */
ret = ffa_rxtx_unmap_with_id(vm_id);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
ERROR("Failed to unmap RXTX for vm %x\n", vm_id);
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}