blob: 4250445184fdd6077f596a3cdd1ac1b9ca137f63 [file] [log] [blame]
Manish Pandey9ee6a8d2021-03-03 09:53:33 +00001/*
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -05002 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
Manish Pandey9ee6a8d2021-03-03 09:53:33 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <common/debug.h>
Madhukar Pappireddy3c287262021-08-05 14:39:24 -05008#include <drivers/arm/sp805.h>
Manish Pandey9ee6a8d2021-03-03 09:53:33 +00009#include <sp_helpers.h>
10#include <spm_helpers.h>
11
12#include "cactus_message_loop.h"
13#include "cactus_test_cmds.h"
14
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -070015#include <mmio.h>
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050016#include <platform.h>
17
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -060018/* Secure virtual interrupt that was last handled by Cactus SP. */
19extern uint32_t last_serviced_interrupt[PLATFORM_CORE_COUNT];
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060020static int flag_set;
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -070021static volatile bool test_espi_handled;
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060022
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -050023static void handle_sec_wdog_interrupt(void)
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060024{
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -050025 /*
26 * Interrupt triggered due to Trusted watchdog timer expiry.
27 * Clear the interrupt and stop the timer.
28 */
29 VERBOSE("Trusted WatchDog timer stopped\n");
30 sp805_twdog_stop();
31
32 /* Perform secure interrupt de-activation. */
33 spm_interrupt_deactivate(IRQ_TWDOG_INTID);
34}
35
36static void check_sec_wdog_interrupt_triggered(void)
37{
38 handle_sec_wdog_interrupt();
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060039 expect(flag_set, 0);
40 flag_set = 1;
41}
42
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000043CACTUS_CMD_HANDLER(sleep_cmd, CACTUS_SLEEP_CMD)
44{
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050045 uint64_t time_lapsed;
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000046 uint32_t sleep_time = cactus_get_sleep_time(*args);
47
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050048 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
49 sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000050
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050051 time_lapsed = sp_sleep_elapsed_time(sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000052
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050053 /* Lapsed time should be at least equal to sleep time. */
54 VERBOSE("Sleep complete: %llu\n", time_lapsed);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000055
56 return cactus_response(ffa_dir_msg_dest(*args),
57 ffa_dir_msg_source(*args),
58 time_lapsed);
59}
60
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050061CACTUS_CMD_HANDLER(sleep_fwd_cmd, CACTUS_FWD_SLEEP_CMD)
62{
Daniel Boulbyce386b12022-03-29 18:36:36 +010063 struct ffa_value ffa_ret;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050064 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
65 ffa_id_t fwd_dest = cactus_get_fwd_sleep_dest(*args);
66 uint32_t sleep_ms = cactus_get_sleep_time(*args);
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050067 bool hint_interrupted = cactus_get_fwd_sleep_interrupted_hint(*args);
68 bool fwd_dest_interrupted;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050069
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050070 VERBOSE("VM%x requested %x to sleep for value %u\n",
71 ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
72
73 ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
74
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050075 /*
76 * The target of the direct request could be pre-empted any number of
77 * times. Moreover, the target SP may or may not support managed exit.
78 * Hence, the target is allocated cpu cycles in this while loop.
79 */
80 while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
81 is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
82 0)) {
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050083 fwd_dest_interrupted = true;
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050084
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050085 if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
86 /* Received FFA_INTERRUPT in blocked state. */
87 VERBOSE("Processing FFA_INTERRUPT while"
88 " blocked on direct response\n");
89 unsigned int my_core_pos =
90 platform_get_core_pos(read_mpidr_el1());
91
92 ffa_ret = ffa_run(fwd_dest, my_core_pos);
93 } else {
94 /*
95 * Destination sent managed exit response. Allocate
96 * dummy cycles through direct request message to
97 * destination SP.
98 */
99 VERBOSE("SP%x: received Managed Exit as response\n",
100 vm_id);
Madhukar Pappireddy92d2e812022-09-19 13:48:13 -0500101 ffa_ret = cactus_resume_after_managed_exit(vm_id,
102 fwd_dest);
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500103 }
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -0500104 }
105
Madhukar Pappireddy4b293412022-09-12 11:39:20 -0500106 if (hint_interrupted && !fwd_dest_interrupted) {
107 ERROR("Forwaded destination of the sleep command was not"
108 " interrupted as anticipated\n");
109 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
110 CACTUS_ERROR_TEST);
111 }
112
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500113 if (!is_ffa_direct_response(ffa_ret)) {
114 ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
115 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
116 CACTUS_ERROR_FFA_CALL);
117 }
118
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500119 if (cactus_get_response(ffa_ret) < sleep_ms) {
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500120 ERROR("Request returned: %u ms!\n",
121 cactus_get_response(ffa_ret));
122 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
123 CACTUS_ERROR_TEST);
124
125 }
126
127 return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
128}
129
Manish Pandey9ee6a8d2021-03-03 09:53:33 +0000130CACTUS_CMD_HANDLER(interrupt_cmd, CACTUS_INTERRUPT_CMD)
131{
132 uint32_t int_id = cactus_get_interrupt_id(*args);
133 bool enable = cactus_get_interrupt_enable(*args);
134 enum interrupt_pin pin = cactus_get_interrupt_pin(*args);
135 int64_t ret;
136
137 ret = spm_interrupt_enable(int_id, enable, pin);
138 if (ret != 0) {
139 return cactus_error_resp(ffa_dir_msg_dest(*args),
140 ffa_dir_msg_source(*args),
141 CACTUS_ERROR_TEST);
142 }
143
144 return cactus_response(ffa_dir_msg_dest(*args),
145 ffa_dir_msg_source(*args),
146 CACTUS_SUCCESS);
147}
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500148
149CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
150{
151 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
152 ffa_id_t source = ffa_dir_msg_source(*args);
153
154 uint64_t time_ms = cactus_get_wdog_duration(*args);
155
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500156 sp_register_interrupt_handler(handle_sec_wdog_interrupt,
157 IRQ_TWDOG_INTID);
158
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500159 VERBOSE("Starting TWDOG: %llums\n", time_ms);
160 sp805_twdog_refresh();
161 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
162
163 return cactus_success_resp(vm_id, source, time_ms);
164}
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600165
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600166bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
167{
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500168 sp_register_interrupt_handler(check_sec_wdog_interrupt_triggered,
169 IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600170 *time_lapsed += sp_sleep_elapsed_time(sleep_time);
171
172 if (flag_set == 0) {
173 return false;
174 }
175
176 /* Reset the flag and unregister the handler. */
177 flag_set = 0;
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500178 sp_unregister_interrupt_handler(IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600179
180 return true;
181}
182
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600183CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
184{
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600185 uint64_t time_lapsed = 0;
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600186 uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
187 uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
188
189 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
190 sleep_time);
191
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600192 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
193 goto fail;
194 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600195
196 /* Lapsed time should be at least equal to sleep time. */
197 VERBOSE("Sleep complete: %llu\n", time_lapsed);
198
199 VERBOSE("Starting TWDOG: %llums\n", time_ms);
200 sp805_twdog_refresh();
201 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
202
203 VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
204 sleep_time);
205
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600206 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
207 goto fail;
208 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600209
210 /* Lapsed time should be at least equal to sleep time. */
211 VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
212
213 return cactus_response(ffa_dir_msg_dest(*args),
214 ffa_dir_msg_source(*args),
215 time_lapsed);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600216fail:
217 /* Test failed. */
218 ERROR("Watchdog interrupt not handled\n");
219 return cactus_error_resp(ffa_dir_msg_dest(*args),
220 ffa_dir_msg_source(*args),
221 CACTUS_ERROR_TEST);
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600222}
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -0600223
224CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
225{
226 unsigned int core_pos = get_current_core_id();
227
228 return cactus_response(ffa_dir_msg_dest(*args),
229 ffa_dir_msg_source(*args),
230 last_serviced_interrupt[core_pos]);
231}
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -0700232
233static void sec_interrupt_test_espi_handled(void)
234{
235 expect(test_espi_handled, false);
236 test_espi_handled = true;
237 NOTICE("Interrupt handler for test espi interrupt called\n");
238
239 /* Perform secure interrupt de-activation. */
240 spm_interrupt_deactivate(IRQ_ESPI_TEST_INTID);
241}
242
243CACTUS_CMD_HANDLER(trigger_espi_cmd, CACTUS_TRIGGER_ESPI_CMD)
244{
245 uint32_t espi_id = cactus_get_espi_id(*args);
246
247 /*
248 * The SiP function ID 0x82000100 must have been added to the SMC
249 * whitelist of the Cactus SP that invokes it.
250 */
251 smc_args plat_sip_call = {
252 .fid = 0x82000100,
253 .arg1 = espi_id,
254 };
255 smc_ret_values ret;
256
257 sp_register_interrupt_handler(sec_interrupt_test_espi_handled,
258 espi_id);
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100259
260 /*
261 * Call the low level assembler routine to make the SMC call bypassing
262 * tftf_smc, as tftf_smc will set SVE hint bit in SMC FID when CPU
263 * supports SVE and SVE traps are enabled.
264 *
265 * This can be changed to tftf_smc call once SPMC disregards SVE hint bit
266 * from function identification.
267 */
268 ret = asm_tftf_smc64(plat_sip_call.fid, plat_sip_call.arg1, 0, 0, 0,
269 0, 0, 0);
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -0700270
271 if (ret.ret0 == SMC_UNKNOWN) {
272 ERROR("SiP SMC call not supported\n");
273 return cactus_error_resp(ffa_dir_msg_dest(*args),
274 ffa_dir_msg_source(*args),
275 CACTUS_ERROR_TEST);
276 }
277
278 return cactus_response(ffa_dir_msg_dest(*args),
279 ffa_dir_msg_source(*args),
280 test_espi_handled ? 1 : 0);
281}