aboutsummaryrefslogtreecommitdiff
path: root/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c
diff options
context:
space:
mode:
Diffstat (limited to 'tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c')
-rw-r--r--tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c
new file mode 100644
index 000000000..8d8758b20
--- /dev/null
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_hotplug/test_psci_hotplug_invalid.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * This file implements test cases exercising invalid scenarios of the CPU
+ * hotplug API. It checks that the PSCI implementation responds as per the
+ * PSCI specification.
+ */
+
+#include <arch_helpers.h>
+#include <events.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <power_management.h>
+#include <psci.h>
+#include <tftf_lib.h>
+
+/*
+ * Event data structures used by non-lead CPUs to tell the lead CPU they entered
+ * the test.
+ */
+static event_t entered_test[PLATFORM_CORE_COUNT];
+
+/*
+ * If 'real_value' == 'expected_value' then return a test success.
+ * Otherwise, print an error message in the test report and report a test
+ * failure.
+ */
+static test_result_t report_result(int expected_value, int real_value)
+{
+ if (real_value != expected_value) {
+ tftf_testcase_printf(
+ "Wrong return value, expected %i, got %i\n",
+ expected_value, real_value);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t reissue_cpu_hotplug(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+ int psci_ret;
+
+ tftf_send_event(&entered_test[core_pos]);
+
+ /*
+ * This time, we can't use tftf_cpu_on() to issue the power on request
+ * because this would go through too much test framework logic. E.g. the
+ * framework would figure out that the the CPU is already powered on by
+ * looking at the CPU state information it keeps, hence it would report
+ * an error.
+ *
+ * Here we need to bypass the framework and issue the SMC call directly
+ * from the test case itself. tftf_psci_cpu_on() is a simple wrapper
+ * over the SMC call.
+ *
+ * Entry point address argument can be any valid address.
+ */
+ psci_ret = tftf_psci_cpu_on(mpid, (uintptr_t)reissue_cpu_hotplug, 0);
+
+ return report_result(PSCI_E_ALREADY_ON, psci_ret);
+}
+
+/*
+ * @Test_Aim@ Hotplug request on a CPU which is already powered on
+ *
+ * 1) Power on all CPUs.
+ * 2) Each CPU re-issues the PSCI CPU_ON request on itself. This is expected to
+ * fail and the PSCI implementation is expected to report that CPUs are
+ * already powered on.
+ *
+ * The test is skipped if an error is encountered during the bring-up of
+ * non-lead CPUs.
+ */
+test_result_t test_psci_cpu_hotplug_plugged(void)
+{
+ unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int cpu_mpid, cpu_node;
+ int psci_ret;
+ unsigned int core_pos;
+
+ /* Power on all CPUs */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU as it is already powered on */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) reissue_cpu_hotplug, 0);
+ if (psci_ret != PSCI_E_SUCCESS)
+ return TEST_RESULT_SKIPPED;
+
+ /* Wait for the CPU to enter the test */
+ core_pos = platform_get_core_pos(cpu_mpid);
+ tftf_wait_for_event(&entered_test[core_pos]);
+ }
+
+ return reissue_cpu_hotplug();
+}
+
+/*
+ * @Test_Aim@ Hotplug request on a CPU that doesn't exist
+ *
+ * Such a hotplug request is expected to fail and the PSCI implementation is
+ * expected to report that the parameters are invalid.
+ */
+test_result_t test_psci_cpu_hotplug_invalid_cpu(void)
+{
+ int psci_ret;
+
+ /*
+ * 0xFFFFFFFF is an invalid MPID.
+ * Pass a valid entry point address to make sure that the call does not
+ * fail for the wrong reason.
+ */
+ psci_ret = tftf_psci_cpu_on(0xFFFFFFFF,
+ (uintptr_t) test_psci_cpu_hotplug_invalid_cpu, 0);
+
+ return report_result(PSCI_E_INVALID_PARAMS, psci_ret);
+}
+
+/*
+ * @Test_Aim@ Hotplug request on a CPU with invalid entrypoint address
+ *
+ * Such a hotplug request is expected to fail and the PSCI implementation is
+ * expected to report that the entrypoint is invalid address for PSCI 1.0
+ * onwards
+ */
+test_result_t test_psci_cpu_hotplug_invalid_ep(void)
+{
+ int psci_ret;
+ unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int cpu_mpid, cpu_node;
+ unsigned int psci_version;
+
+ psci_version = tftf_get_psci_version();
+
+ if (!(psci_version & PSCI_MAJOR_VER_MASK)) {
+ tftf_testcase_printf(
+ "PSCI Version is less then 1.0\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* Power on all CPUs */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU as it is already powered on */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ /*
+ * Here we need to bypass the framework and issue the SMC call
+ * directly from the test case itself as tftf_cpu_on calls SMC
+ * calls with hotplug as entry point. tftf_psci_cpu_on() is a
+ * simple wrapper over the SMC call.
+ *
+ * Entry point address argument can be any invalid address.
+ */
+
+ psci_ret = tftf_psci_cpu_on(cpu_mpid, 0, 0);
+ if (psci_ret != PSCI_E_INVALID_ADDRESS) {
+ tftf_testcase_printf("CPU:0x%x Expected: %i Actual: %i\n",
+ cpu_mpid,
+ PSCI_E_INVALID_ADDRESS,
+ psci_ret);
+ return TEST_RESULT_FAIL;
+ }
+ }
+
+ return TEST_RESULT_SUCCESS;
+}