| /* |
| * 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(); |
| } |