1 /*
2 * Copyright (c) 2026, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <errno.h>
8 #include <stdint.h>
9
10 #include <arch.h>
11 #include <arch_features.h>
12 #include <common/debug.h>
13 #include <lib/gpt_rme/gpt_rme.h>
14 #include <lib/smccc.h>
15 #include <services/firme_svc.h>
16 #include <smccc_helpers.h>
17
18 /* Only supported ABI is GPI_SET for now. */
19 #define FEAT_REG_0_DEFAULT (FIRME_GM_GPI_SET_BIT)
20
21 /* Reg 1 is built at runtime based on hardware config. */
22 #define FEAT_REG_1_DEFAULT 0
23
24 static firme_service_info_t granule_mgmt_info = {
25 .version = FIRME_VERSION(FIRME_GRANULE_MGMT_VERSION_MAJOR,
26 FIRME_GRANULE_MGMT_VERSION_MINOR),
27 #if ENABLE_RMM
28 .instance_support =
29 (BIT(FIRME_SECURE) | BIT(FIRME_NONSECURE) | BIT(FIRME_REALM)),
30 #else
31 .instance_support = (BIT(FIRME_SECURE) | BIT(FIRME_NONSECURE)),
32 #endif
33 .num_feature_regs = 2,
34 .feature_reg = { FEAT_REG_0_DEFAULT, FEAT_REG_1_DEFAULT },
35 };
36
firme_granule_mgmt_service_get_info(void)37 firme_service_info_t *firme_granule_mgmt_service_get_info(void)
38 {
39 /* Build feat reg 1 value from GPCCR value. */
40 uint64_t gpccr;
41
42 if (!is_feat_rme_supported()) {
43 return NULL;
44 }
45
46 /*
47 * todo: FIRME must have a init routine to perform one time
48 * initialization during boot for all supported services.
49 */
50 gpccr = read_gpccr_el3();
51
52 granule_mgmt_info.feature_reg[1] |=
53 ((gpccr >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK)
54 << FIRME_GM_PGS_SHIFT;
55 granule_mgmt_info.feature_reg[1] |=
56 ((gpccr >> GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK)
57 << FIRME_GM_L0GPTSZ_SHIFT;
58 granule_mgmt_info.feature_reg[1] |=
59 ((gpccr >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK)
60 << FIRME_GM_PPS_SHIFT;
61
62 return &granule_mgmt_info;
63 }
64
firme_granule_mgmt_service_handler(firme_instance_e instance,uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)65 u_register_t firme_granule_mgmt_service_handler(firme_instance_e instance,
66 uint32_t smc_fid, uint64_t x1,
67 uint64_t x2, uint64_t x3,
68 uint64_t x4, void *cookie,
69 void *handle, uint64_t flags)
70 {
71 if (!is_feat_rme_supported()) {
72 SMC_RET1(handle, FIRME_NOT_SUPPORTED);
73 }
74
75 switch (smc_fid) {
76 case FIRME_GM_GPI_SET_FID:
77 /* Extract target GPI value from attributes in x3. */
78 uint8_t target_gpi = (x3 >> FIRME_GM_GPI_SET_TGT_GPI_SHIFT) &
79 FIRME_GM_GPI_SET_TGT_GPI_MASK;
80 /*
81 * Granule count is the number of granules to transition, and
82 * will be overwritten to contain the number of granules
83 * actually transitioned by gpt_transition_pas.
84 */
85 uint64_t granule_count = x2;
86 uint32_t ret = gpt_transition_pas(x1, &granule_count,
87 target_gpi,
88 caller_sec_state(flags));
89
90 switch (ret) {
91 case 0:
92 SMC_RET2(handle, FIRME_SUCCESS, granule_count);
93 case -EINVAL:
94 SMC_RET2(handle, FIRME_INVALID_PARAMETERS, 0);
95 case -EPERM:
96 SMC_RET2(handle, FIRME_DENIED, 0);
97 default:
98 SMC_RET2(handle, FIRME_NOT_SUPPORTED, 0);
99 }
100 break;
101 default:
102 ERROR("FIRME Granule Management Service FID 0x%X not implemented\n",
103 smc_fid);
104 SMC_RET1(handle, FIRME_NOT_SUPPORTED);
105 }
106 }
107