blob: 7affc156ff81f0c87bb74ac2c0c92fd224fb4472 [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 Gupta91105082024-11-27 05:29:55 +000014#include <realm_psi.h>
Shruti Gupta5abab762024-11-27 04:57:53 +000015#include <realm_rsi.h>
16#include <sync.h>
17
Shruti Gupta91105082024-11-27 05:29:55 +000018static bool is_plane0;
19static unsigned int plane_num;
20
21bool realm_is_plane0(void)
22{
23 return is_plane0;
24}
25
26unsigned int realm_get_my_plane_num(void)
27{
28 return plane_num;
29}
Shruti Gupta5abab762024-11-27 04:57:53 +000030
31void realm_plane_init(void)
32{
33 u_register_t ret;
34
35 ret = rsi_get_version(RSI_ABI_VERSION_VAL);
36 if (ret == RSI_ERROR_STATE) {
37 is_plane0 = false;
Shruti Gupta91105082024-11-27 05:29:55 +000038 plane_num = (unsigned int)psi_get_plane_id();
Shruti Gupta5abab762024-11-27 04:57:53 +000039 } else {
40 is_plane0 = true;
Shruti Gupta91105082024-11-27 05:29:55 +000041 plane_num = PRIMARY_PLANE_ID;
Shruti Gupta5abab762024-11-27 04:57:53 +000042 }
43}
44
45static void restore_plane_context(rsi_plane_run *run)
46{
47 for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
48 run->enter.gprs[i] = run->exit.gprs[i];
49 }
50
51 run->enter.pc = run->exit.elr;
52}
53
Shruti Gupta91105082024-11-27 05:29:55 +000054static u_register_t realm_exit_to_host_as_plane_n(enum host_call_cmd exit_code,
55 u_register_t plane_num)
56{
57 struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
58 smc_ret_values res = {};
59
60 assert(realm_is_p0());
61 host_cal.imm = exit_code;
62 host_cal.gprs[0] = plane_num;
63 host_cal.gprs[1] = read_mpidr_el1();
64 res = tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
65 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
66 return res.ret0;
67}
68
Shruti Gupta5abab762024-11-27 04:57:53 +000069/* return true to re-enter PlaneN, false to exit to P0 */
70static bool handle_plane_exit(u_register_t plane_index,
71 u_register_t perm_index,
72 rsi_plane_run *run)
73{
74 u_register_t ec = EC_BITS(run->exit.esr);
Shruti Gupta91105082024-11-27 05:29:55 +000075 u_register_t ret;
Shruti Gupta5abab762024-11-27 04:57:53 +000076
77 /* Disallow SMC from Plane N */
78 if (ec == EC_AARCH64_SMC) {
79 restore_plane_context(run);
80 run->enter.gprs[0] = RSI_ERROR_STATE;
81 return true;
82 }
Shruti Gupta91105082024-11-27 05:29:55 +000083
84 /* Handle PSI HVC call from Plane N */
85 if (ec == EC_AARCH64_HVC) {
86 u_register_t hvc_id = run->exit.gprs[0];
87
88 restore_plane_context(run);
89 switch (hvc_id) {
90 case PSI_CALL_GET_SHARED_BUFF_CMD:
91 run->enter.gprs[0] = RSI_SUCCESS;
92 run->enter.gprs[1] = (u_register_t)realm_get_my_shared_structure();
93 return true;
94 case PSI_CALL_GET_PLANE_ID_CMD:
95 run->enter.gprs[0] = RSI_SUCCESS;
96 run->enter.gprs[1] = plane_index;
97 return true;
98 case PSI_CALL_EXIT_PRINT_CMD:
99 /* exit to host to flush buffer, then return to PN */
100 ret = realm_exit_to_host_as_plane_n(HOST_CALL_EXIT_PRINT_CMD, plane_index);
101 run->enter.gprs[0] = ret;
102 return true;
103 case PSI_P0_CALL:
104 default:
105 return false;
106 }
107 }
Shruti Gupta5abab762024-11-27 04:57:53 +0000108 return false;
109}
110
111static bool plane_common_init(u_register_t plane_index,
112 u_register_t perm_index,
113 u_register_t base,
114 rsi_plane_run *run)
115{
116 u_register_t ret;
117
118 memset(run, 0, sizeof(rsi_plane_run));
119 run->enter.pc = base;
120
121 /* Perm init */
122 ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
123 if (ret != RSI_SUCCESS) {
124 ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
125 return false;
126 }
127 return true;
128}
129
130bool realm_plane_enter(u_register_t plane_index,
131 u_register_t perm_index,
132 u_register_t base,
133 u_register_t flags,
134 rsi_plane_run *run)
135{
136 u_register_t ret;
137 bool ret1;
138
139 ret1 = plane_common_init(plane_index, perm_index, base, run);
140 if (!ret1) {
141 return ret1;
142 }
143
144 run->enter.flags = flags;
145
146 while (ret1) {
147 ret = rsi_plane_enter(plane_index, (u_register_t)run);
148 if (ret != RSI_SUCCESS) {
149 ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
150 return false;
151 }
152
153 VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
154 run->exit.exit_reason,
155 run->exit.esr,
156 run->exit.hpfar,
157 run->exit.far);
158
159 ret1 = handle_plane_exit(plane_index, perm_index, run);
160 }
161 return true;
162}
163