blob: c589119750a2b71eded83d0ea74d9299a3f57645 [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();
Karl Meakinc884d6b2024-04-16 14:01:10 +010039 EXPECT(flag_set, 0);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060040 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");
Olivier Deprez19626b42023-12-21 18:29:05 +010089
90 /* Get vCPU index for currently running vCPU. */
91 unsigned int my_core_pos = spm_get_my_core_pos();
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050092
93 ffa_ret = ffa_run(fwd_dest, my_core_pos);
94 } else {
95 /*
96 * Destination sent managed exit response. Allocate
97 * dummy cycles through direct request message to
98 * destination SP.
99 */
100 VERBOSE("SP%x: received Managed Exit as response\n",
101 vm_id);
Madhukar Pappireddy92d2e812022-09-19 13:48:13 -0500102 ffa_ret = cactus_resume_after_managed_exit(vm_id,
103 fwd_dest);
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500104 }
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -0500105 }
106
Madhukar Pappireddy4b293412022-09-12 11:39:20 -0500107 if (hint_interrupted && !fwd_dest_interrupted) {
108 ERROR("Forwaded destination of the sleep command was not"
109 " interrupted as anticipated\n");
110 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
111 CACTUS_ERROR_TEST);
112 }
113
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500114 if (!is_ffa_direct_response(ffa_ret)) {
115 ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
116 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
117 CACTUS_ERROR_FFA_CALL);
118 }
119
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500120 if (cactus_get_response(ffa_ret) < sleep_ms) {
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500121 ERROR("Request returned: %u ms!\n",
122 cactus_get_response(ffa_ret));
123 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
124 CACTUS_ERROR_TEST);
125
126 }
127
128 return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
129}
130
Manish Pandey9ee6a8d2021-03-03 09:53:33 +0000131CACTUS_CMD_HANDLER(interrupt_cmd, CACTUS_INTERRUPT_CMD)
132{
133 uint32_t int_id = cactus_get_interrupt_id(*args);
134 bool enable = cactus_get_interrupt_enable(*args);
135 enum interrupt_pin pin = cactus_get_interrupt_pin(*args);
136 int64_t ret;
137
138 ret = spm_interrupt_enable(int_id, enable, pin);
139 if (ret != 0) {
140 return cactus_error_resp(ffa_dir_msg_dest(*args),
141 ffa_dir_msg_source(*args),
142 CACTUS_ERROR_TEST);
143 }
144
145 return cactus_response(ffa_dir_msg_dest(*args),
146 ffa_dir_msg_source(*args),
147 CACTUS_SUCCESS);
148}
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500149
150CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
151{
152 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
153 ffa_id_t source = ffa_dir_msg_source(*args);
154
155 uint64_t time_ms = cactus_get_wdog_duration(*args);
156
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500157 sp_register_interrupt_handler(handle_sec_wdog_interrupt,
158 IRQ_TWDOG_INTID);
159
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500160 VERBOSE("Starting TWDOG: %llums\n", time_ms);
161 sp805_twdog_refresh();
162 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
163
164 return cactus_success_resp(vm_id, source, time_ms);
165}
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600166
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600167bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
168{
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500169 sp_register_interrupt_handler(check_sec_wdog_interrupt_triggered,
170 IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600171 *time_lapsed += sp_sleep_elapsed_time(sleep_time);
172
173 if (flag_set == 0) {
174 return false;
175 }
176
177 /* Reset the flag and unregister the handler. */
178 flag_set = 0;
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500179 sp_unregister_interrupt_handler(IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600180
181 return true;
182}
183
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600184CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
185{
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600186 uint64_t time_lapsed = 0;
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600187 uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
188 uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
189
190 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
191 sleep_time);
192
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600193 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
194 goto fail;
195 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600196
197 /* Lapsed time should be at least equal to sleep time. */
198 VERBOSE("Sleep complete: %llu\n", time_lapsed);
199
200 VERBOSE("Starting TWDOG: %llums\n", time_ms);
201 sp805_twdog_refresh();
202 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
203
204 VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
205 sleep_time);
206
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600207 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
208 goto fail;
209 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600210
211 /* Lapsed time should be at least equal to sleep time. */
212 VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
213
214 return cactus_response(ffa_dir_msg_dest(*args),
215 ffa_dir_msg_source(*args),
216 time_lapsed);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600217fail:
218 /* Test failed. */
219 ERROR("Watchdog interrupt not handled\n");
220 return cactus_error_resp(ffa_dir_msg_dest(*args),
221 ffa_dir_msg_source(*args),
222 CACTUS_ERROR_TEST);
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600223}
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -0600224
225CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
226{
227 unsigned int core_pos = get_current_core_id();
228
229 return cactus_response(ffa_dir_msg_dest(*args),
230 ffa_dir_msg_source(*args),
231 last_serviced_interrupt[core_pos]);
232}
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -0700233
234static void sec_interrupt_test_espi_handled(void)
235{
Karl Meakinc884d6b2024-04-16 14:01:10 +0100236 EXPECT(test_espi_handled, false);
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -0700237 test_espi_handled = true;
238 NOTICE("Interrupt handler for test espi interrupt called\n");
239
240 /* Perform secure interrupt de-activation. */
241 spm_interrupt_deactivate(IRQ_ESPI_TEST_INTID);
242}
243
244CACTUS_CMD_HANDLER(trigger_espi_cmd, CACTUS_TRIGGER_ESPI_CMD)
245{
246 uint32_t espi_id = cactus_get_espi_id(*args);
247
248 /*
249 * The SiP function ID 0x82000100 must have been added to the SMC
250 * whitelist of the Cactus SP that invokes it.
251 */
252 smc_args plat_sip_call = {
253 .fid = 0x82000100,
254 .arg1 = espi_id,
255 };
256 smc_ret_values ret;
257
258 sp_register_interrupt_handler(sec_interrupt_test_espi_handled,
259 espi_id);
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100260
261 /*
262 * Call the low level assembler routine to make the SMC call bypassing
263 * tftf_smc, as tftf_smc will set SVE hint bit in SMC FID when CPU
264 * supports SVE and SVE traps are enabled.
265 *
266 * This can be changed to tftf_smc call once SPMC disregards SVE hint bit
267 * from function identification.
268 */
269 ret = asm_tftf_smc64(plat_sip_call.fid, plat_sip_call.arg1, 0, 0, 0,
270 0, 0, 0);
Raghu Krishnamurthy9e267a02022-08-11 21:25:26 -0700271
272 if (ret.ret0 == SMC_UNKNOWN) {
273 ERROR("SiP SMC call not supported\n");
274 return cactus_error_resp(ffa_dir_msg_dest(*args),
275 ffa_dir_msg_source(*args),
276 CACTUS_ERROR_TEST);
277 }
278
279 return cactus_response(ffa_dir_msg_dest(*args),
280 ffa_dir_msg_source(*args),
281 test_espi_handled ? 1 : 0);
282}