blob: 13a5e59162ef7ef21bf45bef4731445baf7cce65 [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);
51
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050052 VERBOSE("VM%x requested %x to sleep for value %u\n",
53 ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
54
55 ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
56
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050057 /*
58 * The target of the direct request could be pre-empted any number of
59 * times. Moreover, the target SP may or may not support managed exit.
60 * Hence, the target is allocated cpu cycles in this while loop.
61 */
62 while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
63 is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
64 0)) {
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050065
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050066 if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
67 /* Received FFA_INTERRUPT in blocked state. */
68 VERBOSE("Processing FFA_INTERRUPT while"
69 " blocked on direct response\n");
70 unsigned int my_core_pos =
71 platform_get_core_pos(read_mpidr_el1());
72
73 ffa_ret = ffa_run(fwd_dest, my_core_pos);
74 } else {
75 /*
76 * Destination sent managed exit response. Allocate
77 * dummy cycles through direct request message to
78 * destination SP.
79 */
80 VERBOSE("SP%x: received Managed Exit as response\n",
81 vm_id);
82 ffa_ret = ffa_msg_send_direct_req64(vm_id, fwd_dest,
83 0, 0, 0, 0, 0);
84 }
Madhukar Pappireddycd183ef2021-08-05 15:34:07 -050085 }
86
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050087 if (!is_ffa_direct_response(ffa_ret)) {
88 ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
89 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
90 CACTUS_ERROR_FFA_CALL);
91 }
92
Madhukar Pappireddy9af4d272022-06-22 17:23:42 -050093 if (cactus_get_response(ffa_ret) < sleep_ms) {
Madhukar Pappireddyb6402592021-08-20 13:13:49 -050094 ERROR("Request returned: %u ms!\n",
95 cactus_get_response(ffa_ret));
96 return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
97 CACTUS_ERROR_TEST);
98
99 }
100
101 return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
102}
103
Manish Pandey9ee6a8d2021-03-03 09:53:33 +0000104CACTUS_CMD_HANDLER(interrupt_cmd, CACTUS_INTERRUPT_CMD)
105{
106 uint32_t int_id = cactus_get_interrupt_id(*args);
107 bool enable = cactus_get_interrupt_enable(*args);
108 enum interrupt_pin pin = cactus_get_interrupt_pin(*args);
109 int64_t ret;
110
111 ret = spm_interrupt_enable(int_id, enable, pin);
112 if (ret != 0) {
113 return cactus_error_resp(ffa_dir_msg_dest(*args),
114 ffa_dir_msg_source(*args),
115 CACTUS_ERROR_TEST);
116 }
117
118 return cactus_response(ffa_dir_msg_dest(*args),
119 ffa_dir_msg_source(*args),
120 CACTUS_SUCCESS);
121}
Madhukar Pappireddy3c287262021-08-05 14:39:24 -0500122
123CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
124{
125 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
126 ffa_id_t source = ffa_dir_msg_source(*args);
127
128 uint64_t time_ms = cactus_get_wdog_duration(*args);
129
130 VERBOSE("Starting TWDOG: %llums\n", time_ms);
131 sp805_twdog_refresh();
132 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
133
134 return cactus_success_resp(vm_id, source, time_ms);
135}
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600136
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600137bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
138{
139 sp_register_interrupt_tail_end_handler(sec_wdog_interrupt_handled,
140 IRQ_TWDOG_INTID);
141 *time_lapsed += sp_sleep_elapsed_time(sleep_time);
142
143 if (flag_set == 0) {
144 return false;
145 }
146
147 /* Reset the flag and unregister the handler. */
148 flag_set = 0;
149 sp_unregister_interrupt_tail_end_handler(IRQ_TWDOG_INTID);
150
151 return true;
152}
153
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600154CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
155{
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600156 uint64_t time_lapsed = 0;
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600157 uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
158 uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
159
160 VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
161 sleep_time);
162
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600163 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
164 goto fail;
165 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600166
167 /* Lapsed time should be at least equal to sleep time. */
168 VERBOSE("Sleep complete: %llu\n", time_lapsed);
169
170 VERBOSE("Starting TWDOG: %llums\n", time_ms);
171 sp805_twdog_refresh();
172 sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
173
174 VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
175 sleep_time);
176
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600177 if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
178 goto fail;
179 }
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600180
181 /* Lapsed time should be at least equal to sleep time. */
182 VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
183
184 return cactus_response(ffa_dir_msg_dest(*args),
185 ffa_dir_msg_source(*args),
186 time_lapsed);
Madhukar Pappireddyca8264c2022-01-28 17:14:21 -0600187fail:
188 /* Test failed. */
189 ERROR("Watchdog interrupt not handled\n");
190 return cactus_error_resp(ffa_dir_msg_dest(*args),
191 ffa_dir_msg_source(*args),
192 CACTUS_ERROR_TEST);
Madhukar Pappireddy407befc2021-12-17 11:06:17 -0600193}
Madhukar Pappireddyf4c8e8d2022-02-15 15:52:53 -0600194
195CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
196{
197 unsigned int core_pos = get_current_core_id();
198
199 return cactus_response(ffa_dir_msg_dest(*args),
200 ffa_dir_msg_source(*args),
201 last_serviced_interrupt[core_pos]);
202}