aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Deprez <olivier.deprez@arm.com>2021-03-16 16:15:14 +0100
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2021-03-16 16:15:14 +0100
commit615f8c6eab9d91b0bcb61fbc135dd2d70a37d7cd (patch)
treeea4cb089ea1b6ba063b3489156c66a861ca22ccc
parent80542392bdb5861ccba1d1563b10a0ad7d21b21e (diff)
parent35e1948987aed5929f4c614c79370e12d2a90e52 (diff)
downloadtf-a-tests-615f8c6eab9d91b0bcb61fbc135dd2d70a37d7cd.tar.gz
Merge changes from topic "od/ffa_spmc_pwr"
* changes: cactus: declare third SP instance as UP SP TFTF: Add secondary cores direct messaging test for SPM cactus: secondary core cold boot FF-A: add secondary entry point register function
-rw-r--r--include/runtime_services/ffa_svc.h5
-rw-r--r--spm/cactus/aarch64/cactus_entrypoint.S43
-rw-r--r--spm/cactus/cactus_main.c44
-rw-r--r--spm/cactus/plat/arm/fvp/include/cactus_platform_def.h3
-rw-r--r--spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts2
-rw-r--r--spm/cactus/plat/arm/tc0/include/cactus_platform_def.h2
-rw-r--r--tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c146
-rw-r--r--tftf/tests/tests-spm.xml6
8 files changed, 221 insertions, 30 deletions
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index f08e8039..c9702658 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -22,7 +22,7 @@
/* The macros below are used to identify FFA calls from the SMC function ID */
#define FFA_FNUM_MIN_VALUE U(0x60)
-#define FFA_FNUM_MAX_VALUE U(0x7f)
+#define FFA_FNUM_MAX_VALUE U(0x84)
#define is_ffa_fid(fid) __extension__ ({ \
__typeof__(fid) _fid = (fid); \
((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \
@@ -84,6 +84,7 @@
#define FFA_FNUM_MEM_RETRIEVE_RESP U(0x75)
#define FFA_FNUM_MEM_RELINQUISH U(0x76)
#define FFA_FNUM_MEM_RECLAIM U(0x77)
+#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x84)
/* FFA SMC32 FIDs */
#define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR)
@@ -126,6 +127,8 @@
#define FFA_MEM_SHARE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_SHARE)
#define FFA_MEM_RETRIEVE_REQ_SMC64 \
FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ)
+#define FFA_SECONDARY_EP_REGISTER_SMC64 \
+ FFA_FID(SMC_64, FFA_FNUM_SECONDARY_EP_REGISTER)
/*
* Reserve a special value for traffic targeted to the Hypervisor or SPM.
diff --git a/spm/cactus/aarch64/cactus_entrypoint.S b/spm/cactus/aarch64/cactus_entrypoint.S
index b0f89d4f..7e638569 100644
--- a/spm/cactus/aarch64/cactus_entrypoint.S
+++ b/spm/cactus/aarch64/cactus_entrypoint.S
@@ -7,25 +7,35 @@
#include <arch.h>
#include <asm_macros.S>
#include <cactus_def.h>
-#include <platform_def.h>
+#include <cactus_platform_def.h>
.globl cactus_entrypoint
+ .globl secondary_cold_entry
+/* Provision one stack per Execution Context (or vCPU) */
.section .bss.stacks
.balign CACHE_WRITEBACK_GRANULE
- .fill CACTUS_STACKS_SIZE
+ .fill CACTUS_STACKS_SIZE * PLAT_CACTUS_CORE_COUNT
stacks_end:
func cactus_entrypoint
+ /* Entry reason is primary EC cold boot */
+ mov x19, #1
+secondary_cold_entry:
+ /* Entry reason is secondary EC cold boot */
+ mrs x0, mpidr_el1
+ bl platform_get_core_pos
/* Setup the stack pointer. */
- adr x0, stacks_end
- mov sp, x0
+ adr x1, stacks_end
+ mov x2, #CACTUS_STACKS_SIZE
+ mul x2, x0, x2
+ sub sp, x1, x2
/* Enable I-Cache */
- mrs x0, sctlr_el1
- orr x0, x0, #SCTLR_I_BIT
- msr sctlr_el1, x0
+ mrs x1, sctlr_el1
+ orr x1, x1, #SCTLR_I_BIT
+ msr sctlr_el1, x1
isb
/*
@@ -38,6 +48,15 @@ func cactus_entrypoint
msr cpacr_el1, x0
isb
+ /* Set up exceptions vector table */
+ adrp x1, tftf_vector
+ add x1, x1, :lo12:tftf_vector
+ msr vbar_el1, x1
+ isb
+
+ /* Skip to main if warm boot */
+ cbz x19, 0f
+
/* Relocate symbols */
pie_fixup:
ldr x0, =pie_fixup
@@ -46,13 +65,7 @@ pie_fixup:
add x1, x1, x0
bl fixup_gdt_reloc
- /* Set up exceptions vector table */
- adrp x0, tftf_vector
- add x0, x0, :lo12:tftf_vector
- msr vbar_el1, x0
- isb
-
- /* And jump to the C entrypoint. */
+ /* Jump to the C entrypoint (it does not return) */
+0: mov x0, x19
b cactus_main
-
endfunc cactus_entrypoint
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 7e3f40bf..e54f3b0d 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -13,6 +13,7 @@
#include <drivers/arm/pl011.h>
#include <drivers/console.h>
#include <lib/aarch64/arch_helpers.h>
+#include <lib/tftf_lib.h>
#include <lib/xlat_tables/xlat_mmu_helpers.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat_arm.h>
@@ -29,6 +30,8 @@
extern const char build_message[];
extern const char version_string[];
+extern void secondary_cold_entry(void);
+
/*
*
* Message loop function
@@ -147,6 +150,16 @@ static void cactus_plat_configure_mmu(unsigned int vm_id)
init_xlat_tables();
}
+static void register_secondary_entrypoint(void)
+{
+ smc_args args;
+
+ args.fid = FFA_SECONDARY_EP_REGISTER_SMC64;
+ args.arg1 = (u_register_t)&secondary_cold_entry;
+
+ tftf_smc(&args);
+}
+
int tftf_irq_handler_dispatcher(void)
{
ERROR("%s\n", __func__);
@@ -154,31 +167,39 @@ int tftf_irq_handler_dispatcher(void)
return 0;
}
-void __dead2 cactus_main(void)
+void __dead2 cactus_main(bool primary_cold_boot)
{
assert(IS_IN_EL1() != 0);
struct mailbox_buffers mb;
- /* Clear BSS */
- memset((void *)CACTUS_BSS_START,
- 0, CACTUS_BSS_END - CACTUS_BSS_START);
-
/* Get current FFA id */
smc_ret_values ffa_id_ret = ffa_id_get();
if (ffa_func_id(ffa_id_ret) != FFA_SUCCESS_SMC32) {
ERROR("FFA_ID_GET failed.\n");
panic();
}
-
ffa_vm_id_t ffa_id = ffa_id_ret.ret2 & 0xffff;
- mb.send = (void *) get_sp_tx_start(ffa_id);
- mb.recv = (void *) get_sp_rx_start(ffa_id);
- /* Configure and enable Stage-1 MMU, enable D-Cache */
- cactus_plat_configure_mmu(ffa_id);
+ if (primary_cold_boot == true) {
+ /* Clear BSS */
+ memset((void *)CACTUS_BSS_START,
+ 0, CACTUS_BSS_END - CACTUS_BSS_START);
+
+
+ mb.send = (void *) get_sp_tx_start(ffa_id);
+ mb.recv = (void *) get_sp_rx_start(ffa_id);
+
+ /* Configure and enable Stage-1 MMU, enable D-Cache */
+ cactus_plat_configure_mmu(ffa_id);
+ }
+
enable_mmu_el1(0);
+ if (primary_cold_boot == false) {
+ goto msg_loop;
+ }
+
if (ffa_id == SPM_VM_ID_FIRST) {
console_init(CACTUS_PL011_UART_BASE,
CACTUS_PL011_UART_CLK_IN_HZ,
@@ -210,9 +231,12 @@ void __dead2 cactus_main(void)
INFO("FF-A id: %x\n", ffa_id);
cactus_print_memory_layout(ffa_id);
+ register_secondary_entrypoint();
+
/* Invoking Tests */
ffa_tests(&mb);
+msg_loop:
/* End up to message loop */
message_loop(ffa_id, &mb);
diff --git a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
index e8790027..b4c57efe 100644
--- a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
+++ b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
@@ -16,9 +16,10 @@
#define CACTUS_PL011_UART_CLK_IN_HZ PL011_UART2_CLK_IN_HZ
#define PLAT_CACTUS_RX_BASE ULL(0x7300000)
+#define PLAT_CACTUS_CORE_COUNT (8U)
#define CACTUS_PRIMARY_EC_COUNT (8U)
#define CACTUS_SECONDARY_EC_COUNT (8U)
-#define CACTUS_TERTIARY_EC_COUNT (8U)
+#define CACTUS_TERTIARY_EC_COUNT (1U)
#endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts b/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
index 724d5956..3b50530e 100644
--- a/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
+++ b/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
@@ -18,7 +18,7 @@
ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
uuid = <0x79b55c73 0x1d8c44b9 0x859361e1 0x770ad8d2>;
id = <3>;
- execution-ctx-count = <8>;
+ execution-ctx-count = <1>;
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0xfe200000>;
diff --git a/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h b/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
index d5513142..42dd2915 100644
--- a/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
+++ b/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
@@ -19,6 +19,6 @@
#define CACTUS_PRIMARY_EC_COUNT (8U)
#define CACTUS_SECONDARY_EC_COUNT (8U)
-#define CACTUS_TERTIARY_EC_COUNT (8U)
+#define CACTUS_TERTIARY_EC_COUNT (1U)
#endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 83510b06..0a722e49 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -11,6 +11,8 @@
#include <cactus_test_cmds.h>
#include <ffa_endpoints.h>
#include <ffa_svc.h>
+#include <lib/events.h>
+#include <lib/power_management.h>
#include <platform.h>
#include <test_helpers.h>
@@ -22,6 +24,9 @@ static const struct ffa_uuid expected_sp_uuids[] = {
{PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}
};
+
+static event_t cpu_booted[PLATFORM_CORE_COUNT];
+
static test_result_t send_cactus_echo_cmd(ffa_vm_id_t sender,
ffa_vm_id_t dest,
uint64_t value)
@@ -146,7 +151,7 @@ test_result_t test_ffa_sp_to_sp_deadlock(void)
ret = cactus_req_deadlock_send_cmd(HYP_ID, SP_ID(1), SP_ID(2), SP_ID(3));
- if (!is_ffa_direct_response(ret)) {
+ if (is_ffa_direct_response(ret) == false) {
return TEST_RESULT_FAIL;
}
@@ -156,3 +161,142 @@ test_result_t test_ffa_sp_to_sp_deadlock(void)
return TEST_RESULT_SUCCESS;
}
+
+/**
+ * Handler that is passed during tftf_cpu_on to individual CPU cores.
+ * Runs a specific core and send a direct message request.
+ * Expects core_pos | SP_ID as a response.
+ */
+static test_result_t cpu_on_handler(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+ test_result_t ret = TEST_RESULT_SUCCESS;
+ smc_ret_values ffa_ret;
+
+ /*
+ * Send a direct message request to SP1 (MP SP) from current physical
+ * CPU. Notice SP1 ECs are already woken as a result of the PSCI_CPU_ON
+ * invocation so they already reached the message loop.
+ * The SPMC uses the MP pinned context corresponding to the physical
+ * CPU emitting the request.
+ */
+ ret = send_cactus_echo_cmd(HYP_ID, SP_ID(1), ECHO_VAL1);
+ if (ret != TEST_RESULT_SUCCESS) {
+ goto out;
+ }
+
+ /*
+ * Secure Partitions beyond the first SP only have their first
+ * EC (or vCPU0) woken up at boot time by the SPMC.
+ * Other ECs need one round of ffa_run to reach the message loop.
+ */
+ ffa_ret = ffa_run(SP_ID(2), core_pos);
+ if (ffa_func_id(ffa_ret) != FFA_MSG_WAIT) {
+ ERROR("Failed to run SP%x on core %u\n", SP_ID(2),
+ core_pos);
+ ret = TEST_RESULT_FAIL;
+ goto out;
+ }
+
+ /*
+ * Send a direct message request to SP2 (MP SP) from current physical
+ * CPU. The SPMC uses the MP pinned context corresponding to the
+ * physical CPU emitting the request.
+ */
+ ret = send_cactus_echo_cmd(HYP_ID, SP_ID(2), ECHO_VAL2);
+ if (ret != TEST_RESULT_SUCCESS) {
+ goto out;
+ }
+
+ /*
+ * Send a direct message request to SP3 (UP SP) from current physical CPU.
+ * The SPMC uses the single vCPU migrated to the new physical core.
+ * The single SP vCPU may receive requests from multiple physical CPUs.
+ * Thus it is possible one message is being processed on one core while
+ * another (or multiple) cores attempt sending a new direct message
+ * request. In such case the cores attempting the new request receive
+ * a busy response from the SPMC. To handle this case a retry loop is
+ * implemented permitting some fairness.
+ */
+ uint32_t trial_loop = 5U;
+ while (trial_loop--) {
+ ffa_ret = cactus_echo_send_cmd(HYP_ID, SP_ID(3), ECHO_VAL3);
+ if ((ffa_func_id(ffa_ret) == FFA_ERROR) &&
+ (ffa_error_code(ffa_ret) == FFA_ERROR_BUSY)) {
+ VERBOSE("%s(%u) trial %u\n", __func__, core_pos, trial_loop);
+ waitms(1);
+ continue;
+ }
+
+ if (is_ffa_direct_response(ffa_ret) == true) {
+ if (cactus_get_response(ffa_ret) != CACTUS_SUCCESS ||
+ cactus_echo_get_val(ffa_ret) != ECHO_VAL3) {
+ ERROR("Echo Failed!\n");
+ ret = TEST_RESULT_FAIL;
+ }
+
+ goto out;
+ }
+ }
+
+ ret = TEST_RESULT_FAIL;
+
+out:
+ /* Tell the lead CPU that the calling CPU has completed the test */
+ tftf_send_event(&cpu_booted[core_pos]);
+
+ return ret;
+}
+
+/**
+ * Test direct messaging in multicore setup. Runs SPs on all the cores and sends
+ * direct messages to SPs.
+ */
+test_result_t test_ffa_secondary_core_direct_msg(void)
+{
+ unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos, cpu_node, mpidr;
+ int32_t ret;
+
+ /**********************************************************************
+ * Check SPMC has ffa_version and expected FFA endpoints are deployed.
+ **********************************************************************/
+ CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids);
+
+ for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
+ tftf_init_event(&cpu_booted[i]);
+ }
+
+ for_each_cpu(cpu_node) {
+ mpidr = tftf_get_mpidr_from_node(cpu_node);
+ if (mpidr == lead_mpid) {
+ continue;
+ }
+
+ ret = tftf_cpu_on(mpidr, (uintptr_t)cpu_on_handler, 0U);
+ if (ret != 0) {
+ ERROR("tftf_cpu_on mpidr 0x%x returns %d\n", mpidr, ret);
+ }
+ }
+
+ VERBOSE("Waiting secondary CPUs to turn off ...\n");
+
+ for_each_cpu(cpu_node) {
+ mpidr = tftf_get_mpidr_from_node(cpu_node);
+ if (mpidr == lead_mpid) {
+ continue;
+ }
+
+ core_pos = platform_get_core_pos(mpidr);
+ tftf_wait_for_event(&cpu_booted[core_pos]);
+ }
+
+ VERBOSE("Done exiting.\n");
+
+ /**********************************************************************
+ * All tests passed.
+ **********************************************************************/
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 5e809888..ee342927 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -44,6 +44,12 @@
</testsuite>
+ <testsuite name="FF-A Power management"
+ description="Test FF-A power management" >
+ <testcase name="FF-A SP hotplug"
+ function="test_ffa_secondary_core_direct_msg" />
+ </testsuite>
+
<testsuite name="FF-A Memory Sharing"
description="Test FF-A Memory Sharing ABIs" >
<testcase name="Lend Memory to Secure World"