blob: ff42ba986d689ce6e7c6c9854c712fd5e8858932 [file] [log] [blame]
Shruti Gupta5abab762024-11-27 04:57:53 +00001/*
2 * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7#include <stdio.h>
8#include <arch.h>
9#include <arch_features.h>
10#include <assert.h>
11#include <debug.h>
12
13#include <host_realm_helper.h>
Shruti Guptabd729192025-01-24 17:02:15 +000014#include <psci.h>
15#include <realm_psci.h>
Shruti Gupta91105082024-11-27 05:29:55 +000016#include <realm_psi.h>
Shruti Gupta5abab762024-11-27 04:57:53 +000017#include <realm_rsi.h>
18#include <sync.h>
19
Shruti Gupta91105082024-11-27 05:29:55 +000020static bool is_plane0;
21static unsigned int plane_num;
Shruti Gupta7d3b9992025-02-25 15:39:55 +000022static bool plane_init[MAX_PLANE_COUNT];
Shruti Gupta91105082024-11-27 05:29:55 +000023
24bool realm_is_plane0(void)
25{
26 return is_plane0;
27}
28
29unsigned int realm_get_my_plane_num(void)
30{
31 return plane_num;
32}
Shruti Gupta5abab762024-11-27 04:57:53 +000033
34void realm_plane_init(void)
35{
36 u_register_t ret;
37
38 ret = rsi_get_version(RSI_ABI_VERSION_VAL);
39 if (ret == RSI_ERROR_STATE) {
40 is_plane0 = false;
Shruti Gupta91105082024-11-27 05:29:55 +000041 plane_num = (unsigned int)psi_get_plane_id();
Shruti Gupta5abab762024-11-27 04:57:53 +000042 } else {
43 is_plane0 = true;
Shruti Gupta91105082024-11-27 05:29:55 +000044 plane_num = PRIMARY_PLANE_ID;
Shruti Gupta5abab762024-11-27 04:57:53 +000045 }
46}
47
48static void restore_plane_context(rsi_plane_run *run)
49{
50 for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
51 run->enter.gprs[i] = run->exit.gprs[i];
52 }
53
54 run->enter.pc = run->exit.elr;
55}
56
Shruti Gupta91105082024-11-27 05:29:55 +000057static u_register_t realm_exit_to_host_as_plane_n(enum host_call_cmd exit_code,
58 u_register_t plane_num)
59{
60 struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
61 smc_ret_values res = {};
62
63 assert(realm_is_p0());
64 host_cal.imm = exit_code;
65 host_cal.gprs[0] = plane_num;
66 host_cal.gprs[1] = read_mpidr_el1();
Arunachalam Ganapathy51135c82025-01-27 11:17:32 +000067 res = tftf_smc(&(smc_args) {SMC_RSI_HOST_CALL, (u_register_t)&host_cal,
Shruti Gupta91105082024-11-27 05:29:55 +000068 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
69 return res.ret0;
70}
71
Shruti Gupta5abab762024-11-27 04:57:53 +000072/* return true to re-enter PlaneN, false to exit to P0 */
Shruti Guptaa0736c32024-11-27 09:34:35 +000073u_register_t handle_plane_exit(u_register_t plane_index,
Shruti Gupta5abab762024-11-27 04:57:53 +000074 u_register_t perm_index,
75 rsi_plane_run *run)
76{
77 u_register_t ec = EC_BITS(run->exit.esr);
Shruti Gupta91105082024-11-27 05:29:55 +000078 u_register_t ret;
Shruti Gupta5abab762024-11-27 04:57:53 +000079
Shruti Guptaa0736c32024-11-27 09:34:35 +000080 if (((run->exit.esr & ISS_FSC_MASK) >= FSC_L0_PERM_FAULT) &&
81 ((run->exit.esr & ISS_FSC_MASK) <= FSC_L3_PERM_FAULT)) {
82
83 /* If Plane N exit is due to permission fault, change s2ap */
84 u_register_t base, new_base, response, ret;
85 u_register_t new_cookie = 0UL;
86
87 new_base = base = (run->exit.far & ~PAGE_SIZE_MASK);
88
89 VERBOSE("P0 set s2ap 0x%lx\n", base);
90 while (new_base != (base + PAGE_SIZE)) {
91
92 ret = rsi_mem_set_perm_index(new_base, base + PAGE_SIZE,
93 perm_index, new_cookie, &new_base,
94 &response, &new_cookie);
95
96 if (ret != RSI_SUCCESS || response == RSI_REJECT) {
97 ERROR("rsi_mem_set_perm_index failed 0x%lx\n", new_base);
98 return PSI_RETURN_TO_P0;
99 }
100 }
101
102 restore_plane_context(run);
103 return PSI_RETURN_TO_PN;
104 }
105
Shruti Gupta5abab762024-11-27 04:57:53 +0000106 /* Disallow SMC from Plane N */
107 if (ec == EC_AARCH64_SMC) {
Shruti Guptabd729192025-01-24 17:02:15 +0000108 u_register_t smc_id = run->exit.gprs[0];
109
Shruti Gupta5abab762024-11-27 04:57:53 +0000110 restore_plane_context(run);
Shruti Guptabd729192025-01-24 17:02:15 +0000111 switch (smc_id) {
112 case SMC_PSCI_CPU_ON_AARCH64:
113 assert(run->exit.gprs[1] < MAX_REC_COUNT);
114 assert(run->exit.gprs[1] != 0U);
115 /* Let P0 handle CPU ON */
116 return PSI_RETURN_TO_P0;
117 case SMC_PSCI_CPU_OFF:
118 realm_cpu_off();
119 /* Does not return. */
120 return PSI_RETURN_TO_PN;
121 case SMC_PSCI_FEATURES:
122 run->enter.gprs[0] = realm_psci_features(run->exit.gprs[1U]);
123 return PSI_RETURN_TO_PN;
124 case SMC_PSCI_AFFINITY_INFO:
125 run->enter.gprs[0] = realm_psci_affinity_info(run->exit.gprs[1U],
126 run->exit.gprs[2U]);
127 return PSI_RETURN_TO_PN;
128 default:
129 run->enter.gprs[0] = RSI_ERROR_STATE;
130 return PSI_RETURN_TO_PN;
131 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000132 }
Shruti Gupta91105082024-11-27 05:29:55 +0000133
134 /* Handle PSI HVC call from Plane N */
135 if (ec == EC_AARCH64_HVC) {
136 u_register_t hvc_id = run->exit.gprs[0];
137
138 restore_plane_context(run);
139 switch (hvc_id) {
140 case PSI_CALL_GET_SHARED_BUFF_CMD:
141 run->enter.gprs[0] = RSI_SUCCESS;
142 run->enter.gprs[1] = (u_register_t)realm_get_my_shared_structure();
Shruti Guptaa0736c32024-11-27 09:34:35 +0000143 return PSI_RETURN_TO_PN;
Shruti Gupta91105082024-11-27 05:29:55 +0000144 case PSI_CALL_GET_PLANE_ID_CMD:
145 run->enter.gprs[0] = RSI_SUCCESS;
146 run->enter.gprs[1] = plane_index;
Shruti Guptaa0736c32024-11-27 09:34:35 +0000147 return PSI_RETURN_TO_PN;
Shruti Gupta91105082024-11-27 05:29:55 +0000148 case PSI_CALL_EXIT_PRINT_CMD:
149 /* exit to host to flush buffer, then return to PN */
150 ret = realm_exit_to_host_as_plane_n(HOST_CALL_EXIT_PRINT_CMD, plane_index);
151 run->enter.gprs[0] = ret;
Shruti Guptaa0736c32024-11-27 09:34:35 +0000152 return PSI_RETURN_TO_PN;
Javier Almansa Sobrinoa1fe7382025-04-25 20:45:17 +0100153 case PSI_CALL_EXIT_SUCCESS_CMD:
154 case PSI_CALL_EXIT_FAILED_CMD:
155 run->exit.gprs[0] = hvc_id;
156 return PSI_RETURN_TO_P0;
Shruti Gupta91105082024-11-27 05:29:55 +0000157 case PSI_P0_CALL:
158 default:
Shruti Guptaa0736c32024-11-27 09:34:35 +0000159 return PSI_RETURN_TO_P0;
Shruti Gupta91105082024-11-27 05:29:55 +0000160 }
161 }
Shruti Guptaa0736c32024-11-27 09:34:35 +0000162 return PSI_RETURN_TO_P0;
Shruti Gupta5abab762024-11-27 04:57:53 +0000163}
164
Shruti Gupta41434682024-12-05 14:57:48 +0000165bool plane_common_init(u_register_t plane_index,
Shruti Gupta5abab762024-11-27 04:57:53 +0000166 u_register_t perm_index,
167 u_register_t base,
168 rsi_plane_run *run)
169{
170 u_register_t ret;
171
172 memset(run, 0, sizeof(rsi_plane_run));
173 run->enter.pc = base;
174
175 /* Perm init */
Shruti Gupta7d3b9992025-02-25 15:39:55 +0000176 if (plane_init[plane_index]) {
177 return true;
178 }
179
Shruti Gupta5abab762024-11-27 04:57:53 +0000180 ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
181 if (ret != RSI_SUCCESS) {
182 ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
183 return false;
184 }
Shruti Gupta7d3b9992025-02-25 15:39:55 +0000185 plane_init[plane_index] = true;
Shruti Gupta5abab762024-11-27 04:57:53 +0000186 return true;
187}
188
189bool realm_plane_enter(u_register_t plane_index,
190 u_register_t perm_index,
191 u_register_t base,
192 u_register_t flags,
193 rsi_plane_run *run)
194{
195 u_register_t ret;
Shruti Gupta5abab762024-11-27 04:57:53 +0000196
197 run->enter.flags = flags;
198
Shruti Guptaa0736c32024-11-27 09:34:35 +0000199 while (true) {
Shruti Gupta5abab762024-11-27 04:57:53 +0000200 ret = rsi_plane_enter(plane_index, (u_register_t)run);
201 if (ret != RSI_SUCCESS) {
202 ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
203 return false;
204 }
205
206 VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
207 run->exit.exit_reason,
208 run->exit.esr,
209 run->exit.hpfar,
210 run->exit.far);
211
Shruti Guptaa0736c32024-11-27 09:34:35 +0000212 ret = handle_plane_exit(plane_index, perm_index, run);
213
Javier Almansa Sobrinoa1fe7382025-04-25 20:45:17 +0100214 if (ret == PSI_RETURN_TO_P0) {
215 return !(run->exit.gprs[0] == PSI_CALL_EXIT_FAILED_CMD);
Shruti Guptaa0736c32024-11-27 09:34:35 +0000216 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000217 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000218}
219