blob: 3b79afff6dcb42797d5ced68d1bef2b361e2d222 [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;
22
23bool realm_is_plane0(void)
24{
25 return is_plane0;
26}
27
28unsigned int realm_get_my_plane_num(void)
29{
30 return plane_num;
31}
Shruti Gupta5abab762024-11-27 04:57:53 +000032
33void realm_plane_init(void)
34{
35 u_register_t ret;
36
37 ret = rsi_get_version(RSI_ABI_VERSION_VAL);
38 if (ret == RSI_ERROR_STATE) {
39 is_plane0 = false;
Shruti Gupta91105082024-11-27 05:29:55 +000040 plane_num = (unsigned int)psi_get_plane_id();
Shruti Gupta5abab762024-11-27 04:57:53 +000041 } else {
42 is_plane0 = true;
Shruti Gupta91105082024-11-27 05:29:55 +000043 plane_num = PRIMARY_PLANE_ID;
Shruti Gupta5abab762024-11-27 04:57:53 +000044 }
45}
46
47static void restore_plane_context(rsi_plane_run *run)
48{
49 for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
50 run->enter.gprs[i] = run->exit.gprs[i];
51 }
52
53 run->enter.pc = run->exit.elr;
54}
55
Shruti Gupta91105082024-11-27 05:29:55 +000056static u_register_t realm_exit_to_host_as_plane_n(enum host_call_cmd exit_code,
57 u_register_t plane_num)
58{
59 struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
60 smc_ret_values res = {};
61
62 assert(realm_is_p0());
63 host_cal.imm = exit_code;
64 host_cal.gprs[0] = plane_num;
65 host_cal.gprs[1] = read_mpidr_el1();
66 res = tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
67 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
68 return res.ret0;
69}
70
Shruti Gupta5abab762024-11-27 04:57:53 +000071/* return true to re-enter PlaneN, false to exit to P0 */
Shruti Guptaa0736c32024-11-27 09:34:35 +000072u_register_t handle_plane_exit(u_register_t plane_index,
Shruti Gupta5abab762024-11-27 04:57:53 +000073 u_register_t perm_index,
74 rsi_plane_run *run)
75{
76 u_register_t ec = EC_BITS(run->exit.esr);
Shruti Gupta91105082024-11-27 05:29:55 +000077 u_register_t ret;
Shruti Gupta5abab762024-11-27 04:57:53 +000078
Shruti Guptaa0736c32024-11-27 09:34:35 +000079 if (((run->exit.esr & ISS_FSC_MASK) >= FSC_L0_PERM_FAULT) &&
80 ((run->exit.esr & ISS_FSC_MASK) <= FSC_L3_PERM_FAULT)) {
81
82 /* If Plane N exit is due to permission fault, change s2ap */
83 u_register_t base, new_base, response, ret;
84 u_register_t new_cookie = 0UL;
85
86 new_base = base = (run->exit.far & ~PAGE_SIZE_MASK);
87
88 VERBOSE("P0 set s2ap 0x%lx\n", base);
89 while (new_base != (base + PAGE_SIZE)) {
90
91 ret = rsi_mem_set_perm_index(new_base, base + PAGE_SIZE,
92 perm_index, new_cookie, &new_base,
93 &response, &new_cookie);
94
95 if (ret != RSI_SUCCESS || response == RSI_REJECT) {
96 ERROR("rsi_mem_set_perm_index failed 0x%lx\n", new_base);
97 return PSI_RETURN_TO_P0;
98 }
99 }
100
101 restore_plane_context(run);
102 return PSI_RETURN_TO_PN;
103 }
104
Shruti Gupta5abab762024-11-27 04:57:53 +0000105 /* Disallow SMC from Plane N */
106 if (ec == EC_AARCH64_SMC) {
Shruti Guptabd729192025-01-24 17:02:15 +0000107 u_register_t smc_id = run->exit.gprs[0];
108
Shruti Gupta5abab762024-11-27 04:57:53 +0000109 restore_plane_context(run);
Shruti Guptabd729192025-01-24 17:02:15 +0000110 switch (smc_id) {
111 case SMC_PSCI_CPU_ON_AARCH64:
112 assert(run->exit.gprs[1] < MAX_REC_COUNT);
113 assert(run->exit.gprs[1] != 0U);
114 /* Let P0 handle CPU ON */
115 return PSI_RETURN_TO_P0;
116 case SMC_PSCI_CPU_OFF:
117 realm_cpu_off();
118 /* Does not return. */
119 return PSI_RETURN_TO_PN;
120 case SMC_PSCI_FEATURES:
121 run->enter.gprs[0] = realm_psci_features(run->exit.gprs[1U]);
122 return PSI_RETURN_TO_PN;
123 case SMC_PSCI_AFFINITY_INFO:
124 run->enter.gprs[0] = realm_psci_affinity_info(run->exit.gprs[1U],
125 run->exit.gprs[2U]);
126 return PSI_RETURN_TO_PN;
127 default:
128 run->enter.gprs[0] = RSI_ERROR_STATE;
129 return PSI_RETURN_TO_PN;
130 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000131 }
Shruti Gupta91105082024-11-27 05:29:55 +0000132
133 /* Handle PSI HVC call from Plane N */
134 if (ec == EC_AARCH64_HVC) {
135 u_register_t hvc_id = run->exit.gprs[0];
136
137 restore_plane_context(run);
138 switch (hvc_id) {
139 case PSI_CALL_GET_SHARED_BUFF_CMD:
140 run->enter.gprs[0] = RSI_SUCCESS;
141 run->enter.gprs[1] = (u_register_t)realm_get_my_shared_structure();
Shruti Guptaa0736c32024-11-27 09:34:35 +0000142 return PSI_RETURN_TO_PN;
Shruti Gupta91105082024-11-27 05:29:55 +0000143 case PSI_CALL_GET_PLANE_ID_CMD:
144 run->enter.gprs[0] = RSI_SUCCESS;
145 run->enter.gprs[1] = plane_index;
Shruti Guptaa0736c32024-11-27 09:34:35 +0000146 return PSI_RETURN_TO_PN;
Shruti Gupta91105082024-11-27 05:29:55 +0000147 case PSI_CALL_EXIT_PRINT_CMD:
148 /* exit to host to flush buffer, then return to PN */
149 ret = realm_exit_to_host_as_plane_n(HOST_CALL_EXIT_PRINT_CMD, plane_index);
150 run->enter.gprs[0] = ret;
Shruti Guptaa0736c32024-11-27 09:34:35 +0000151 return PSI_RETURN_TO_PN;
Shruti Gupta91105082024-11-27 05:29:55 +0000152 case PSI_P0_CALL:
153 default:
Shruti Guptaa0736c32024-11-27 09:34:35 +0000154 return PSI_RETURN_TO_P0;
Shruti Gupta91105082024-11-27 05:29:55 +0000155 }
156 }
Shruti Guptaa0736c32024-11-27 09:34:35 +0000157 return PSI_RETURN_TO_P0;
Shruti Gupta5abab762024-11-27 04:57:53 +0000158}
159
Shruti Gupta41434682024-12-05 14:57:48 +0000160bool plane_common_init(u_register_t plane_index,
Shruti Gupta5abab762024-11-27 04:57:53 +0000161 u_register_t perm_index,
162 u_register_t base,
163 rsi_plane_run *run)
164{
165 u_register_t ret;
166
167 memset(run, 0, sizeof(rsi_plane_run));
168 run->enter.pc = base;
169
170 /* Perm init */
171 ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
172 if (ret != RSI_SUCCESS) {
173 ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
174 return false;
175 }
176 return true;
177}
178
179bool realm_plane_enter(u_register_t plane_index,
180 u_register_t perm_index,
181 u_register_t base,
182 u_register_t flags,
183 rsi_plane_run *run)
184{
185 u_register_t ret;
Shruti Gupta5abab762024-11-27 04:57:53 +0000186
187 run->enter.flags = flags;
188
Shruti Guptaa0736c32024-11-27 09:34:35 +0000189 while (true) {
Shruti Gupta5abab762024-11-27 04:57:53 +0000190 ret = rsi_plane_enter(plane_index, (u_register_t)run);
191 if (ret != RSI_SUCCESS) {
192 ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
193 return false;
194 }
195
196 VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
197 run->exit.exit_reason,
198 run->exit.esr,
199 run->exit.hpfar,
200 run->exit.far);
201
Shruti Guptaa0736c32024-11-27 09:34:35 +0000202 ret = handle_plane_exit(plane_index, perm_index, run);
203
204 if (ret != PSI_RETURN_TO_PN) {
205 return true;
206 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000207 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000208}
209