blob: 7f3de0c1569bc109f38296fa8dc070547f0f1d49 [file] [log] [blame]
Manish Pandey9ee6a8d2021-03-03 09:53:33 +00001/*
Madhukar Pappireddy407befc2021-12-17 11:06:17 -06002 * Copyright (c) 2021-2022, 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
21static void sec_wdog_interrupt_handled(void)
22{
23 expect(flag_set, 0);
24 flag_set = 1;
25}
26
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000027CACTUS_CMD_HANDLER(sleep_cmd, CACTUS_SLEEP_CMD)
28{
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050029 uint64_t time_lapsed;
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000030 uint32_t sleep_time = cactus_get_sleep_time(*args);
31
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050032 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
33 sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000034
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050035 time_lapsed = sp_sleep_elapsed_time(sleep_time);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000036
Madhukar Pappireddya09d5f72021-10-26 14:50:52 -050037 /* Lapsed time should be at least equal to sleep time. */
38 VERBOSE("Sleep complete: %llu\n", time_lapsed);
Manish Pandey9ee6a8d2021-03-03 09:53:33 +000039
40 return cactus_response(ffa_dir_msg_dest(*args),
41 ffa_dir_msg_source(*args),
42 time_lapsed);
43}
44
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050045CACTUS_CMD_HANDLER(sleep_fwd_cmd, CACTUS_FWD_SLEEP_CMD)
46{
Daniel Boulbyce386b12022-03-29 18:36:36 +010047 struct ffa_value ffa_ret;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050048 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
49 ffa_id_t fwd_dest = cactus_get_fwd_sleep_dest(*args);
50 uint32_t sleep_ms = cactus_get_sleep_time(*args);
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050051 bool hint_interrupted = cactus_get_fwd_sleep_interrupted_hint(*args);
52 bool fwd_dest_interrupted;
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050053
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050054 VERBOSE("VM%x requested %x to sleep for value %u\n",
55 ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
56
57 ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
58
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050059 /*
60 * The target of the direct request could be pre-empted any number of
61 * times. Moreover, the target SP may or may not support managed exit.
62 * Hence, the target is allocated cpu cycles in this while loop.
63 */
64 while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
65 is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
66 0)) {
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050067 fwd_dest_interrupted = true;
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050068
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050069 if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
70 /* Received FFA_INTERRUPT in blocked state. */
71 VERBOSE("Processing FFA_INTERRUPT while"
72 " blocked on direct response\n");
73 unsigned int my_core_pos =
74 platform_get_core_pos(read_mpidr_el1());
75
76 ffa_ret = ffa_run(fwd_dest, my_core_pos);
77 } else {
78 /*
79 * Destination sent managed exit response. Allocate
80 * dummy cycles through direct request message to
81 * destination SP.
82 */
83 VERBOSE("SP%x: received Managed Exit as response\n",
84 vm_id);
Madhukar Pappireddy92d2e812022-09-19 13:48:13 -050085 ffa_ret = cactus_resume_after_managed_exit(vm_id,
86 fwd_dest);
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050087 }
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050088 }
89
Madhukar Pappireddy4b293412022-09-12 11:39:20 -050090 if (hint_interrupted && !fwd_dest_interrupted) {
91 ERROR("Forwaded destination of the sleep command was not"
92 " interrupted as anticipated\n");
93 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
94 CACTUS_ERROR_TEST);
95 }
96
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050097 if (!is_ffa_direct_response(ffa_ret)) {
98 ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
99 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
100 CACTUS_ERROR_FFA_CALL);
101 }
102
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -0500103 if (cactus_get_response(ffa_ret) < sleep_ms) {
Madhukar Pappireddyb6402592021-08-20 13:13:49 -0500104 ERROR("Request returned: %u ms!\n",
105 cactus_get_response(ffa_ret));
106 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
107 CACTUS_ERROR_TEST);
108
109 }
110
111 return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
112}
113
Manish Pandey9ee6a8d2021-03-03 09:53:33 +0000114CACTUS_CMD_HANDLER(interrupt_cmd, CACTUS_INTERRUPT_CMD)
115{
116 uint32_t int_id = cactus_get_interrupt_id(*args);
117 bool enable = cactus_get_interrupt_enable(*args);
118 enum interrupt_pin pin = cactus_get_interrupt_pin(*args);
119 int64_t ret;
120
121 ret = spm_interrupt_enable(int_id, enable, pin);
122 if (ret != 0) {
123 return cactus_error_resp(ffa_dir_msg_dest(*args),
124 ffa_dir_msg_source(*args),
125 CACTUS_ERROR_TEST);
126 }
127
128 return cactus_response(ffa_dir_msg_dest(*args),
129 ffa_dir_msg_source(*args),
130 CACTUS_SUCCESS);
131}
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500132
133CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
134{
135 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
136 ffa_id_t source = ffa_dir_msg_source(*args);
137
138 uint64_t time_ms = cactus_get_wdog_duration(*args);
139
140 VERBOSE("Starting TWDOG: %llums\n", time_ms);
141 sp805_twdog_refresh();
142 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
143
144 return cactus_success_resp(vm_id, source, time_ms);
145}
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600146
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600147bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
148{
149 sp_register_interrupt_tail_end_handler(sec_wdog_interrupt_handled,
150 IRQ_TWDOG_INTID);
151 *time_lapsed += sp_sleep_elapsed_time(sleep_time);
152
153 if (flag_set == 0) {
154 return false;
155 }
156
157 /* Reset the flag and unregister the handler. */
158 flag_set = 0;
159 sp_unregister_interrupt_tail_end_handler(IRQ_TWDOG_INTID);
160
161 return true;
162}
163
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600164CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
165{
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600166 uint64_t time_lapsed = 0;
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600167 uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
168 uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
169
170 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
171 sleep_time);
172
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600173 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
174 goto fail;
175 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600176
177 /* Lapsed time should be at least equal to sleep time. */
178 VERBOSE("Sleep complete: %llu\n", time_lapsed);
179
180 VERBOSE("Starting TWDOG: %llums\n", time_ms);
181 sp805_twdog_refresh();
182 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
183
184 VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
185 sleep_time);
186
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600187 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
188 goto fail;
189 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600190
191 /* Lapsed time should be at least equal to sleep time. */
192 VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
193
194 return cactus_response(ffa_dir_msg_dest(*args),
195 ffa_dir_msg_source(*args),
196 time_lapsed);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600197fail:
198 /* Test failed. */
199 ERROR("Watchdog interrupt not handled\n");
200 return cactus_error_resp(ffa_dir_msg_dest(*args),
201 ffa_dir_msg_source(*args),
202 CACTUS_ERROR_TEST);
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600203}
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -0600204
205CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
206{
207 unsigned int core_pos = get_current_core_id();
208
209 return cactus_response(ffa_dir_msg_dest(*args),
210 ffa_dir_msg_source(*args),
211 last_serviced_interrupt[core_pos]);
212}