blob: b1ea02401c05d25967c75da2e2e0296cdb80d7ce [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,
28 RMI_SUPPORTED);
29 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_512,
30 RMI_SUPPORTED);
31
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,
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000037 RMI_SUPPORTED);
38
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,
46 RMI_SUPPORTED);
47
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 */
92 if ((EXTRACT(RMM_FEATURE_REGISTER_0_PMU_EN, value) == RMI_SUPPORTED) &&
93 (EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, value) !=
94 EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, feat_reg0))) {
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000095 return false;
96 }
97
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +000098 /* Validate SVE flag */
99 if ((EXTRACT(RMM_FEATURE_REGISTER_0_SVE_EN, value) == RMI_SUPPORTED)) {
100 if (!is_feat_sve_present()) {
101 return false;
102 }
103
104 /* Validate SVE_VL value */
105 if (EXTRACT(RMM_FEATURE_REGISTER_0_SVE_VL, value) >
106 simd_sve_get_max_vq()) {
107 return false;
108 }
109 }
110
Soby Mathewb4c6df42022-11-09 11:13:29 +0000111 return true;
112}
113
114bool validate_feature_register(unsigned long index, unsigned long value)
115{
116 switch (index) {
117 case RMM_FEATURE_REGISTER_0_INDEX:
118 return validate_feature_register_0(value);
119 default:
120 assert(false);
121 return false;
122 }
123}