blob: c03768bbd268c118064fd824afcb38edb48a07c9 [file] [log] [blame]
/*
* Adapted from Hafnium.
* TODO: Figure out the right way of specifying the license header.
*/
#include <libcflat.h>
#include "arm64/call.h"
#include "arm64/ffa.h"
/* SMCCC reserves ID 0 for the hypervisor itself. */
const int HYPERVISOR_ID = 0;
/* For now, assume the primary VM has an ID of 1, same as hafnium */
const ffa_vm_id_t PRIMARY_VM_ID = 1;
static void test_ffa_primary_basics(void)
{
bool pass = true;
struct ffa_value ret;
ffa_vm_id_t vm_id;
ret = ffa_id_get();
pass &= (ret.func == FFA_SUCCESS_32 && ret.arg2 != HYPERVISOR_ID);
vm_id = ret.arg2;
if (vm_id != PRIMARY_VM_ID) {
report_info("VM id %d not a primary VM.", vm_id);
goto end;
}
/* Yielding from the primary is a noop. */
ret = ffa_yield();
pass &= (ret.func == FFA_SUCCESS_32);
end:
report(pass, "ffa_primary_basics");
}
static void test_ffa_basics(void)
{
bool pass = true;
struct ffa_value ret;
ret = ffa_id_get();
pass &= (ret.func == FFA_SUCCESS_32 && ret.arg2 != HYPERVISOR_ID);
/* Primary VM cannot be run by the hypervisor. */
ret = ffa_run(PRIMARY_VM_ID, 0);
pass &= (ret.func == FFA_ERROR_32);
/* Cannot run a non-existent VM. */
ret = ffa_run(PRIMARY_VM_ID + 1234, 0);
pass &= (ret.func == FFA_ERROR_32);
report(pass, "ffa_basics");
}
/** Ensures that the FF-A version is reported as expected. */
static void test_ffa_version(void)
{
const int32_t major_revision = 1;
const int32_t major_revision_offset = 16;
const int32_t minor_revision = 0;
const int32_t current_version =
(major_revision << major_revision_offset) | minor_revision;
bool pass = true;
int32_t ret;
pass &= (ffa_version(current_version) == current_version);
pass &= (ffa_version(0x0) == current_version);
pass &= (ffa_version(0x1)== current_version);
pass &= (ffa_version(0x10003) == current_version);
pass &= (ffa_version(0xffff) == current_version);
pass &= (ffa_version(0xfffffff) == current_version);
ret = ffa_version(0x80000000);
pass &= (ret == FFA_NOT_SUPPORTED);
report(pass, "ffa_version");
}
static void test_ffa_features(void)
{
bool pass = true;
struct ffa_value ret;
/*
* TODO: Some features are mandatory some are optional.
* Handle appropriately based on that.
*/
ret = ffa_features(FFA_ERROR_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_SUCCESS_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_INTERRUPT_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_VERSION_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_FEATURES_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_RX_RELEASE_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_RXTX_MAP_64);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_ID_GET_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MSG_POLL_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MSG_WAIT_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_YIELD_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_RUN_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MSG_SEND_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_DONATE_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_LEND_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_SHARE_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_RETRIEVE_REQ_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_RETRIEVE_RESP_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_RELINQUISH_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(FFA_MEM_RECLAIM_32);
pass &= (ret.func == FFA_SUCCESS_32);
ret = ffa_features(0);
pass &= (ret.func == FFA_ERROR_32 && ret.arg2 == FFA_NOT_SUPPORTED);
ret = ffa_features(0x84000000);
pass &= (ret.func == FFA_ERROR_32 && ret.arg2 == FFA_NOT_SUPPORTED);
report(pass, "ffa_features");
}
int main(void)
{
test_ffa_basics();
test_ffa_primary_basics();
test_ffa_version();
test_ffa_features();
report_pass();
return report_summary();
}