tsp_ffa_main.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <inttypes.h>
  8. #include <stdint.h>
  9. #include "../../services/std_svc/spm/el3_spmc/spmc.h"
  10. #include "../../services/std_svc/spm/el3_spmc/spmc_shared_mem.h"
  11. #include <arch_features.h>
  12. #include <arch_helpers.h>
  13. #include <bl32/tsp/tsp.h>
  14. #include <common/bl_common.h>
  15. #include <common/build_message.h>
  16. #include <common/debug.h>
  17. #include "ffa_helpers.h"
  18. #include <lib/psci/psci.h>
  19. #include <lib/spinlock.h>
  20. #include <lib/xlat_tables/xlat_tables_defs.h>
  21. #include <lib/xlat_tables/xlat_tables_v2.h>
  22. #include <plat/common/platform.h>
  23. #include <platform_tsp.h>
  24. #include <services/ffa_svc.h>
  25. #include "tsp_private.h"
  26. #include <platform_def.h>
  27. static ffa_endpoint_id16_t tsp_id, spmc_id;
  28. uint8_t mem_region_buffer[4096 * 2] __aligned(PAGE_SIZE);
  29. /* Partition Mailbox. */
  30. static uint8_t send_page[PAGE_SIZE] __aligned(PAGE_SIZE);
  31. static uint8_t recv_page[PAGE_SIZE] __aligned(PAGE_SIZE);
  32. /*
  33. * Declare a global mailbox for use within the TSP.
  34. * This will be initialized appropriately when the buffers
  35. * are mapped with the SPMC.
  36. */
  37. static struct mailbox mailbox;
  38. /*******************************************************************************
  39. * This enum is used to handle test cases driven from the FF-A Test Driver.
  40. ******************************************************************************/
  41. /* Keep in Sync with FF-A Test Driver. */
  42. enum message_t {
  43. /* Partition Only Messages. */
  44. FF_A_RELAY_MESSAGE = 0,
  45. /* Basic Functionality. */
  46. FF_A_ECHO_MESSAGE,
  47. FF_A_RELAY_MESSAGE_EL3,
  48. /* Memory Sharing. */
  49. FF_A_MEMORY_SHARE,
  50. FF_A_MEMORY_SHARE_FRAGMENTED,
  51. FF_A_MEMORY_LEND,
  52. FF_A_MEMORY_LEND_FRAGMENTED,
  53. FF_A_MEMORY_SHARE_MULTI_ENDPOINT,
  54. FF_A_MEMORY_LEND_MULTI_ENDPOINT,
  55. LAST,
  56. FF_A_RUN_ALL = 255,
  57. FF_A_OP_MAX = 256
  58. };
  59. #if SPMC_AT_EL3
  60. extern void tsp_cpu_on_entry(void);
  61. #endif
  62. /*******************************************************************************
  63. * Test Functions.
  64. ******************************************************************************/
  65. /*******************************************************************************
  66. * Enable the TSP to forward the received message to another partition and ask
  67. * it to echo the value back in order to validate direct messages functionality.
  68. ******************************************************************************/
  69. static int ffa_test_relay(uint64_t arg0,
  70. uint64_t arg1,
  71. uint64_t arg2,
  72. uint64_t arg3,
  73. uint64_t arg4,
  74. uint64_t arg5,
  75. uint64_t arg6,
  76. uint64_t arg7)
  77. {
  78. smc_args_t ffa_forward_result;
  79. ffa_endpoint_id16_t receiver = arg5;
  80. ffa_forward_result = ffa_msg_send_direct_req(tsp_id,
  81. receiver,
  82. FF_A_ECHO_MESSAGE, arg4,
  83. 0, 0, 0);
  84. return ffa_forward_result._regs[3];
  85. }
  86. /*******************************************************************************
  87. * This function handles memory management tests, currently share and lend.
  88. * This test supports the use of FRAG_RX to use memory descriptors that do not
  89. * fit in a single 4KB buffer.
  90. ******************************************************************************/
  91. static int test_memory_send(ffa_endpoint_id16_t sender, uint64_t handle,
  92. ffa_mtd_flag32_t flags, bool multi_endpoint)
  93. {
  94. struct ffa_mtd *m;
  95. struct ffa_emad_v1_0 *receivers;
  96. struct ffa_comp_mrd *composite;
  97. int ret, status = 0;
  98. unsigned int mem_attrs;
  99. char *ptr;
  100. ffa_endpoint_id16_t source = sender;
  101. uint32_t total_length, recv_length = 0;
  102. /*
  103. * In the case that we're testing multiple endpoints choose a partition
  104. * ID that resides in the normal world so the SPMC won't detect it as
  105. * invalid.
  106. * TODO: Should get endpoint receiver id and flag as input from NWd.
  107. */
  108. uint32_t receiver_count = multi_endpoint ? 2 : 1;
  109. ffa_endpoint_id16_t test_receivers[2] = { tsp_id, 0x10 };
  110. /* Ensure that the sender ID resides in the normal world. */
  111. if (ffa_is_secure_world_id(sender)) {
  112. ERROR("Invalid sender ID 0x%x.\n", sender);
  113. return FFA_ERROR_DENIED;
  114. }
  115. if (!memory_retrieve(&mailbox, &m, handle, source, test_receivers,
  116. receiver_count, flags, &recv_length,
  117. &total_length)) {
  118. return FFA_ERROR_INVALID_PARAMETER;
  119. }
  120. receivers = (struct ffa_emad_v1_0 *)
  121. ((uint8_t *) m + m->emad_offset);
  122. while (total_length != recv_length) {
  123. smc_args_t ffa_return;
  124. uint32_t frag_length;
  125. ffa_return = ffa_mem_frag_rx(handle, recv_length);
  126. if (ffa_return._regs[0] == FFA_ERROR) {
  127. WARN("TSP: failed to resume mem with handle %lx\n",
  128. handle);
  129. return ffa_return._regs[2];
  130. }
  131. frag_length = ffa_return._regs[3];
  132. /* Validate frag_length is less than total_length and mailbox size. */
  133. if (frag_length > total_length ||
  134. frag_length > (mailbox.rxtx_page_count * PAGE_SIZE)) {
  135. ERROR("Invalid parameters!\n");
  136. return FFA_ERROR_INVALID_PARAMETER;
  137. }
  138. /* Validate frag_length is less than remaining mem_region_buffer size. */
  139. if (frag_length + recv_length >= REGION_BUF_SIZE) {
  140. ERROR("Out of memory!\n");
  141. return FFA_ERROR_INVALID_PARAMETER;
  142. }
  143. memcpy(&mem_region_buffer[recv_length], mailbox.rx_buffer,
  144. frag_length);
  145. if (ffa_rx_release()) {
  146. ERROR("Failed to release buffer!\n");
  147. return FFA_ERROR_DENIED;
  148. }
  149. recv_length += frag_length;
  150. assert(recv_length <= total_length);
  151. }
  152. composite = ffa_memory_region_get_composite(m, 0);
  153. if (composite == NULL) {
  154. WARN("Failed to get composite descriptor!\n");
  155. return FFA_ERROR_INVALID_PARAMETER;
  156. }
  157. VERBOSE("Address: %p; page_count: %x %lx\n",
  158. (void *)composite->address_range_array[0].address,
  159. composite->address_range_array[0].page_count, PAGE_SIZE);
  160. /* This test is only concerned with RW permissions. */
  161. if (ffa_get_data_access_attr(
  162. receivers[0].mapd.memory_access_permissions) != FFA_MEM_PERM_RW) {
  163. ERROR("Data permission in retrieve response %x does not match share/lend %x!\n",
  164. ffa_get_data_access_attr(receivers[0].mapd.memory_access_permissions),
  165. FFA_MEM_PERM_RW);
  166. return FFA_ERROR_INVALID_PARAMETER;
  167. }
  168. mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER;
  169. /* Only expecting to be sent memory from NWd so map accordingly. */
  170. mem_attrs |= MT_NS;
  171. for (int32_t i = 0; i < (int32_t)composite->address_range_count; i++) {
  172. size_t size = composite->address_range_array[i].page_count * PAGE_SIZE;
  173. ptr = (char *) composite->address_range_array[i].address;
  174. ret = mmap_add_dynamic_region(
  175. (uint64_t)ptr,
  176. (uint64_t)ptr,
  177. size, mem_attrs);
  178. if (ret != 0) {
  179. ERROR("Failed [%d] mmap_add_dynamic_region %u (%lx) (%lx) (%x)!\n",
  180. i, ret,
  181. (uint64_t)composite->address_range_array[i].address,
  182. size, mem_attrs);
  183. /* Remove mappings previously created in this transaction. */
  184. for (i--; i >= 0; i--) {
  185. ret = mmap_remove_dynamic_region(
  186. (uint64_t)composite->address_range_array[i].address,
  187. composite->address_range_array[i].page_count * PAGE_SIZE);
  188. if (ret != 0) {
  189. ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i);
  190. panic();
  191. }
  192. }
  193. return FFA_ERROR_NO_MEMORY;
  194. }
  195. /* Increment memory region for validation purposes. */
  196. ++(*ptr);
  197. /*
  198. * Read initial magic number from memory region for
  199. * validation purposes.
  200. */
  201. if (!i) {
  202. status = *ptr;
  203. }
  204. }
  205. for (uint32_t i = 0U; i < composite->address_range_count; i++) {
  206. ret = mmap_remove_dynamic_region(
  207. (uint64_t)composite->address_range_array[i].address,
  208. composite->address_range_array[i].page_count * PAGE_SIZE);
  209. if (ret != 0) {
  210. ERROR("Failed [%d] mmap_remove_dynamic_region!\n", i);
  211. return FFA_ERROR_NO_MEMORY;
  212. }
  213. }
  214. if (!memory_relinquish((struct ffa_mem_relinquish_descriptor *)mailbox.tx_buffer,
  215. m->handle, tsp_id)) {
  216. ERROR("Failed to relinquish memory region!\n");
  217. return FFA_ERROR_INVALID_PARAMETER;
  218. }
  219. return status;
  220. }
  221. static smc_args_t *send_ffa_pm_success(void)
  222. {
  223. return set_smc_args(FFA_MSG_SEND_DIRECT_RESP_SMC32,
  224. ((tsp_id & FFA_DIRECT_MSG_ENDPOINT_ID_MASK)
  225. << FFA_DIRECT_MSG_SOURCE_SHIFT) | spmc_id,
  226. FFA_FWK_MSG_BIT |
  227. (FFA_PM_MSG_PM_RESP & FFA_FWK_MSG_MASK),
  228. 0, 0, 0, 0, 0);
  229. }
  230. /*******************************************************************************
  231. * This function performs any remaining book keeping in the test secure payload
  232. * before this cpu is turned off in response to a psci cpu_off request.
  233. ******************************************************************************/
  234. smc_args_t *tsp_cpu_off_main(uint64_t arg0,
  235. uint64_t arg1,
  236. uint64_t arg2,
  237. uint64_t arg3,
  238. uint64_t arg4,
  239. uint64_t arg5,
  240. uint64_t arg6,
  241. uint64_t arg7)
  242. {
  243. uint32_t linear_id = plat_my_core_pos();
  244. /*
  245. * This cpu is being turned off, so disable the timer to prevent the
  246. * secure timer interrupt from interfering with power down. A pending
  247. * interrupt will be lost but we do not care as we are turning off.
  248. */
  249. tsp_generic_timer_stop();
  250. /* Update this cpu's statistics. */
  251. tsp_stats[linear_id].smc_count++;
  252. tsp_stats[linear_id].eret_count++;
  253. tsp_stats[linear_id].cpu_off_count++;
  254. VERBOSE("TSP: cpu 0x%lx off request\n", read_mpidr());
  255. VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
  256. read_mpidr(),
  257. tsp_stats[linear_id].smc_count,
  258. tsp_stats[linear_id].eret_count,
  259. tsp_stats[linear_id].cpu_off_count);
  260. return send_ffa_pm_success();
  261. }
  262. /*******************************************************************************
  263. * This function performs any book keeping in the test secure payload before
  264. * this cpu's architectural state is saved in response to an earlier psci
  265. * cpu_suspend request.
  266. ******************************************************************************/
  267. smc_args_t *tsp_cpu_suspend_main(uint64_t arg0,
  268. uint64_t arg1,
  269. uint64_t arg2,
  270. uint64_t arg3,
  271. uint64_t arg4,
  272. uint64_t arg5,
  273. uint64_t arg6,
  274. uint64_t arg7)
  275. {
  276. uint32_t linear_id = plat_my_core_pos();
  277. /*
  278. * Save the time context and disable it to prevent the secure timer
  279. * interrupt from interfering with wakeup from the suspend state.
  280. */
  281. tsp_generic_timer_save();
  282. tsp_generic_timer_stop();
  283. /* Update this cpu's statistics. */
  284. tsp_stats[linear_id].smc_count++;
  285. tsp_stats[linear_id].eret_count++;
  286. tsp_stats[linear_id].cpu_suspend_count++;
  287. VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
  288. read_mpidr(),
  289. tsp_stats[linear_id].smc_count,
  290. tsp_stats[linear_id].eret_count,
  291. tsp_stats[linear_id].cpu_suspend_count);
  292. return send_ffa_pm_success();
  293. }
  294. /*******************************************************************************
  295. * This function performs any bookkeeping in the test secure payload after this
  296. * cpu's architectural state has been restored after wakeup from an earlier psci
  297. * cpu_suspend request.
  298. ******************************************************************************/
  299. smc_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
  300. uint64_t arg1,
  301. uint64_t arg2,
  302. uint64_t arg3,
  303. uint64_t arg4,
  304. uint64_t arg5,
  305. uint64_t arg6,
  306. uint64_t arg7)
  307. {
  308. uint32_t linear_id = plat_my_core_pos();
  309. /* Restore the generic timer context. */
  310. tsp_generic_timer_restore();
  311. /* Update this cpu's statistics. */
  312. tsp_stats[linear_id].smc_count++;
  313. tsp_stats[linear_id].eret_count++;
  314. tsp_stats[linear_id].cpu_resume_count++;
  315. VERBOSE("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n",
  316. read_mpidr(), max_off_pwrlvl);
  317. VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
  318. read_mpidr(),
  319. tsp_stats[linear_id].smc_count,
  320. tsp_stats[linear_id].eret_count,
  321. tsp_stats[linear_id].cpu_resume_count);
  322. return send_ffa_pm_success();
  323. }
  324. /*******************************************************************************
  325. * This function handles framework messages. Currently only PM.
  326. ******************************************************************************/
  327. static smc_args_t *handle_framework_message(uint64_t arg0,
  328. uint64_t arg1,
  329. uint64_t arg2,
  330. uint64_t arg3,
  331. uint64_t arg4,
  332. uint64_t arg5,
  333. uint64_t arg6,
  334. uint64_t arg7)
  335. {
  336. /* Check if it is a power management message from the SPMC. */
  337. if (ffa_endpoint_source(arg1) != spmc_id) {
  338. goto err;
  339. }
  340. /* Check if it is a PM request message. */
  341. if ((arg2 & FFA_FWK_MSG_MASK) == FFA_FWK_MSG_PSCI) {
  342. /* Check if it is a PSCI CPU_OFF request. */
  343. if (arg3 == PSCI_CPU_OFF) {
  344. return tsp_cpu_off_main(arg0, arg1, arg2, arg3,
  345. arg4, arg5, arg6, arg7);
  346. } else if (arg3 == PSCI_CPU_SUSPEND_AARCH64) {
  347. return tsp_cpu_suspend_main(arg0, arg1, arg2, arg3,
  348. arg4, arg5, arg6, arg7);
  349. }
  350. } else if ((arg2 & FFA_FWK_MSG_MASK) == FFA_PM_MSG_WB_REQ) {
  351. /* Check it is a PSCI Warm Boot request. */
  352. if (arg3 == FFA_WB_TYPE_NOTS2RAM) {
  353. return tsp_cpu_resume_main(arg0, arg1, arg2, arg3,
  354. arg4, arg5, arg6, arg7);
  355. }
  356. }
  357. err:
  358. ERROR("%s: Unknown framework message!\n", __func__);
  359. panic();
  360. }
  361. /*******************************************************************************
  362. * Handles partition messages. Exercised from the FF-A Test Driver.
  363. ******************************************************************************/
  364. static smc_args_t *handle_partition_message(uint64_t arg0,
  365. uint64_t arg1,
  366. uint64_t arg2,
  367. uint64_t arg3,
  368. uint64_t arg4,
  369. uint64_t arg5,
  370. uint64_t arg6,
  371. uint64_t arg7)
  372. {
  373. uint16_t sender = ffa_endpoint_source(arg1);
  374. uint16_t receiver = ffa_endpoint_destination(arg1);
  375. int status = -1;
  376. const bool multi_endpoint = true;
  377. switch (arg3) {
  378. case FF_A_MEMORY_SHARE:
  379. INFO("TSP Tests: Memory Share Request--\n");
  380. status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, !multi_endpoint);
  381. break;
  382. case FF_A_MEMORY_LEND:
  383. INFO("TSP Tests: Memory Lend Request--\n");
  384. status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, !multi_endpoint);
  385. break;
  386. case FF_A_MEMORY_SHARE_MULTI_ENDPOINT:
  387. INFO("TSP Tests: Multi Endpoint Memory Share Request--\n");
  388. status = test_memory_send(sender, arg4, FFA_FLAG_SHARE_MEMORY, multi_endpoint);
  389. break;
  390. case FF_A_MEMORY_LEND_MULTI_ENDPOINT:
  391. INFO("TSP Tests: Multi Endpoint Memory Lend Request--\n");
  392. status = test_memory_send(sender, arg4, FFA_FLAG_LEND_MEMORY, multi_endpoint);
  393. break;
  394. case FF_A_RELAY_MESSAGE:
  395. INFO("TSP Tests: Relaying message--\n");
  396. status = ffa_test_relay(arg0, arg1, arg2, arg3, arg4,
  397. arg5, arg6, arg7);
  398. break;
  399. case FF_A_ECHO_MESSAGE:
  400. INFO("TSP Tests: echo message--\n");
  401. status = arg4;
  402. break;
  403. default:
  404. INFO("TSP Tests: Unknown request ID %d--\n", (int) arg3);
  405. }
  406. /* Swap the sender and receiver in the response. */
  407. return ffa_msg_send_direct_resp(receiver, sender, status, 0, 0, 0, 0);
  408. }
  409. /*******************************************************************************
  410. * This function implements the event loop for handling FF-A ABI invocations.
  411. ******************************************************************************/
  412. static smc_args_t *tsp_event_loop(uint64_t smc_fid,
  413. uint64_t arg1,
  414. uint64_t arg2,
  415. uint64_t arg3,
  416. uint64_t arg4,
  417. uint64_t arg5,
  418. uint64_t arg6,
  419. uint64_t arg7)
  420. {
  421. /* Panic if the SPMC did not forward an FF-A call. */
  422. if (!is_ffa_fid(smc_fid)) {
  423. ERROR("%s: Unknown SMC FID (0x%lx)\n", __func__, smc_fid);
  424. panic();
  425. }
  426. switch (smc_fid) {
  427. case FFA_INTERRUPT:
  428. /*
  429. * IRQs were enabled upon re-entry into the TSP. The interrupt
  430. * must have been handled by now. Return to the SPMC indicating
  431. * the same.
  432. */
  433. return set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0);
  434. case FFA_MSG_SEND_DIRECT_REQ_SMC64:
  435. case FFA_MSG_SEND_DIRECT_REQ_SMC32:
  436. /* Check if a framework message, handle accordingly. */
  437. if ((arg2 & FFA_FWK_MSG_BIT)) {
  438. return handle_framework_message(smc_fid, arg1, arg2, arg3,
  439. arg4, arg5, arg6, arg7);
  440. }
  441. return handle_partition_message(smc_fid, arg1, arg2, arg3,
  442. arg4, arg5, arg6, arg7);
  443. }
  444. ERROR("%s: Unsupported FF-A FID (0x%lx)\n", __func__, smc_fid);
  445. panic();
  446. }
  447. static smc_args_t *tsp_loop(smc_args_t *args)
  448. {
  449. smc_args_t ret;
  450. do {
  451. /* --------------------------------------------
  452. * Mask FIQ interrupts to avoid preemption
  453. * in case EL3 SPMC delegates an IRQ next or a
  454. * managed exit. Lastly, unmask IRQs so that
  455. * they can be handled immediately upon re-entry.
  456. * ---------------------------------------------
  457. */
  458. write_daifset(DAIF_FIQ_BIT);
  459. write_daifclr(DAIF_IRQ_BIT);
  460. ret = smc_helper(args->_regs[0], args->_regs[1], args->_regs[2],
  461. args->_regs[3], args->_regs[4], args->_regs[5],
  462. args->_regs[6], args->_regs[7]);
  463. args = tsp_event_loop(ret._regs[0], ret._regs[1], ret._regs[2],
  464. ret._regs[3], ret._regs[4], ret._regs[5],
  465. ret._regs[6], ret._regs[7]);
  466. } while (1);
  467. /* Not Reached. */
  468. return NULL;
  469. }
  470. /*******************************************************************************
  471. * TSP main entry point where it gets the opportunity to initialize its secure
  472. * state/applications. Once the state is initialized, it must return to the
  473. * SPD with a pointer to the 'tsp_vector_table' jump table.
  474. ******************************************************************************/
  475. uint64_t tsp_main(void)
  476. {
  477. smc_args_t smc_args = {0};
  478. NOTICE("TSP: %s\n", build_version_string);
  479. NOTICE("TSP: %s\n", build_message);
  480. INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
  481. INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
  482. uint32_t linear_id = plat_my_core_pos();
  483. /* Initialize the platform. */
  484. tsp_platform_setup();
  485. /* Initialize secure/applications state here. */
  486. tsp_generic_timer_start();
  487. /* Register secondary entrypoint with the SPMC. */
  488. smc_args = smc_helper(FFA_SECONDARY_EP_REGISTER_SMC64,
  489. (uint64_t) tsp_cpu_on_entry,
  490. 0, 0, 0, 0, 0, 0);
  491. if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
  492. ERROR("TSP could not register secondary ep (0x%lx)\n",
  493. smc_args._regs[2]);
  494. panic();
  495. }
  496. /* Get TSP's endpoint id. */
  497. smc_args = smc_helper(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0);
  498. if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
  499. ERROR("TSP could not get own ID (0x%lx) on core%d\n",
  500. smc_args._regs[2], linear_id);
  501. panic();
  502. }
  503. tsp_id = smc_args._regs[2];
  504. INFO("TSP FF-A endpoint id = 0x%x\n", tsp_id);
  505. /* Get the SPMC ID. */
  506. smc_args = smc_helper(FFA_SPM_ID_GET, 0, 0, 0, 0, 0, 0, 0);
  507. if (smc_args._regs[SMC_ARG0] != FFA_SUCCESS_SMC32) {
  508. ERROR("TSP could not get SPMC ID (0x%lx) on core%d\n",
  509. smc_args._regs[2], linear_id);
  510. panic();
  511. }
  512. spmc_id = smc_args._regs[2];
  513. /* Call RXTX_MAP to map a 4k RX and TX buffer. */
  514. if (ffa_rxtx_map((uintptr_t) send_page,
  515. (uintptr_t) recv_page, 1)) {
  516. ERROR("TSP could not map it's RX/TX Buffers\n");
  517. panic();
  518. }
  519. mailbox.tx_buffer = send_page;
  520. mailbox.rx_buffer = recv_page;
  521. mailbox.rxtx_page_count = 1;
  522. /* Update this cpu's statistics. */
  523. tsp_stats[linear_id].smc_count++;
  524. tsp_stats[linear_id].eret_count++;
  525. tsp_stats[linear_id].cpu_on_count++;
  526. VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
  527. read_mpidr(),
  528. tsp_stats[linear_id].smc_count,
  529. tsp_stats[linear_id].eret_count,
  530. tsp_stats[linear_id].cpu_on_count);
  531. /* Tell SPMD that we are done initialising. */
  532. tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0));
  533. /* Not reached. */
  534. return 0;
  535. }
  536. /*******************************************************************************
  537. * This function performs any remaining book keeping in the test secure payload
  538. * after this cpu's architectural state has been setup in response to an earlier
  539. * psci cpu_on request.
  540. ******************************************************************************/
  541. smc_args_t *tsp_cpu_on_main(void)
  542. {
  543. uint32_t linear_id = plat_my_core_pos();
  544. /* Initialize secure/applications state here. */
  545. tsp_generic_timer_start();
  546. /* Update this cpu's statistics. */
  547. tsp_stats[linear_id].smc_count++;
  548. tsp_stats[linear_id].eret_count++;
  549. tsp_stats[linear_id].cpu_on_count++;
  550. VERBOSE("TSP: cpu 0x%lx turned on\n", read_mpidr());
  551. VERBOSE("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
  552. read_mpidr(),
  553. tsp_stats[linear_id].smc_count,
  554. tsp_stats[linear_id].eret_count,
  555. tsp_stats[linear_id].cpu_on_count);
  556. /* ---------------------------------------------
  557. * Jump to the main event loop to return to EL3
  558. * and be ready for the next request on this cpu.
  559. * ---------------------------------------------
  560. */
  561. return tsp_loop(set_smc_args(FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0));
  562. }