blob: 352b1409462df49395e72f3008a244eda2d6c744 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch_features.h>
7#include <assert.h>
8#include <feature.h>
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +00009#include <simd.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000010#include <smc-handler.h>
11#include <smc-rmi.h>
12#include <status.h>
Javier Almansa Sobrino765a3162023-04-27 17:42:58 +010013#include <table.h>
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000014#include <utils_def.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000015
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000016#define RMM_FEATURE_MIN_IPA_SIZE PARANGE_0000_WIDTH
Yousuf Aa297b9b2022-10-13 13:54:21 +010017
Soby Mathewb4c6df42022-11-09 11:13:29 +000018static unsigned long get_feature_register_0(void)
19{
Javier Almansa Sobrino765a3162023-04-27 17:42:58 +010020 /* TODO: Announce FEAT_LPA2 through feat_reg0 when supported for S2TTE */
Soby Mathewb4c6df42022-11-09 11:13:29 +000021
Javier Almansa Sobrino765a3162023-04-27 17:42:58 +010022 /* Set S2SZ field */
23 unsigned long s2sz = max_ipa_size();
24 unsigned long feat_reg0 = INPLACE(RMM_FEATURE_REGISTER_0_S2SZ, s2sz);
Soby Mathewb4c6df42022-11-09 11:13:29 +000025
26 /* Set support for SHA256 and SHA512 hash algorithms */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000027 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_256,
AlexeiFedorovc09b1652023-04-04 15:41:37 +010028 RMI_FEATURE_TRUE);
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000029 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_512,
AlexeiFedorovc09b1652023-04-04 15:41:37 +010030 RMI_FEATURE_TRUE);
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000031
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000032 /* RMM supports PMUv3p7+ */
33 assert(read_pmu_version() >= ID_AA64DFR0_EL1_PMUv3p7);
34
35 /* Set support for PMUv3 */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000036 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_EN,
AlexeiFedorovc09b1652023-04-04 15:41:37 +010037 RMI_FEATURE_TRUE);
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000038
39 /* Set number of PMU counters available */
40 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS,
41 EXTRACT(PMCR_EL0_N, read_pmcr_el0()));
Soby Mathewb4c6df42022-11-09 11:13:29 +000042
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +000043 /* Set SVE fields */
44 if (is_feat_sve_present()) {
45 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_SVE_EN,
AlexeiFedorovc09b1652023-04-04 15:41:37 +010046 RMI_FEATURE_TRUE);
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +000047
48 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_SVE_VL,
49 simd_sve_get_max_vq());
50 }
51
Soby Mathewb4c6df42022-11-09 11:13:29 +000052 return feat_reg0;
53}
54
55void smc_read_feature_register(unsigned long index,
56 struct smc_result *ret_struct)
57{
58 switch (index) {
59 case RMM_FEATURE_REGISTER_0_INDEX:
60 ret_struct->x[0] = RMI_SUCCESS;
61 ret_struct->x[1] = get_feature_register_0();
62 break;
63 default:
64 ret_struct->x[0] = RMI_ERROR_INPUT;
shaxio011fcd62d2023-06-13 13:13:11 +010065 ret_struct->x[1] = 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +000066 }
67}
68
69static bool validate_feature_register_0(unsigned long value)
70{
71 unsigned long feat_reg0 = get_feature_register_0();
72 unsigned long s2sz = EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, value);
73
74 /* Validate S2SZ field */
75 if ((s2sz < RMM_FEATURE_MIN_IPA_SIZE) ||
76 (s2sz > EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, feat_reg0))) {
77 return false;
78 }
79
80 /* Validate LPA2 flag */
81 if ((EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, value) == RMI_LPA2) &&
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000082 (EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, feat_reg0) == RMI_NO_LPA2)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000083 return false;
84 }
85
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000086 /*
87 * Skip validation of RMM_FEATURE_REGISTER_0_PMU_EN flag
88 * as RMM always assumes that PMUv3p7+ is present.
89 */
90
91 /* Validate number of PMU counters if PMUv3 is enabled */
AlexeiFedorovc09b1652023-04-04 15:41:37 +010092 if ((EXTRACT(RMM_FEATURE_REGISTER_0_PMU_EN, value) ==
93 RMI_FEATURE_TRUE) &&
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000094 (EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, value) !=
95 EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, feat_reg0))) {
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000096 return false;
97 }
98
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +000099 /* Validate SVE flag */
AlexeiFedorovc09b1652023-04-04 15:41:37 +0100100 if ((EXTRACT(RMM_FEATURE_REGISTER_0_SVE_EN, value) == RMI_FEATURE_TRUE)) {
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +0000101 if (!is_feat_sve_present()) {
102 return false;
103 }
104
105 /* Validate SVE_VL value */
106 if (EXTRACT(RMM_FEATURE_REGISTER_0_SVE_VL, value) >
107 simd_sve_get_max_vq()) {
108 return false;
109 }
110 }
111
Soby Mathewb4c6df42022-11-09 11:13:29 +0000112 return true;
113}
114
115bool validate_feature_register(unsigned long index, unsigned long value)
116{
117 switch (index) {
118 case RMM_FEATURE_REGISTER_0_INDEX:
119 return validate_feature_register_0(value);
120 default:
121 assert(false);
122 return false;
123 }
124}