blob: f8275229cf29d5af580735d2d2134789f6356ec6 [file] [log] [blame]
/*
* Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <tftf.h>
#include <arm_arch_svc.h>
#include <smccc.h>
#include <test_helpers.h>
#include <tftf_lib.h>
static inline u_register_t get_feature_for_reg(u_register_t reg)
{
smc_args args = {0};
smc_ret_values ret;
args.fid = SMCCC_ARCH_FEATURE_AVAILABILITY | (SMC_64 << FUNCID_CC_SHIFT);
args.arg1 = reg;
ret = tftf_smc(&args);
/* APi is pretty simple, support was already checked. This is simpler */
assert((int)ret.ret0 == SMC_ARCH_CALL_SUCCESS);
return ret.ret1;
}
static inline bool always_present(void)
{
return true;
}
/*
* Checks that the bit's matches the feature's presence
* feat_func should be is_feat_xyz_present(), but get_feat_xyz_support() will
* also work.
*/
#define CHECK_BIT_SET(feat_func, bit) \
do { \
if (!!feat_func() != !!(reg & bit)) { \
tftf_testcase_printf( \
#feat_func " says feature is %ssupported but " \
#bit " was %sset!\n", feat_func() ? "" : "not ",\
(reg & bit) ? "" : "not "); \
bad = true; \
} \
reg &= ~bit; \
} while (0)
/* when support for a new feature is added, we want this test to be
* updated. Fail the test so it's noticed. */
#define CHECK_NO_BITS_SET(reg_name) \
do { \
if (reg != 0) { \
tftf_testcase_printf( \
#reg_name " still has values set: 0x%lx. " \
"Test needs to be updated\n", reg); \
bad = true; \
} \
} while (0)
test_result_t test_smccc_arch_feature_availability(void)
{
SKIP_TEST_IF_AARCH32();
#ifdef __aarch64__
SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
SKIP_TEST_IF_SMCCC_FUNC_NOT_SUPPORTED(SMCCC_ARCH_FEATURE_AVAILABILITY |
(SMC_64 << FUNCID_CC_SHIFT));
u_register_t reg;
bool bad = false;
reg = get_feature_for_reg(SCR_EL3_OPCODE);
CHECK_BIT_SET(is_armv8_9_fgt2_present, SCR_FGTEN2_BIT);
CHECK_BIT_SET(is_feat_fpmr_present, SCR_EnFPM_BIT);
CHECK_BIT_SET(is_feat_d128_supported, SCR_D128En_BIT);
CHECK_BIT_SET(is_feat_s1pie_present, SCR_PIEN_BIT);
CHECK_BIT_SET(is_feat_sctlr2_supported, SCR_SCTLR2En_BIT);
CHECK_BIT_SET(is_feat_tcr2_supported, SCR_TCR2EN_BIT);
CHECK_BIT_SET(is_feat_the_supported, SCR_RCWMASKEn_BIT);
CHECK_BIT_SET(is_feat_sme_supported, SCR_ENTP2_BIT);
CHECK_BIT_SET(is_feat_rng_present, SCR_TRNDR_BIT);
CHECK_BIT_SET(is_feat_gcs_present, SCR_GCSEn_BIT);
CHECK_BIT_SET(get_feat_hcx_support, SCR_HXEn_BIT);
CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_ADEn_BIT);
CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_EnAS0_BIT);
CHECK_BIT_SET(is_feat_amuv1p1_present, SCR_AMVOFFEN_BIT);
CHECK_BIT_SET(is_feat_twed_present, SCR_TWEDEn_BIT);
CHECK_BIT_SET(get_armv8_6_ecv_support, SCR_ECVEN_BIT);
CHECK_BIT_SET(is_armv8_6_fgt_present, SCR_FGTEN_BIT);
CHECK_BIT_SET(is_feat_mte2_present, SCR_ATA_BIT);
CHECK_BIT_SET(is_feat_csv2_2_present, SCR_EnSCXT_BIT);
CHECK_BIT_SET(is_armv8_3_pauth_present, SCR_APK_BIT);
CHECK_BIT_SET(is_feat_ras_present, SCR_TERR_BIT);
CHECK_BIT_SET(is_feat_aie_supported, SCR_AIEn_BIT);
CHECK_BIT_SET(is_feat_pfar_supported, SCR_PFAREn_BIT);
CHECK_NO_BITS_SET(SCR_EL3);
reg = get_feature_for_reg(CPTR_EL3_OPCODE);
CHECK_BIT_SET(always_present, CPTR_EL3_TCPAC_BIT);
CHECK_BIT_SET(is_feat_amuv1_present, CPTR_EL3_TAM_BIT);
CHECK_BIT_SET(get_armv8_0_sys_reg_trace_support, CPTR_EL3_TTA_BIT);
CHECK_BIT_SET(is_feat_sme_supported, CPTR_EL3_ESM_BIT);
CHECK_BIT_SET(always_present, CPTR_EL3_TFP_BIT);
CHECK_BIT_SET(is_armv8_2_sve_present, CPTR_EL3_EZ_BIT);
CHECK_NO_BITS_SET(CPTR_EL3);
reg = get_feature_for_reg(MDCR_EL3_OPCODE);
CHECK_BIT_SET(get_feat_brbe_support, MDCR_SBRBE(1));
CHECK_BIT_SET(is_armv8_6_fgt_present, MDCR_TDCC_BIT);
CHECK_BIT_SET(is_feat_trbe_present, MDCR_NSTB(1));
CHECK_BIT_SET(get_armv8_4_trf_support, MDCR_TTRF_BIT);
CHECK_BIT_SET(is_feat_spe_supported, MDCR_NSPB(1));
CHECK_BIT_SET(is_feat_pmuv3p9_present, MDCR_EnPM2_BIT);
CHECK_BIT_SET(is_feat_doublelock_present, MDCR_TDOSA_BIT);
CHECK_BIT_SET(always_present, MDCR_TDA_BIT);
CHECK_BIT_SET(get_feat_pmuv3_supported, MDCR_TPM_BIT);
CHECK_NO_BITS_SET(MDCR_EL3);
reg = get_feature_for_reg(MPAM3_EL3_OPCODE);
CHECK_BIT_SET(is_feat_mpam_supported, MPAM3_EL3_TRAPLOWER_BIT);
CHECK_NO_BITS_SET(MPAM3_EL3);
if (bad)
return TEST_RESULT_FAIL;
return TEST_RESULT_SUCCESS;
#endif /* __aarch64__ */
}