blob: d1e91f1a18f490e83f3e79202fbf1f24101b5167 [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;
67 }
68}
69
70static bool validate_feature_register_0(unsigned long value)
71{
72 unsigned long feat_reg0 = get_feature_register_0();
73 unsigned long s2sz = EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, value);
74
75 /* Validate S2SZ field */
76 if ((s2sz < RMM_FEATURE_MIN_IPA_SIZE) ||
77 (s2sz > EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, feat_reg0))) {
78 return false;
79 }
80
81 /* Validate LPA2 flag */
82 if ((EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, value) == RMI_LPA2) &&
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000083 (EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, feat_reg0) == RMI_NO_LPA2)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000084 return false;
85 }
86
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000087 /*
88 * Skip validation of RMM_FEATURE_REGISTER_0_PMU_EN flag
89 * as RMM always assumes that PMUv3p7+ is present.
90 */
91
92 /* Validate number of PMU counters if PMUv3 is enabled */
93 if ((EXTRACT(RMM_FEATURE_REGISTER_0_PMU_EN, value) == RMI_SUPPORTED) &&
94 (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 */
100 if ((EXTRACT(RMM_FEATURE_REGISTER_0_SVE_EN, value) == RMI_SUPPORTED)) {
101 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}