aboutsummaryrefslogtreecommitdiff
path: root/tftf
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2019-01-07 15:55:07 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2019-01-07 15:55:07 +0000
commit48ea56b221c113834a02334a71661dbeea26a091 (patch)
treebfe75e58d8032a54cb54195509d5c3e84b8d52c2 /tftf
parentbbdb2762062547ef279256d0163e4d743f21474a (diff)
parent10a0254708efb96397890ce53265adac3fc94153 (diff)
downloadtf-a-tests-48ea56b221c113834a02334a71661dbeea26a091.tar.gz
Merge changes from topic "an/spm"
* changes: SPM: Test interrupt preemption SPM: Test blocking requests while busy
Diffstat (limited to 'tftf')
-rw-r--r--tftf/tests/runtime_services/secure_service/test_spci_blocking_interrupt.c121
-rw-r--r--tftf/tests/runtime_services/secure_service/test_spci_blocking_while_busy.c170
-rw-r--r--tftf/tests/runtime_services/secure_service/test_spci_non_blocking_interrupt.c146
-rw-r--r--tftf/tests/tests-spm.mk3
-rw-r--r--tftf/tests/tests-spm.xml8
5 files changed, 448 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/secure_service/test_spci_blocking_interrupt.c b/tftf/tests/runtime_services/secure_service/test_spci_blocking_interrupt.c
new file mode 100644
index 000000000..44ee0f9a9
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_spci_blocking_interrupt.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cactus_def.h>
+#include <debug.h>
+#include <smccc.h>
+#include <spci_helpers.h>
+#include <spci_svc.h>
+#include <string.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <timer.h>
+
+static volatile int timer_irq_received;
+
+/*
+ * ISR for the timer interrupt. Update a global variable to check it has been
+ * called.
+ */
+static int timer_handler(void *data)
+{
+ assert(timer_irq_received == 0);
+ timer_irq_received = 1;
+ return 0;
+}
+
+/*
+ * @Test_Aim@ Test that non-secure interrupts do not interrupt blocking
+ * requests.
+ *
+ * 1. Register a handler for the non-secure timer interrupt. Program it to fire
+ * in a certain time.
+ *
+ * 2. Send a blocking request to Cactus to sleep for more time than the timer.
+ *
+ * 3. While servicing the timer sleep request, the non-secure timer should
+ * fire but not interrupt Cactus.
+ *
+ * 4. Once back in TFTF, check the response from Cactus, which shows whether the
+ * secure service indeed ran to completion.
+ *
+ * 5. Also check whether the pending non-secure timer interrupt successfully got
+ * handled in TFTF.
+ */
+test_result_t test_spci_blocking_interrupt_by_ns(void)
+{
+ int ret;
+ uint16_t handle_cactus;
+ test_result_t result = TEST_RESULT_SUCCESS;
+
+ SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 1);
+
+ /* Open handle */
+
+ ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_cactus,
+ CACTUS_SERVICE1_UUID);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: %d\n",
+ __LINE__, ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Program timer */
+
+ timer_irq_received = 0;
+ tftf_timer_register_handler(timer_handler);
+
+ ret = tftf_program_timer(100);
+ if (ret < 0) {
+ tftf_testcase_printf("Failed to program timer (%d)\n", ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Send request to Cactus */
+
+ ret = spci_service_request_blocking(CACTUS_SLEEP_MS, 200U,
+ 0, 0, 0, 0,
+ TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ NULL, NULL, NULL);
+ if (ret != SPCI_SUCCESS) {
+ /*
+ * If the interrupt is handled during the blocking call, there
+ * will be a crash in EL3 because the function that invokes a
+ * blocking call doesn't know how to handle it. The CPU won't
+ * come back here (because it should never happen!).
+ */
+ tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Check that the interrupt has been handled */
+
+ tftf_cancel_timer();
+ tftf_timer_unregister_handler();
+
+ if (timer_irq_received == 0) {
+ tftf_testcase_printf("%d: Timer interrupt hasn't actually been handled.\n",
+ __LINE__);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Close handle */
+
+ ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_cactus);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to close the handle. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* All tests finished */
+
+ return result;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_spci_blocking_while_busy.c b/tftf/tests/runtime_services/secure_service/test_spci_blocking_while_busy.c
new file mode 100644
index 000000000..dffd910f8
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_spci_blocking_while_busy.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cactus_def.h>
+#include <debug.h>
+#include <smccc.h>
+#include <spci_helpers.h>
+#include <spci_svc.h>
+#include <string.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <timer.h>
+
+static volatile int timer_irq_received;
+
+/*
+ * ISR for the timer interrupt. Update a global variable to check it has been
+ * called.
+ */
+static int timer_handler(void *data)
+{
+ assert(timer_irq_received == 0);
+ timer_irq_received = 1;
+ return 0;
+}
+
+/*
+ * @Test_Aim@ Test that blocking requests can only be done when there are no
+ * active non-blocking requests in a partition.
+ *
+ * 1. Register a handler for the non-secure timer interrupt. Program it to fire
+ * in a certain time.
+ *
+ * 2. Send a non-blocking request to Cactus to sleep for more time than the
+ * timer.
+ *
+ * 3. While servicing the timer sleep request, the non-secure timer should
+ * fire and interrupt Cactus.
+ *
+ * 5. Check that the interrupt has been handled.
+ *
+ * 6. Make sure that the response isn't ready yet.
+ *
+ * 7. Try to send a blocking request. It should be denied because the partition
+ * is busy.
+ *
+ * 8. Return to Cactus to finish the request.
+ */
+test_result_t test_spci_blocking_while_busy(void)
+{
+ int ret;
+ u_register_t rx1, rx2, rx3;
+ uint16_t handle_cactus;
+ uint32_t token_cactus;
+ test_result_t result = TEST_RESULT_SUCCESS;
+
+ SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 1);
+
+ /* Open handle. */
+
+ ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_cactus,
+ CACTUS_SERVICE1_UUID);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: %d\n",
+ __LINE__, ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Program timer */
+
+ timer_irq_received = 0;
+ tftf_timer_register_handler(timer_handler);
+
+ ret = tftf_program_timer(100);
+ if (ret < 0) {
+ tftf_testcase_printf("Failed to program timer (%d)\n", ret);
+ result = TEST_RESULT_FAIL;
+ goto exit_close_handle;
+ }
+
+ enable_irq();
+
+ /* Send request to Cactus */
+
+ ret = spci_service_request_start(CACTUS_SLEEP_MS, 200U,
+ 0, 0, 0, 0,
+ TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ &token_cactus);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Check that the interrupt has been handled. */
+
+ if (timer_irq_received == 0) {
+ tftf_testcase_printf("%d: Didn't handle interrupt\n", __LINE__);
+ result = TEST_RESULT_FAIL;
+ }
+
+ tftf_cancel_timer();
+ tftf_timer_unregister_handler();
+
+ /* Make sure that the response is not ready yet. */
+
+ ret = spci_service_get_response(TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ token_cactus,
+ NULL, NULL, NULL);
+
+ if (ret == SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: Cactus returned SPCI_SUCCESS\n",
+ __LINE__);
+ result = TEST_RESULT_FAIL;
+ goto exit_close_handle;
+ }
+
+ /*
+ * Try to send a blocking request. It should be denied because the
+ * partition is busy.
+ */
+
+ ret = spci_service_request_blocking(CACTUS_GET_MAGIC,
+ 0, 0, 0, 0, 0,
+ TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ &rx1, &rx2, &rx3);
+ if (ret != SPCI_BUSY) {
+ tftf_testcase_printf("%d: Cactus should have returned SPCI_BUSY. Returned %d 0x%lx 0x%lx 0x%lx\n",
+ __LINE__, ret, rx1, rx2, rx3);
+ result = TEST_RESULT_FAIL;
+ goto exit_close_handle;
+ }
+
+ /* Re-enter Cactus to finish the request */
+
+ do {
+ ret = spci_service_request_resume(TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ token_cactus,
+ &rx1, NULL, NULL);
+ } while (ret == SPCI_QUEUED);
+
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: Cactus returned %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Close handle. */
+exit_close_handle:
+
+ ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_cactus);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to close the handle. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* All tests finished. */
+
+ return result;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_spci_non_blocking_interrupt.c b/tftf/tests/runtime_services/secure_service/test_spci_non_blocking_interrupt.c
new file mode 100644
index 000000000..cb5dd6b0c
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_spci_non_blocking_interrupt.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cactus_def.h>
+#include <debug.h>
+#include <smccc.h>
+#include <spci_helpers.h>
+#include <spci_svc.h>
+#include <string.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <timer.h>
+
+static volatile int timer_irq_received;
+
+/*
+ * ISR for the timer interrupt. Update a global variable to check it has been
+ * called.
+ */
+static int timer_handler(void *data)
+{
+ assert(timer_irq_received == 0);
+ timer_irq_received = 1;
+ return 0;
+}
+
+/*
+ * @Test_Aim@ Test that non-secure interrupts interrupt non-blocking requests.
+ *
+ * 1. Register a handler for the non-secure timer interrupt. Program it to fire
+ * in a certain time.
+ *
+ * 2. Send a non-blocking request to Cactus to sleep for more time than the
+ * timer.
+ *
+ * 3. While servicing the timer sleep request, the non-secure timer should
+ * fire and interrupt Cactus.
+ *
+ * 4. Make sure that the response isn't ready yet.
+ *
+ * 5. In the TFTF, check that the interrupt has been handled.
+ *
+ * 6. Return to Cactus to finish the request.
+ */
+test_result_t test_spci_non_blocking_interrupt_by_ns(void)
+{
+ int ret;
+ u_register_t ret1;
+ uint16_t handle_cactus;
+ uint32_t token_cactus;
+ test_result_t result = TEST_RESULT_SUCCESS;
+
+ SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 1);
+
+ /* Open handle */
+
+ ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_cactus,
+ CACTUS_SERVICE1_UUID);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: %d\n",
+ __LINE__, ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Program timer */
+
+ timer_irq_received = 0;
+ tftf_timer_register_handler(timer_handler);
+
+ ret = tftf_program_timer(100);
+ if (ret < 0) {
+ tftf_testcase_printf("Failed to program timer (%d)\n", ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Send request to Cactus */
+
+ ret = spci_service_request_start(CACTUS_SLEEP_MS, 200U,
+ 0, 0, 0, 0,
+ TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ &token_cactus);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Check that the interrupt has been handled */
+
+ tftf_cancel_timer();
+ tftf_timer_unregister_handler();
+
+ if (timer_irq_received == 0) {
+ tftf_testcase_printf("%d: Didn't handle interrupt\n", __LINE__);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Make sure that the response is not ready yet */
+
+ ret = spci_service_get_response(TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ token_cactus,
+ NULL, NULL, NULL);
+
+ if (ret == SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: Cactus returned SPCI_SUCCESS\n",
+ __LINE__);
+ result = TEST_RESULT_FAIL;
+ goto exit_close_handle;
+ }
+
+ /* Re-enter Cactus to finish the request */
+
+ do {
+ ret = spci_service_request_resume(TFTF_SPCI_CLIENT_ID,
+ handle_cactus,
+ token_cactus,
+ &ret1, NULL, NULL);
+ } while (ret == SPCI_QUEUED);
+
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: Cactus returned 0x%x\n",
+ __LINE__, (uint32_t)ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Close handle */
+exit_close_handle:
+
+ ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_cactus);
+ if (ret != SPCI_SUCCESS) {
+ tftf_testcase_printf("%d: SPM failed to close the handle. Returned: %d\n",
+ __LINE__, ret);
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* All tests finished */
+
+ return result;
+}
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 0dba4137b..c4876879f 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -10,4 +10,7 @@ TESTS_SOURCES += \
test_spci_handle_open.c \
test_spci_blocking_request.c \
test_spci_non_blocking_request.c \
+ test_spci_blocking_while_busy.c \
+ test_spci_blocking_interrupt.c \
+ test_spci_non_blocking_interrupt.c \
)
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index bb6e5dd1a..9afc6afd2 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -22,6 +22,14 @@
<testcase name="SPCI non-blocking requests multicore"
function="test_spci_request_multicore" />
+ <testcase name="SPCI blocking request while busy"
+ function="test_spci_blocking_while_busy" />
+
+ <testcase name="SPCI blocking request fail to preempt"
+ function="test_spci_blocking_interrupt_by_ns" />
+ <testcase name="SPCI non-blocking request succeed to preempt"
+ function="test_spci_non_blocking_interrupt_by_ns" />
+
</testsuite>
</testsuites>