blob: 74c06d4481621cd35771ce7c7b9985be4ac29016 [file] [log] [blame]
/*
* Copyright (c) 2022-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <cactus_test_cmds.h>
#include <ffa_endpoints.h>
#include <ffa_helpers.h>
#include <fpu.h>
#include <host_realm_helper.h>
#include <host_realm_mem_layout.h>
#include <host_shared_data.h>
#include <spm_test_helpers.h>
#include <test_helpers.h>
#include <tftf_lib.h>
#include "host_realm_simd_common.h"
#define REALM_TIME_SLEEP 300U
#define SENDER HYP_ID
#define RECEIVER SP_ID(1)
static const struct ffa_uuid expected_sp_uuids[] = { {PRIMARY_UUID} };
static struct mailbox_buffers mb;
static bool secure_mailbox_initialised;
/*
* Min test iteration count for 'host_and_realm_check_simd' and
* 'host_realm_swd_check_simd' tests.
*/
#define TEST_ITERATIONS_MIN (16U)
/* Number of FPU configs: none */
#define NUM_FPU_CONFIGS (0U)
/* Number of SVE configs: SVE_VL, SVE hint */
#define NUM_SVE_CONFIGS (2U)
/* Number of SME configs: SVE_SVL, FEAT_FA64, Streaming mode */
#define NUM_SME_CONFIGS (3U)
typedef enum {
TEST_FPU = 0U,
TEST_SVE,
TEST_SME,
} simd_test_t;
typedef enum security_state {
NONSECURE_WORLD = 0U,
REALM_WORLD,
SECURE_WORLD,
SECURITY_STATE_MAX
} security_state_t;
/* Defined in host_realm_simd_common.c */
extern sve_z_regs_t ns_sve_z_regs_write;
extern sve_z_regs_t ns_sve_z_regs_read;
static sve_p_regs_t ns_sve_p_regs_write;
static sve_p_regs_t ns_sve_p_regs_read;
static sve_ffr_regs_t ns_sve_ffr_regs_write;
static sve_ffr_regs_t ns_sve_ffr_regs_read;
static fpu_q_reg_t ns_fpu_q_regs_write[FPU_Q_COUNT];
static fpu_q_reg_t ns_fpu_q_regs_read[FPU_Q_COUNT];
static fpu_cs_regs_t ns_fpu_cs_regs_write;
static fpu_cs_regs_t ns_fpu_cs_regs_read;
static struct realm realm;
/* This function helps to initialise secure_mailbox if FFA is supported */
static test_result_t init_secure_partition(void)
{
/* Verify that FF-A is there and that it has the correct version. */
SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1);
if (!secure_mailbox_initialised) {
GET_TFTF_MAILBOX(mb);
CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
secure_mailbox_initialised = true;
}
return TEST_RESULT_SUCCESS;
}
static test_result_t init_realm_payload(struct realm *realm, bool *sve_en_ret)
{
u_register_t rmi_feat_reg0;
test_result_t rc;
uint8_t sve_vq;
bool sve_en;
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
if (host_rmi_features(0UL, &rmi_feat_reg0) != REALM_SUCCESS) {
ERROR("Failed to get RMI feat_reg0\n");
return TEST_RESULT_FAIL;
}
sve_en = rmi_feat_reg0 & RMI_FEATURE_REGISTER_0_SVE_EN;
sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
/* Create Realm with SVE enabled if RMI features supports it */
INFO("TFTF: create realm sve_en/sve_vq: %d/%d\n", sve_en, sve_vq);
rc = host_create_sve_realm_payload(realm, sve_en, sve_vq, 1U, 0U);
if (rc != TEST_RESULT_SUCCESS) {
return rc;
}
if (sve_en_ret != NULL) {
*sve_en_ret = sve_en;
}
return TEST_RESULT_SUCCESS;
}
static bool host_realm_handle_fiq_exit(struct realm *realm_ptr,
unsigned int rec_num)
{
struct rmi_rec_run *run = (struct rmi_rec_run *)realm_ptr->run[rec_num];
if (run->exit.exit_reason == RMI_EXIT_FIQ) {
return true;
}
return false;
}
/*
* @Test_Aim@ Test secure interrupt handling while Secure Partition is in waiting
* state and Realm world runs a busy loop at R-EL1.
*
* 1. Send a direct message request command to first Cactus SP to start the
* trusted watchdog timer.
*
* 2. Once the SP returns with a direct response message, it moves to WAITING
* state.
*
* 3. Create and execute a busy loop to sleep the PE in the realm world for
* REALM_TIME_SLEEP ms.
*
* 4. Trusted watchdog timer expires during this time which leads to secure
* interrupt being triggered while cpu is executing in realm world.
*
* 5. Realm EL1 exits to host, but because the FIQ is still pending,
* the Host will be pre-empted to EL3.
*
* 6. The interrupt is trapped to BL31/SPMD as FIQ and later synchronously
* delivered to SPM.
*
* 7. SPM injects a virtual IRQ to first Cactus Secure Partition.
*
* 8. Once the SP has handled the interrupt, it returns execution back to normal
* world using FFA_MSG_WAIT call.
*
* 9. TFTF parses REC's exit reason (FIQ in this case).
*
* 10. TFTF sends a direct request message to SP to query the ID of last serviced
* secure virtual interrupt.
*
* 121. Further, TFTF expects SP to return the ID of Trusted Watchdog timer
* interrupt through a direct response message.
*
* 13. Test finishes successfully once the TFTF disables the trusted watchdog
* interrupt through a direct message request command.
*
* 14. TFTF then proceed to destroy the Realm.
*
*/
test_result_t host_realm_sec_interrupt_can_preempt_rl(void)
{
struct ffa_value ret_values;
test_result_t res;
res = init_secure_partition();
if (res != TEST_RESULT_SUCCESS) {
return res;
}
res = init_realm_payload(&realm, NULL);
if (res != TEST_RESULT_SUCCESS) {
return res;
}
/* Enable trusted watchdog interrupt as IRQ in the secure side. */
if (!enable_trusted_wdog_interrupt(SENDER, RECEIVER)) {
goto destroy_realm;
}
/*
* Send a message to SP1 through direct messaging.
*/
ret_values = cactus_send_twdog_cmd(SENDER, RECEIVER,
(REALM_TIME_SLEEP/2));
if (!is_ffa_direct_response(ret_values)) {
ERROR("Expected a direct response for starting TWDOG timer\n");
goto destroy_realm;
}
/*
* Spin Realm payload for REALM_TIME_SLEEP ms, This ensures secure wdog
* timer triggers during this time.
*/
host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U,
HOST_ARG1_INDEX, REALM_TIME_SLEEP);
host_enter_realm_execute(&realm, REALM_SLEEP_CMD, RMI_EXIT_FIQ, 0U);
/*
* Check if Realm exit reason is FIQ.
*/
if (!host_realm_handle_fiq_exit(&realm, 0U)) {
ERROR("Trusted watchdog timer interrupt not fired\n");
goto destroy_realm;
}
/* Check for the last serviced secure virtual interrupt. */
ret_values = cactus_get_last_interrupt_cmd(SENDER, RECEIVER);
if (!is_ffa_direct_response(ret_values)) {
ERROR("Expected a direct response for last serviced interrupt"
" command\n");
goto destroy_realm;
}
/* Make sure Trusted Watchdog timer interrupt was serviced*/
if (cactus_get_response(ret_values) != IRQ_TWDOG_INTID) {
ERROR("Trusted watchdog timer interrupt not serviced by SP\n");
goto destroy_realm;
}
/* Disable Trusted Watchdog interrupt. */
if (!disable_trusted_wdog_interrupt(SENDER, RECEIVER)) {
goto destroy_realm;
}
if (!host_destroy_realm(&realm)) {
ERROR("host_destroy_realm error\n");
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
destroy_realm:
host_destroy_realm(&realm);
return TEST_RESULT_FAIL;
}
/* Choose a random security state that is different from the 'current' state */
static security_state_t get_random_security_state(security_state_t current,
bool is_sp_present,
bool is_rl_present)
{
security_state_t next;
/*
* 3 world config:
* Switch between NS world and Realm world if Secure world is not
* enabled or SP is not loaded. or
* Switch between NS world and Secure world if Realm world is not
* enabled.
*/
if (is_sp_present ^ is_rl_present) {
if (current == NONSECURE_WORLD) {
return is_rl_present ? REALM_WORLD : SECURE_WORLD;
} else {
return NONSECURE_WORLD;
}
}
/*
* 4 world config: Randomly select a security_state between Realm, NS
* and Secure until the new state is not equal to the current state.
*/
while (true) {
next = rand() % SECURITY_STATE_MAX;
if (next == current) {
continue;
}
break;
}
return next;
}
/* Generate random values and write it to SVE Z, P and FFR registers */
static void ns_sve_write_rand(void)
{
bool has_ffr = true;
if (is_feat_sme_supported() && sme_smstat_sm() &&
!sme_feat_fa64_enabled()) {
has_ffr = false;
}
sve_z_regs_write_rand(&ns_sve_z_regs_write);
sve_p_regs_write_rand(&ns_sve_p_regs_write);
if (has_ffr) {
sve_ffr_regs_write_rand(&ns_sve_ffr_regs_write);
}
}
/* Read SVE Z, P and FFR registers and compare it with the last written values */
static test_result_t ns_sve_read_and_compare(void)
{
test_result_t rc = TEST_RESULT_SUCCESS;
uint64_t bitmap;
bool has_ffr = true;
if (is_feat_sme_supported() && sme_smstat_sm() &&
!sme_feat_fa64_enabled()) {
has_ffr = false;
}
/* Clear old state */
memset((void *)&ns_sve_z_regs_read, 0, sizeof(ns_sve_z_regs_read));
memset((void *)&ns_sve_p_regs_read, 0, sizeof(ns_sve_p_regs_read));
memset((void *)&ns_sve_ffr_regs_read, 0, sizeof(ns_sve_ffr_regs_read));
/* Read Z, P, FFR registers to compare it with the last written values */
sve_z_regs_read(&ns_sve_z_regs_read);
sve_p_regs_read(&ns_sve_p_regs_read);
if (has_ffr) {
sve_ffr_regs_read(&ns_sve_ffr_regs_read);
}
bitmap = sve_z_regs_compare(&ns_sve_z_regs_write, &ns_sve_z_regs_read);
if (bitmap != 0UL) {
ERROR("SVE Z regs compare failed (bitmap: 0x%016llx)\n",
bitmap);
rc = TEST_RESULT_FAIL;
}
bitmap = sve_p_regs_compare(&ns_sve_p_regs_write, &ns_sve_p_regs_read);
if (bitmap != 0UL) {
ERROR("SVE P regs compare failed (bitmap: 0x%016llx)\n",
bitmap);
rc = TEST_RESULT_FAIL;
}
if (has_ffr) {
bitmap = sve_ffr_regs_compare(&ns_sve_ffr_regs_write,
&ns_sve_ffr_regs_read);
if (bitmap != 0) {
ERROR("SVE FFR regs compare failed "
"(bitmap: 0x%016llx)\n", bitmap);
rc = TEST_RESULT_FAIL;
}
}
return rc;
}
/*
* Generate random values and write it to Streaming SVE Z, P and FFR registers.
*/
static void ns_sme_write_rand(void)
{
/*
* TODO: more SME specific registers like ZA, ZT0 can be included later.
*/
/* Fill SVE registers in normal or streaming SVE mode */
ns_sve_write_rand();
}
/*
* Read streaming SVE Z, P and FFR registers and compare it with the last
* written values
*/
static test_result_t ns_sme_read_and_compare(void)
{
/*
* TODO: more SME specific registers like ZA, ZT0 can be included later.
*/
/* Compares SVE registers in normal or streaming SVE mode */
return ns_sve_read_and_compare();
}
static char *simd_type_to_str(simd_test_t type)
{
if (type == TEST_FPU) {
return "FPU";
} else if (type == TEST_SVE) {
return "SVE";
} else if (type == TEST_SME) {
return "SME";
} else {
return "UNKNOWN";
}
}
static void ns_simd_print_cmd_config(bool cmd, simd_test_t type)
{
char __unused *tstr = simd_type_to_str(type);
char __unused *cstr = cmd ? "write rand" : "read and compare";
if (type == TEST_SME) {
if (sme_smstat_sm()) {
INFO("TFTF: NS [%s] %s. Config: smcr: 0x%llx, SM: on\n",
tstr, cstr, (uint64_t)read_smcr_el2());
} else {
INFO("TFTF: NS [%s] %s. Config: smcr: 0x%llx, "
"zcr: 0x%llx sve_hint: %d SM: off\n", tstr, cstr,
(uint64_t)read_smcr_el2(),
(uint64_t)sve_read_zcr_elx(),
tftf_smc_get_sve_hint());
}
} else if (type == TEST_SVE) {
INFO("TFTF: NS [%s] %s. Config: zcr: 0x%llx, sve_hint: %d\n",
tstr, cstr, (uint64_t)sve_read_zcr_elx(),
tftf_smc_get_sve_hint());
} else {
INFO("TFTF: NS [%s] %s\n", tstr, cstr);
}
}
/*
* Randomly select TEST_SME or TEST_FPU. For TEST_SME, randomly select below
* configurations:
* - enable/disable streaming mode
* For streaming mode:
* - enable or disable FA64
* - select random streaming vector length
* For normal SVE mode:
* - select random normal SVE vector length
*/
static simd_test_t ns_sme_select_random_config(void)
{
simd_test_t type;
static unsigned int counter;
/* Use a static counter to mostly select TEST_SME case. */
if ((counter % 8U) != 0) {
/* Use counter to toggle between Streaming mode on or off */
if (is_armv8_2_sve_present() && ((counter % 2U) != 0)) {
sme_smstop(SMSTOP_SM);
sve_config_vq(SVE_GET_RANDOM_VQ);
if ((counter % 3U) != 0) {
tftf_smc_set_sve_hint(true);
} else {
tftf_smc_set_sve_hint(false);
}
} else {
sme_smstart(SMSTART_SM);
sme_config_svq(SME_GET_RANDOM_SVQ);
if ((counter % 3U) != 0) {
sme_enable_fa64();
} else {
sme_disable_fa64();
}
}
type = TEST_SME;
} else {
type = TEST_FPU;
}
counter++;
return type;
}
/*
* Randomly select TEST_SVE or TEST_FPU. For TEST_SVE, configure zcr_el2 with
* random vector length and randomly enable or disable SMC SVE hint bit.
*/
static simd_test_t ns_sve_select_random_config(void)
{
simd_test_t type;
static unsigned int counter;
/* Use a static counter to mostly select TEST_SVE case. */
if ((counter % 4U) != 0) {
sve_config_vq(SVE_GET_RANDOM_VQ);
if ((counter % 2U) != 0) {
tftf_smc_set_sve_hint(true);
} else {
tftf_smc_set_sve_hint(false);
}
type = TEST_SVE;
} else {
type = TEST_FPU;
}
counter++;
return type;
}
/*
* Configure NS world SIMD. Randomly choose to test SVE or FPU registers if
* system supports SVE.
*
* Returns either TEST_FPU or TEST_SVE or TEST_SME
*/
static simd_test_t ns_simd_select_random_config(void)
{
simd_test_t type;
/* cleanup old config for SME */
if (is_feat_sme_supported()) {
sme_smstop(SMSTOP_SM);
sme_enable_fa64();
}
/* Cleanup old config for SVE */
if (is_armv8_2_sve_present()) {
tftf_smc_set_sve_hint(false);
}
if (is_armv8_2_sve_present() && is_feat_sme_supported()) {
if (rand() % 2) {
type = ns_sme_select_random_config();
} else {
type = ns_sve_select_random_config();
}
} else if (is_feat_sme_supported()) {
type = ns_sme_select_random_config();
} else if (is_armv8_2_sve_present()) {
type = ns_sve_select_random_config();
} else {
type = TEST_FPU;
}
return type;
}
/* Select random NS SIMD config and write random values to its registers */
static simd_test_t ns_simd_write_rand(void)
{
simd_test_t type;
type = ns_simd_select_random_config();
ns_simd_print_cmd_config(true, type);
if (type == TEST_SME) {
ns_sme_write_rand();
} else if (type == TEST_SVE) {
ns_sve_write_rand();
} else {
fpu_q_regs_write_rand(ns_fpu_q_regs_write);
}
/* fpcr, fpsr common to all configs */
fpu_cs_regs_write_rand(&ns_fpu_cs_regs_write);
return type;
}
/* Read and compare the NS SIMD registers with the last written values */
static test_result_t ns_simd_read_and_compare(simd_test_t type)
{
test_result_t rc = TEST_RESULT_SUCCESS;
ns_simd_print_cmd_config(false, type);
if (type == TEST_SME) {
rc = ns_sme_read_and_compare();
} else if (type == TEST_SVE) {
rc = ns_sve_read_and_compare();
} else {
fpu_q_regs_read(ns_fpu_q_regs_read);
if (fpu_q_regs_compare(ns_fpu_q_regs_write,
ns_fpu_q_regs_read)) {
ERROR("FPU Q registers compare failed\n");
rc = TEST_RESULT_FAIL;
}
}
/* fpcr, fpsr common to all configs */
fpu_cs_regs_read(&ns_fpu_cs_regs_read);
if (fpu_cs_regs_compare(&ns_fpu_cs_regs_write, &ns_fpu_cs_regs_read)) {
ERROR("FPCR/FPSR registers compare failed\n");
rc = TEST_RESULT_FAIL;
}
return rc;
}
/* Select random Realm SIMD config and write random values to its registers */
static simd_test_t rl_simd_write_rand(struct realm *realm, bool rl_sve_en)
{
enum realm_cmd rl_fill_cmd;
simd_test_t type;
bool __unused rc;
/* Select random commands to test. SVE or FPU registers in Realm */
if (rl_sve_en && (rand() % 2)) {
type = TEST_SVE;
} else {
type = TEST_FPU;
}
INFO("TFTF: RL [%s] write random\n", simd_type_to_str(type));
if (type == TEST_SVE) {
rl_fill_cmd = REALM_SVE_FILL_REGS;
} else {
rl_fill_cmd = REALM_REQ_FPU_FILL_CMD;
}
rc = host_enter_realm_execute(realm, rl_fill_cmd, RMI_EXIT_HOST_CALL, 0U);
assert(rc);
return type;
}
/* Read and compare the Realm SIMD registers with the last written values */
static bool rl_simd_read_and_compare(struct realm *realm, simd_test_t type)
{
enum realm_cmd rl_cmp_cmd;
INFO("TFTF: RL [%s] read and compare\n", simd_type_to_str(type));
if (type == TEST_SVE) {
rl_cmp_cmd = REALM_SVE_CMP_REGS;
} else {
rl_cmp_cmd = REALM_REQ_FPU_CMP_CMD;
}
return host_enter_realm_execute(realm, rl_cmp_cmd, RMI_EXIT_HOST_CALL,
0U);
}
/* Send request to SP to fill FPU/SIMD regs with secure template values */
static bool sp_fpu_write_rand(void)
{
struct ffa_value ret = cactus_req_simd_fill_send_cmd(SENDER, RECEIVER);
if (!is_ffa_direct_response(ret)) {
ERROR("%s failed %d\n", __func__, __LINE__);
return false;
}
if (cactus_get_response(ret) == CACTUS_ERROR) {
ERROR("%s failed %d\n", __func__, __LINE__);
return false;
}
return true;
}
/* Send request to SP to compare FPU/SIMD regs with secure template values */
static bool sp_fpu_read_and_compare(void)
{
struct ffa_value ret = cactus_req_simd_compare_send_cmd(SENDER,
RECEIVER);
if (!is_ffa_direct_response(ret)) {
ERROR("%s failed %d\n", __func__, __LINE__);
return false;
}
if (cactus_get_response(ret) == CACTUS_ERROR) {
ERROR("%s failed %d\n", __func__, __LINE__);
return false;
}
return true;
}
/*
* This test case verifies whether various SIMD related registers like Q[0-31],
* FPCR, FPSR, Z[0-31], P[0-15], FFR are preserved by:
*
* 1. RMM during world switch between NS world and Realm world.
* 2. Hafnium during world switch between NS world and Secure world.
*
* This testcase runs on below SIMD configs:
* - SVE only
* - SME only
* - with SVE and SME
* - without SVE and SME
*
* This testcase runs on below world configs:
* - Secure world only
* - Realm world only
* - With Secure and Realm world
*/
test_result_t host_realm_swd_check_simd(void)
{
test_result_t rc;
bool sve_en = false;
security_state_t sec_state;
simd_test_t ns_simd_type;
simd_test_t rl_simd_type = TEST_FPU;
unsigned int test_iterations;
unsigned int num_simd_types;
unsigned int num_simd_configs;
bool is_sp_present = false;
bool is_rl_present = false;
/* Init and fill FPU registers in Secure world if present */
if (init_secure_partition() == TEST_RESULT_SUCCESS) {
is_sp_present = true;
if (!sp_fpu_write_rand()) {
ERROR("%s failed %d\n", __func__, __LINE__);
return TEST_RESULT_FAIL;
}
}
/* Init and fill FPU or SVE registers in Realm if present */
if (init_realm_payload(&realm, &sve_en) == TEST_RESULT_SUCCESS) {
is_rl_present = true;
rl_simd_type = rl_simd_write_rand(&realm, sve_en);
}
if (!is_sp_present && !is_rl_present) {
INFO("Neither SP nor Realm exists. Skipping test case\n");
return TEST_RESULT_SKIPPED;
}
/*
* Randomly select and configure NS simd context to test. And fill it
* with random values.
*/
ns_simd_type = ns_simd_write_rand();
sec_state = NONSECURE_WORLD;
/*
* Find out test iterations based on if SVE is enabled and the number of
* configurations available in the SVE.
*/
/* FPU is always available */
num_simd_types = 1U;
num_simd_configs = NUM_FPU_CONFIGS;
if (is_armv8_2_sve_present()) {
num_simd_types += 1;
num_simd_configs += NUM_SVE_CONFIGS;
}
if (is_feat_sme_supported()) {
num_simd_types += 1;
num_simd_configs += NUM_SME_CONFIGS;
}
if (num_simd_configs > 0U) {
test_iterations = TEST_ITERATIONS_MIN * num_simd_types *
num_simd_configs;
} else {
test_iterations = TEST_ITERATIONS_MIN * num_simd_types;
}
if (is_sp_present && is_rl_present) {
test_iterations *= 2U;
}
/*
* Test loop:
* security_state = get_random_security_state()
*
* switch to security_state
* if (SIMD registers read != last filled values)
* break loop; return TC_FAIL
*
* Fill SIMD registers with new random values for the next comparison.
*/
for (uint32_t i = 0U; i < test_iterations; i++) {
sec_state = get_random_security_state(sec_state, is_sp_present,
is_rl_present);
switch (sec_state) {
case NONSECURE_WORLD:
/*
* Read NS simd context and compare it with last written
* context.
*/
rc = ns_simd_read_and_compare(ns_simd_type);
if (rc != TEST_RESULT_SUCCESS) {
ERROR("%s failed %d\n", __func__, __LINE__);
rc = TEST_RESULT_FAIL;
goto rm_realm;
}
/*
* Randomly select and configure NS simd context. And
* fill it with random values for the next compare.
*/
ns_simd_type = ns_simd_write_rand();
break;
case REALM_WORLD:
/*
* Enter Realm and read the simd context and compare it
* with last written context.
*/
if (!rl_simd_read_and_compare(&realm, rl_simd_type)) {
ERROR("%s failed %d\n", __func__, __LINE__);
rc = TEST_RESULT_FAIL;
goto rm_realm;
}
/*
* Randomly select and configure Realm simd context to
* test. Enter realm and fill simd context with random
* values for the next compare.
*/
rl_simd_type = rl_simd_write_rand(&realm, sve_en);
break;
case SECURE_WORLD:
INFO("TFTF: S [FPU] read and compare\n");
/* Secure world verify its FPU/SIMD state registers */
if (!sp_fpu_read_and_compare()) {
ERROR("%s failed %d\n", __func__, __LINE__);
rc = TEST_RESULT_FAIL;
goto rm_realm;
}
INFO("TFTF: S [FPU] write random\n");
/* Fill FPU state with new random values in SP */
if (!sp_fpu_write_rand()) {
rc = TEST_RESULT_FAIL;
goto rm_realm;
}
break;
default:
break;
}
}
rc = TEST_RESULT_SUCCESS;
rm_realm:
/* Cleanup old config */
if (is_feat_sme_supported()) {
sme_smstop(SMSTOP_SM);
sme_enable_fa64();
}
/* Cleanup old config */
if (is_armv8_2_sve_present()) {
tftf_smc_set_sve_hint(false);
}
if (is_rl_present && !host_destroy_realm(&realm)) {
return TEST_RESULT_FAIL;
}
return rc;
}