blob: bc53e0046e93bade24921b447b8baf3730709c8a [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>
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000013#include <utils_def.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000014
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000015#define RMM_FEATURE_MIN_IPA_SIZE PARANGE_0000_WIDTH
Yousuf Aa297b9b2022-10-13 13:54:21 +010016
Soby Mathewb4c6df42022-11-09 11:13:29 +000017static unsigned long get_feature_register_0(void)
18{
19 /* Set S2SZ field */
20 unsigned long s2sz = arch_feat_get_pa_width();
21 unsigned long feat_reg0 = INPLACE(RMM_FEATURE_REGISTER_0_S2SZ, s2sz);
22
23 /* Set LPA2 field */
24 if (is_feat_lpa2_4k_present()) {
25 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_LPA2, RMI_LPA2);
26 }
27
28 /* Set support for SHA256 and SHA512 hash algorithms */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000029 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_256,
30 RMI_SUPPORTED);
31 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_512,
32 RMI_SUPPORTED);
33
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000034 /* RMM supports PMUv3p7+ */
35 assert(read_pmu_version() >= ID_AA64DFR0_EL1_PMUv3p7);
36
37 /* Set support for PMUv3 */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000038 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_EN,
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000039 RMI_SUPPORTED);
40
41 /* Set number of PMU counters available */
42 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS,
43 EXTRACT(PMCR_EL0_N, read_pmcr_el0()));
Soby Mathewb4c6df42022-11-09 11:13:29 +000044
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +000045 /* Set SVE fields */
46 if (is_feat_sve_present()) {
47 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_SVE_EN,
48 RMI_SUPPORTED);
49
50 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_SVE_VL,
51 simd_sve_get_max_vq());
52 }
53
Soby Mathewb4c6df42022-11-09 11:13:29 +000054 return feat_reg0;
55}
56
57void smc_read_feature_register(unsigned long index,
58 struct smc_result *ret_struct)
59{
60 switch (index) {
61 case RMM_FEATURE_REGISTER_0_INDEX:
62 ret_struct->x[0] = RMI_SUCCESS;
63 ret_struct->x[1] = get_feature_register_0();
64 break;
65 default:
66 ret_struct->x[0] = RMI_ERROR_INPUT;
shaxio011fcd62d2023-06-13 13:13:11 +010067 ret_struct->x[1] = 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +000068 }
69}
70
71static bool validate_feature_register_0(unsigned long value)
72{
73 unsigned long feat_reg0 = get_feature_register_0();
74 unsigned long s2sz = EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, value);
75
76 /* Validate S2SZ field */
77 if ((s2sz < RMM_FEATURE_MIN_IPA_SIZE) ||
78 (s2sz > EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, feat_reg0))) {
79 return false;
80 }
81
82 /* Validate LPA2 flag */
83 if ((EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, value) == RMI_LPA2) &&
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000084 (EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, feat_reg0) == RMI_NO_LPA2)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000085 return false;
86 }
87
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000088 /*
89 * Skip validation of RMM_FEATURE_REGISTER_0_PMU_EN flag
90 * as RMM always assumes that PMUv3p7+ is present.
91 */
92
93 /* Validate number of PMU counters if PMUv3 is enabled */
94 if ((EXTRACT(RMM_FEATURE_REGISTER_0_PMU_EN, value) == RMI_SUPPORTED) &&
95 (EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, value) !=
96 EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, feat_reg0))) {
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000097 return false;
98 }
99
Arunachalam Ganapathyf6491212023-02-23 16:04:34 +0000100 /* Validate SVE flag */
101 if ((EXTRACT(RMM_FEATURE_REGISTER_0_SVE_EN, value) == RMI_SUPPORTED)) {
102 if (!is_feat_sve_present()) {
103 return false;
104 }
105
106 /* Validate SVE_VL value */
107 if (EXTRACT(RMM_FEATURE_REGISTER_0_SVE_VL, value) >
108 simd_sve_get_max_vq()) {
109 return false;
110 }
111 }
112
Soby Mathewb4c6df42022-11-09 11:13:29 +0000113 return true;
114}
115
116bool validate_feature_register(unsigned long index, unsigned long value)
117{
118 switch (index) {
119 case RMM_FEATURE_REGISTER_0_INDEX:
120 return validate_feature_register_0(value);
121 default:
122 assert(false);
123 return false;
124 }
125}