blob: efe2260171aa8f620efb2e6a622d3c7f19a587ce [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
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050015#include <platform.h>
16
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -060017/* Secure virtual interrupt that was last handled by Cactus SP. */
18extern uint32_t last_serviced_interrupt[PLATFORM_CORE_COUNT];
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060019static int flag_set;
20
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -050021static void handle_sec_wdog_interrupt(void)
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060022{
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -050023 /*
24 * Interrupt triggered due to Trusted watchdog timer expiry.
25 * Clear the interrupt and stop the timer.
26 */
27 VERBOSE("Trusted WatchDog timer stopped\n");
28 sp805_twdog_stop();
29
30 /* Perform secure interrupt de-activation. */
31 spm_interrupt_deactivate(IRQ_TWDOG_INTID);
32}
33
34static void check_sec_wdog_interrupt_triggered(void)
35{
36 handle_sec_wdog_interrupt();
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -060037 expect(flag_set, 0);
38 flag_set = 1;
39}
40
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000041CACTUS_CMD_HANDLER(sleep_cmd, CACTUS_SLEEP_CMD)
42{
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050043 uint64_t time_lapsed;
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000044 uint32_t sleep_time = cactus_get_sleep_time(*args);
45
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050046 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
47 sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000048
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050049 time_lapsed = sp_sleep_elapsed_time(sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000050
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050051 /* Lapsed time should be at least equal to sleep time. */
52 VERBOSE("Sleep complete: %llu\n", time_lapsed);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000053
54 return cactus_response(ffa_dir_msg_dest(*args),
55 ffa_dir_msg_source(*args),
56 time_lapsed);
57}
58
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050059CACTUS_CMD_HANDLER(sleep_fwd_cmd, CACTUS_FWD_SLEEP_CMD)
60{
Daniel Boulbyce386b12022-03-29 18:36:36 +010061 struct ffa_value ffa_ret;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050062 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
63 ffa_id_t fwd_dest = cactus_get_fwd_sleep_dest(*args);
64 uint32_t sleep_ms = cactus_get_sleep_time(*args);
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050065 bool hint_interrupted = cactus_get_fwd_sleep_interrupted_hint(*args);
66 bool fwd_dest_interrupted;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050067
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050068 VERBOSE("VM%x requested %x to sleep for value %u\n",
69 ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
70
71 ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
72
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050073 /*
74 * The target of the direct request could be pre-empted any number of
75 * times. Moreover, the target SP may or may not support managed exit.
76 * Hence, the target is allocated cpu cycles in this while loop.
77 */
78 while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
79 is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
80 0)) {
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050081 fwd_dest_interrupted = true;
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050082
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050083 if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
84 /* Received FFA_INTERRUPT in blocked state. */
85 VERBOSE("Processing FFA_INTERRUPT while"
86 " blocked on direct response\n");
87 unsigned int my_core_pos =
88 platform_get_core_pos(read_mpidr_el1());
89
90 ffa_ret = ffa_run(fwd_dest, my_core_pos);
91 } else {
92 /*
93 * Destination sent managed exit response. Allocate
94 * dummy cycles through direct request message to
95 * destination SP.
96 */
97 VERBOSE("SP%x: received Managed Exit as response\n",
98 vm_id);
Madhukar Pappireddy92d2e812022-09-19 13:48:13 -050099 ffa_ret = cactus_resume_after_managed_exit(vm_id,
100 fwd_dest);
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500101 }
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -0500102 }
103
Madhukar Pappireddy4b293412022-09-12 11:39:20 -0500104 if (hint_interrupted && !fwd_dest_interrupted) {
105 ERROR("Forwaded destination of the sleep command was not"
106 " interrupted as anticipated\n");
107 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
108 CACTUS_ERROR_TEST);
109 }
110
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500111 if (!is_ffa_direct_response(ffa_ret)) {
112 ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
113 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
114 CACTUS_ERROR_FFA_CALL);
115 }
116
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500117 if (cactus_get_response(ffa_ret) < sleep_ms) {
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500118 ERROR("Request returned: %u ms!\n",
119 cactus_get_response(ffa_ret));
120 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
121 CACTUS_ERROR_TEST);
122
123 }
124
125 return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
126}
127
Manish Pandey9ee6a8d2021-03-03 09:53:33 +0000128CACTUS_CMD_HANDLER(interrupt_cmd, CACTUS_INTERRUPT_CMD)
129{
130 uint32_t int_id = cactus_get_interrupt_id(*args);
131 bool enable = cactus_get_interrupt_enable(*args);
132 enum interrupt_pin pin = cactus_get_interrupt_pin(*args);
133 int64_t ret;
134
135 ret = spm_interrupt_enable(int_id, enable, pin);
136 if (ret != 0) {
137 return cactus_error_resp(ffa_dir_msg_dest(*args),
138 ffa_dir_msg_source(*args),
139 CACTUS_ERROR_TEST);
140 }
141
142 return cactus_response(ffa_dir_msg_dest(*args),
143 ffa_dir_msg_source(*args),
144 CACTUS_SUCCESS);
145}
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500146
147CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
148{
149 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
150 ffa_id_t source = ffa_dir_msg_source(*args);
151
152 uint64_t time_ms = cactus_get_wdog_duration(*args);
153
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500154 sp_register_interrupt_handler(handle_sec_wdog_interrupt,
155 IRQ_TWDOG_INTID);
156
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500157 VERBOSE("Starting TWDOG: %llums\n", time_ms);
158 sp805_twdog_refresh();
159 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
160
161 return cactus_success_resp(vm_id, source, time_ms);
162}
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600163
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600164bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
165{
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500166 sp_register_interrupt_handler(check_sec_wdog_interrupt_triggered,
167 IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600168 *time_lapsed += sp_sleep_elapsed_time(sleep_time);
169
170 if (flag_set == 0) {
171 return false;
172 }
173
174 /* Reset the flag and unregister the handler. */
175 flag_set = 0;
Madhukar Pappireddy4d1f1122023-03-16 17:54:24 -0500176 sp_unregister_interrupt_handler(IRQ_TWDOG_INTID);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600177
178 return true;
179}
180
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600181CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
182{
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600183 uint64_t time_lapsed = 0;
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600184 uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
185 uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
186
187 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
188 sleep_time);
189
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600190 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
191 goto fail;
192 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600193
194 /* Lapsed time should be at least equal to sleep time. */
195 VERBOSE("Sleep complete: %llu\n", time_lapsed);
196
197 VERBOSE("Starting TWDOG: %llums\n", time_ms);
198 sp805_twdog_refresh();
199 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
200
201 VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
202 sleep_time);
203
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600204 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
205 goto fail;
206 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600207
208 /* Lapsed time should be at least equal to sleep time. */
209 VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
210
211 return cactus_response(ffa_dir_msg_dest(*args),
212 ffa_dir_msg_source(*args),
213 time_lapsed);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600214fail:
215 /* Test failed. */
216 ERROR("Watchdog interrupt not handled\n");
217 return cactus_error_resp(ffa_dir_msg_dest(*args),
218 ffa_dir_msg_source(*args),
219 CACTUS_ERROR_TEST);
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600220}
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -0600221
222CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
223{
224 unsigned int core_pos = get_current_core_id();
225
226 return cactus_response(ffa_dir_msg_dest(*args),
227 ffa_dir_msg_source(*args),
228 last_serviced_interrupt[core_pos]);
229}