blob: a5c4a6a8bc655d07d34286a8e4a14d2ea62fd36d [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>
9#include <smc-handler.h>
10#include <smc-rmi.h>
11#include <status.h>
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000012#include <utils_def.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000013
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000014#define RMM_FEATURE_MIN_IPA_SIZE PARANGE_0000_WIDTH
Yousuf Aa297b9b2022-10-13 13:54:21 +010015
Soby Mathewb4c6df42022-11-09 11:13:29 +000016static unsigned long get_feature_register_0(void)
17{
18 /* Set S2SZ field */
19 unsigned long s2sz = arch_feat_get_pa_width();
20 unsigned long feat_reg0 = INPLACE(RMM_FEATURE_REGISTER_0_S2SZ, s2sz);
21
22 /* Set LPA2 field */
23 if (is_feat_lpa2_4k_present()) {
24 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_LPA2, RMI_LPA2);
25 }
26
27 /* Set support for SHA256 and SHA512 hash algorithms */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000028 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_256,
29 RMI_SUPPORTED);
30 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_HASH_SHA_512,
31 RMI_SUPPORTED);
32
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000033 /* RMM supports PMUv3p7+ */
34 assert(read_pmu_version() >= ID_AA64DFR0_EL1_PMUv3p7);
35
36 /* Set support for PMUv3 */
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000037 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_EN,
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000038 RMI_SUPPORTED);
39
40 /* Set number of PMU counters available */
41 feat_reg0 |= INPLACE(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS,
42 EXTRACT(PMCR_EL0_N, read_pmcr_el0()));
Soby Mathewb4c6df42022-11-09 11:13:29 +000043
44 return feat_reg0;
45}
46
47void smc_read_feature_register(unsigned long index,
48 struct smc_result *ret_struct)
49{
50 switch (index) {
51 case RMM_FEATURE_REGISTER_0_INDEX:
52 ret_struct->x[0] = RMI_SUCCESS;
53 ret_struct->x[1] = get_feature_register_0();
54 break;
55 default:
56 ret_struct->x[0] = RMI_ERROR_INPUT;
57 }
58}
59
60static bool validate_feature_register_0(unsigned long value)
61{
62 unsigned long feat_reg0 = get_feature_register_0();
63 unsigned long s2sz = EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, value);
64
65 /* Validate S2SZ field */
66 if ((s2sz < RMM_FEATURE_MIN_IPA_SIZE) ||
67 (s2sz > EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ, feat_reg0))) {
68 return false;
69 }
70
71 /* Validate LPA2 flag */
72 if ((EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, value) == RMI_LPA2) &&
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000073 (EXTRACT(RMM_FEATURE_REGISTER_0_LPA2, feat_reg0) == RMI_NO_LPA2)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000074 return false;
75 }
76
AlexeiFedoroveaec0c42023-02-01 18:13:32 +000077 /*
78 * Skip validation of RMM_FEATURE_REGISTER_0_PMU_EN flag
79 * as RMM always assumes that PMUv3p7+ is present.
80 */
81
82 /* Validate number of PMU counters if PMUv3 is enabled */
83 if ((EXTRACT(RMM_FEATURE_REGISTER_0_PMU_EN, value) == RMI_SUPPORTED) &&
84 (EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, value) !=
85 EXTRACT(RMM_FEATURE_REGISTER_0_PMU_NUM_CTRS, feat_reg0))) {
AlexeiFedorov7bb7a702023-01-17 17:04:14 +000086 return false;
87 }
88
Soby Mathewb4c6df42022-11-09 11:13:29 +000089 return true;
90}
91
92bool validate_feature_register(unsigned long index, unsigned long value)
93{
94 switch (index) {
95 case RMM_FEATURE_REGISTER_0_INDEX:
96 return validate_feature_register_0(value);
97 default:
98 assert(false);
99 return false;
100 }
101}