summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2014-10-15 15:13:29 +0100
committerSandrine Bailleux <sandrine.bailleux@arm.com>2014-10-15 15:33:36 +0100
commit3fc8e6cfabfb95621847c8e5e11a8d2d4eca4a5b (patch)
tree51e3a141378fbeba00087f16541deb0ca796b08c /framework
parent805d828a79e83908ba97100e86fa3b950883c11a (diff)
Remove dispatcher and TFTF state machine
* Remove synchronisations based on the TFTF state machine * Remove task dispatcher Also: * Do not power up secondary CPUs in the framework, the test will be responsible of powering up the cores it needs. * Disable hotplug support for now, the warm boot path code needs to be reworked. Secondary CPUs can still be powered on but they will spin forever in the framework and won't be let in the test. Change-Id: I29c54b31be148a8dd0a4be618e25fd596813d172
Diffstat (limited to 'framework')
-rw-r--r--framework/dispatch.c465
-rw-r--r--framework/framework.mk1
-rw-r--r--framework/helpers.c20
-rw-r--r--framework/include/dispatcher.h83
-rw-r--r--framework/include/tests_api.h64
-rw-r--r--framework/include/tftf.h24
-rw-r--r--framework/main.c196
7 files changed, 22 insertions, 831 deletions
diff --git a/framework/dispatch.c b/framework/dispatch.c
deleted file mode 100644
index 8cfd3bb..0000000
--- a/framework/dispatch.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/** @file
-*
-* Copyright (c) 2013-2014, ARM Limited. All rights reserved.
-*
-* This program and the accompanying materials
-* are licensed and made available under the terms and conditions of the BSD License
-* which accompanies this distribution. The full text of the license may be found at
-* http://opensource.org/licenses/bsd-license.php
-*
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-*
-**/
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <arch_helpers.h>
-#include <mmio.h>
-#include <platform.h>
-#include <platform_def.h>
-
-#include <tftf.h>
-#include <dispatcher.h>
-
-#if DEBUG_TFTF_STATE_MACHINE
-static const char *state_str(TFTF_TASK_STATE state)
-{
- switch (state) {
- case TFTF_TASK_OFF:
- return "OFF";
-
- case TFTF_TASK_ARCH_INIT:
- return "ARCH_INIT";
-
- case TFTF_TASK_SETUP:
- return "SETUP";
-
- case TFTF_TASK_WAITING:
- return "WAITING";
-
- case TFTF_TASK_RUNNING:
- return "RUNNING";
-
- case TFTF_TASK_COMPLETED:
- return "COMPLETED";
-
- default:
- return "INVALID";
- }
-}
-
-static char *states_mask_str(TFTF_TASK_STATE states_mask, char *str)
-{
- assert(str);
- str[0] = 0;
-
- for (unsigned int i = 0; i < TFTF_TASK_INVALID_ID; ++i) {
- if (states_mask & (1 << i)) {
- strcat(str, state_str(1 << i));
- strcat(str, " ");
- }
- }
-
- return str;
-}
-#endif /* DEBUG_TFTF_STATE_MACHINE */
-
-TASK_ENTRY mp_task_entries[PLATFORM_CORE_COUNT];
-
-// Store the MPID of the CPU assuming the dispatcher role for the current test.
-// TODO: Remove this variable when we'll have the test definition in place. At
-// this point, we won't need this variable anymore because the dispatcher MPID
-// will be read directly from the test definition.
-volatile unsigned int dispatcher_mpid;
-
-bool i_am_dispatcher(void) {
- unsigned int mpid = read_mpidr() & 0x00FFFFFF;
- assert(tftf_task_get_state() == TFTF_TASK_SETUP);
- return mpid == dispatcher_mpid;
-}
-
-#if TEST_JUNO_DISPATCHER
-/*
- * Artificially update the dispatcher.
- * This function is very juno-specific, it is just there for test purpose.
- * In the future, we will get this information from the test definition.
- * In the meantime, we'll just nominate a different CPU for each new test
- * so that we can exercise the TFTF on all CPUs.
- * TODO: Remove this function once it is no longer needed.
- */
-void update_dispatcher(void)
-{
- static unsigned int mpids[] = { 0, 1, 0x100, 0x101, 0x102, 0x103 };
- static int new_dispatcher_index = 0;
-
- /*
- * ToDo: It is possible that the dispatcher may migrate to a different
- * core. However, all cores have now been shutdown (except the current
- * dispatcher).
- *
- * Therefore:
- * - before migrating, the new dispatcher must be switched on
- * - after migrating, the old dispatcher must be switched off
- */
-
- dispatcher_mpid = mpids[new_dispatcher_index];
- new_dispatcher_index = (new_dispatcher_index + 1) % 6;
- dsb();
-}
-#endif /* TEST_JUNO_DISPATCHER */
-
-/*
- * Bring up all the cores for executing a test case.
- * This function presumes that all cores except the current one are off.
- */
-STATUS tftf_bring_up_cores(void)
-{
- STATUS status = STATUS_SUCCESS;
- unsigned int aff0_count;
- unsigned int aff1_count;
- unsigned int cluster;
- unsigned int cores;
- unsigned int mpidr;
-
- aff1_count = plat_get_aff_count(1, 0x00);
-
- for (cluster = 0; cluster < aff1_count; cluster++) {
- aff0_count = plat_get_aff_count(0, cluster << MPIDR_AFF1_SHIFT);
- for (cores = 0; cores < aff0_count; cores++) {
- mpidr = cluster << MPIDR_AFF1_SHIFT | cores;
- if (mpidr == (read_mpidr() & 0xFFFFFF))
- continue;
- status = tftf_enable_core(platform_get_core_pos(mpidr));
- if (status != STATUS_SUCCESS)
- mp_printf("Error: Failed to enable core %d"
- " (status=%d)\n", mpidr, status);
- }
- }
- return status;
-}
-
-/*
- * Shutdown all cpus *EXCEPT* the dispatcher
- */
-STATUS tftf_shutdown_all_other_cores(void)
-{
- unsigned my_core_pos = tftf_platform_core_whoami();
- STATUS status = STATUS_SUCCESS;
-
- for (unsigned int core_pos = 0; core_pos < PLATFORM_CORE_COUNT; core_pos++) {
- if ((i_am_dispatcher()) && (core_pos == my_core_pos)) {
- /*
- * The dispatcher can not shut down.
- * Skip to the next core.
- */
- continue;
- }
-
- /*
- * Shut down all non-dispatcher cores,
- * This ensures all tests consistently start
- * from the same initial state.
- */
- status = tftf_disable_core(core_pos);
- if (status != STATUS_SUCCESS) {
- mp_printf("Error: Failed to disable core %d (status=%d).\n",
- core_pos, status);
- /*
- * Continue shutting down the remaining cores.
- */
- }
- }
-
- return status;
-}
-
-
-STATUS tftf_dispatcher_init(void) {
- /*
- * Consider all cores but the primary as OFF.
- */
- memset(mp_task_entries, 0, PLATFORM_CORE_COUNT * sizeof(TASK_ENTRY));
- for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++)
- mp_task_entries[i].state = TFTF_TASK_OFF;
-
- tftf_task_change_state(TFTF_TASK_OFF, TFTF_TASK_ARCH_INIT);
-
- /*
- * Let's say the dispatcher for the 1st test is the primary core.
- * TODO: read the test definition to know the actual dispatcher for the
- * first test.
- */
- dispatcher_mpid = read_mpidr() & 0xFFFFFF;
- dsb();
-
- return STATUS_SUCCESS;
-}
-
-void tftf_task_set_state(TFTF_TASK_STATE state) {
- unsigned iam;
-
- assert((state != 0) && (state <= (1 << TFTF_TASK_INVALID_ID)));
-
- iam = tftf_platform_core_whoami();
- mp_task_entries[iam].state = state;
- dsb();
-}
-
-TFTF_TASK_STATE tftf_task_get_state(void) {
- unsigned iam = tftf_platform_core_whoami();
- return mp_task_entries[iam].state;
-}
-
-void tftf_task_signal_state(TFTF_TASK_STATE state) {
- tftf_task_set_state(state);
- sev();
-}
-
-void tftf_task_wait_state(unsigned core_pos, TFTF_TASK_STATE state_mask) {
- TFTF_TASK_STATE current_state;
-
- assert(state_mask != 0);
-
-#if DEBUG_TFTF_STATE_MACHINE
- {
- char str[128];
- mp_printf("Waiting for CPU 0x%.4x to reach any of these states: %s\n",
- tftf_platform_core_pos_to_mpid(core_pos),
- states_mask_str(state_mask, str));
- }
-#endif /* DEBUG_TFTF_STATE_MACHINE */
-
- current_state = (TFTF_TASK_STATE)mmio_read_64((UINTN)&(mp_task_entries[core_pos].state));
- while ((current_state & state_mask) == 0) {
- wfe();
- current_state = (TFTF_TASK_STATE)mmio_read_64((UINTN)&(mp_task_entries[core_pos].state));
- }
-}
-
-void tftf_task_change_state(TFTF_TASK_STATE old_state, TFTF_TASK_STATE new_state)
-{
-#if DEBUG_TFTF_STATE_MACHINE
- mp_printf("state: %s -> %s\n", state_str(old_state), state_str(new_state));
- if (tftf_task_get_state() != old_state)
- mp_printf("ERROR: wrong state, expected %u, got %u\n", old_state,
- tftf_task_get_state());
-#endif /* DEBUG_TFTF_STATE_MACHINE */
- assert(tftf_task_get_state() == old_state);
- tftf_task_signal_state(new_state);
-}
-
-TEST_RESULT tftf_dispatch_task_single_core_pos(unsigned core_pos,
- TFTF_TASK task,
- void* arguments,
- int wait)
-{
- unsigned iam = tftf_platform_core_whoami();
- unsigned i;
-
- /*
- * Check if this core is present in the device
- */
- if (!tftf_platform_is_core_pos_present(core_pos))
- return TEST_RESULT_CORE_NOT_PARTICIPATING;
-
- // If we start the task on ourself then we just run it and return the result
- if (core_pos == iam) {
- TEST_RESULT res;
- assert(tftf_task_get_state() == TFTF_TASK_WAITING);
- res = task(core_pos, arguments);
- if (wait)
- tftf_task_signal_state(TFTF_TASK_WAITING);
- else
- tftf_task_signal_state(TFTF_TASK_COMPLETED);
- return res;
- }
-
- // The targeted core should already be ON
- assert(tftf_is_core_enabled(core_pos));
-
- // Ensure there are no pending jobs
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- assert(mp_task_entries[i].task == NULL);
- }
-
- // Ensure the core is waiting for a new task
- tftf_task_wait_state(core_pos, TFTF_TASK_WAITING);
-
- // Set the parameters for the current job
- mp_task_entries[core_pos].result = TEST_RESULT_NOT_STARTED;
- mp_task_entries[core_pos].arguments = arguments;
- mp_task_entries[core_pos].task = task;
- dsb();
-
- // Trigger the task
- sev();
-
- if (wait) {
- // Wait for the task to complete
- tftf_task_wait_state(core_pos, TFTF_TASK_COMPLETED);
-
- // Acknowledge the completion to allow the secondary core to receive new task
- mp_task_entries[core_pos].task = NULL;
- dsb();
- sev();
-
- return mp_task_entries[core_pos].result;
- } else {
- return TEST_RESULT_SUCCESS;
- }
-}
-
-unsigned extract_cores_mask(unsigned cores_mask)
-{
- unsigned i;
- unsigned participating_mask = 0;
-
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if ((cores_mask & (1 << i)) &&
- tftf_platform_is_core_pos_present(i)) {
- /*
- * Add this core to the participating mask.
- */
- participating_mask = participating_mask | (1 << i);
- }
- }
-
- return participating_mask;
-}
-
-TEST_RESULT tftf_dispatch_task_multi_core_pos(unsigned cores_mask,
- TFTF_TASK task,
- void* arguments,
- int wait)
-{
- unsigned iam = tftf_platform_core_whoami();
- unsigned i;
- unsigned participating_mask;
-
- /*
- * Parallel execution of multiple test cases is not supported.
- * Only one test case can run at any time.
- * Ensure there are no pending jobs on any core.
- */
- for (i = 0; i < PLATFORM_CORE_COUNT; i++)
- assert(mp_task_entries[i].task == NULL);
-
- /* Get the real cores present in the system */
- participating_mask = extract_cores_mask(cores_mask);
-
- /*
- * Check if there are any cores to receive the task.
- * If not, then the test can not run.
- */
- if (participating_mask == 0)
- return TEST_RESULT_CORE_NOT_PARTICIPATING;
-
- /*
- * Ensure the participating cores are ON & waiting for a new task.
- */
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if (participating_mask & (1 << i)) {
- assert(tftf_is_core_enabled(i));
- tftf_task_wait_state(i, TFTF_TASK_WAITING);
- }
- }
-
- /*
- * Set the parameters for the current job
- */
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if (participating_mask & (1 << i)) {
- mp_task_entries[i].result = TEST_RESULT_NOT_STARTED;
- mp_task_entries[i].arguments = arguments;
- mp_task_entries[i].task = task;
- }
- }
- dsb();
- /*
- * Start running the task on the other cores,
- * by triggering an event.
- */
- sev();
-
- /*
- * Start running the task on this core,
- * if this core is also participating.
- */
- if (participating_mask & (1 << iam)) {
- if (task == END_OF_TEST)
- mp_task_entries[iam].result = TEST_RESULT_SUCCESS;
- else
- mp_task_entries[iam].result = task(iam, arguments);
-
- /*
- * By now the task running on this core will have completed.
- */
- mp_task_entries[iam].task = 0;
- tftf_task_change_state(TFTF_TASK_WAITING, TFTF_TASK_COMPLETED);
- }
-
- if (wait)
- tftf_wait_until_task_completed(participating_mask);
-
- return TEST_RESULT_SUCCESS;
-}
-
-TEST_RESULT tftf_wait_until_task_completed(int cores_mask) {
- unsigned iam = tftf_platform_core_whoami();
- unsigned i;
- unsigned participating_mask;
-
- /* Get the real participating cores */
- participating_mask = extract_cores_mask(cores_mask);
-
- /*
- * Check if there are any cores to receive the task.
- * If not, then there is no reason to wait.
- */
- if (participating_mask == 0)
- return TEST_RESULT_CORE_NOT_PARTICIPATING;
-
- /*
- * Wait until all the other participating cores have completed
- * the dispatched task.
- */
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if (participating_mask & (1 << i)) {
- /*
- * Wait for the task to complete
- */
- tftf_task_wait_state(i, TFTF_TASK_COMPLETED);
-
- /*
- * Acknowledge the task completion
- * by clearing the task entry.
- * This will allow the participating cores
- * to receive a new task.
- */
- mp_task_entries[i].task = NULL;
- dsb();
- sev();
- }
- }
-
- /*
- * Move the state machine to TASK_WAITING, but only for this core
- */
- if (cores_mask & (1 << iam))
- tftf_task_change_state(TFTF_TASK_COMPLETED, TFTF_TASK_WAITING);
-
- /*
- * If any core has failed this task then return
- * the first error message we encounter.
- * All other error messages will be lost.
- */
- for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if (mp_task_entries[i].result != TEST_RESULT_SUCCESS)
- return mp_task_entries[i].result;
- }
-
- return TEST_RESULT_SUCCESS;
-}
diff --git a/framework/framework.mk b/framework/framework.mk
index 9cef8bd..33f212b 100644
--- a/framework/framework.mk
+++ b/framework/framework.mk
@@ -42,7 +42,6 @@ FRAMEWORK_SOURCES := ${AUTOGEN_DIR}/tests_list.c \
framework/aarch64/exceptions.S \
framework/debug.c \
framework/delay.c \
- framework/dispatch.c \
framework/helpers.c \
framework/irq.c \
framework/main.c \
diff --git a/framework/helpers.c b/framework/helpers.c
index 4bd9070..62f008f 100644
--- a/framework/helpers.c
+++ b/framework/helpers.c
@@ -25,7 +25,6 @@
#include <spinlock.h>
#include <debug.h>
#include <psci.h>
-#include <dispatcher.h>
#include <nvm.h>
extern unsigned long __COHERENT_RAM_START__;
@@ -331,14 +330,10 @@ STATUS tftf_enable_core(unsigned core_pos)
return (psci_ret == PSCI_E_SUCCESS) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
}
-static TEST_RESULT tftf_disable_secondary(unsigned core_pos, void* argument)
+TEST_RESULT tftf_disable_secondary(unsigned core_pos, void *argument)
{
uint32_t psci_ret;
- // Clear our task - when we will turn off the core we will ensure the
- // view is coherent to the other cores.
- mp_task_entries[core_pos].task = 0;
-
/*
* Do the bare minimal to turn off this cpu i.e. turn off
* interrupts, disable the gic cpu interface
@@ -346,9 +341,6 @@ static TEST_RESULT tftf_disable_secondary(unsigned core_pos, void* argument)
disable_irq();
arm_gic_cpuif_deactivate();
- // Signal we are off
- tftf_task_change_state(TFTF_TASK_RUNNING, TFTF_TASK_OFF);
-
psci_ret = tftf_psci_cpu_off();
/*
@@ -376,21 +368,11 @@ STATUS tftf_disable_core(unsigned core_pos)
return STATUS_SUCCESS;
}
- // Ensure the core is ready to receive the shutdown task
- tftf_task_wait_state(core_pos, TFTF_TASK_WAITING);
-
- // Set the disable function for the targeted task
- mp_task_entries[core_pos].task = tftf_disable_secondary;
dsb();
// Trigger the task
sev();
- // Wait for the disabling operation to be completed
- tftf_task_wait_state(core_pos, TFTF_TASK_OFF);
- while (tftf_is_core_enabled(core_pos))
- continue;
-
return STATUS_SUCCESS;
}
diff --git a/framework/include/dispatcher.h b/framework/include/dispatcher.h
deleted file mode 100644
index 8cf155b..0000000
--- a/framework/include/dispatcher.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/** @file
-*
-* Copyright (c) 2013, ARM Limited. All rights reserved.
-*
-* This program and the accompanying materials
-* are licensed and made available under the terms and conditions of the BSD License
-* which accompanies this distribution. The full text of the license may be found at
-* http://opensource.org/licenses/bsd-license.php
-*
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-*
-**/
-
-#ifndef __DISPATCHER_H__
-#define __DISPATCHER_H__
-
-
-#ifndef __ASSEMBLY__
-
-#include <tftf_common.h>
-
-/* State machine states */
-
-/*
- * State when the core is off from the TFTF's point of view.
- * It means that the core is either physically off or it is running in the
- * trusted firmware in secure world and hasn't switched to the TFTF in the
- * normal world yet.
- */
-#define TFTF_TASK_OFF (1 << 0)
-
-/*
- * State when the core is initializing its architectural state.
- * The core will move to TFTF_TASK_SETUP state once it has finished the
- * architectural setup.
- */
-#define TFTF_TASK_ARCH_INIT (1 << 1)
-
-/*
- * State when the core looks at the test definition to figure out whether it's
- * going to be the dispatcher or a slave for the next test.
- * The core will move to TFTF_TASK_WAITING state once it knows its role.
- * The dispatcher won't submit any job to the slaves until it has confirmation
- * that all cores have figured out their role.
- */
-#define TFTF_TASK_SETUP (1 << 2)
-
-/*
- * State when the core is ready to receive a task to execute.
- * Both the dispatcher and the slaves can enter this state since a task
- * can be executed on the dispatcher as well.
- *
- * From there, the core can move to 2 states:
- * - TFTF_TASK_RUNNING if the core received a task to execute;
- * - TFTF_TASK_SETUP if the current test is finished and therefore the
- * core should read the next test definition.
- */
-#define TFTF_TASK_WAITING (1 << 3)
-
-/*
- * State when a the core is running a task.
- * From there, the core can move to 2 states:
- * - TFTF_TASK_OFF if the task implies to power off the core.
- * - TFTF_TASK_COMPLETED otherwise, once the task has completed (should it be
- * a test success or failure).
- */
-#define TFTF_TASK_RUNNING (1 << 4)
-
-/*
- * State when the core just completed a task.
- * The core will move to TFTF_TASK_WAITING once the dispatcher has acknowledged
- * the completion of the test (by clearing TASK_ENTRY.task != NULL).
- */
-#define TFTF_TASK_COMPLETED (1 << 5)
-
-#define TFTF_TASK_INVALID_ID 6
-
-/* MPCore wrapper */
-STATUS tftf_dispatcher_init(void);
-#endif /* __ASSEMBLY__ */
-
-#endif /* __DISPATCHER_H__ */
diff --git a/framework/include/tests_api.h b/framework/include/tests_api.h
index f8f7bfc..5028df6 100644
--- a/framework/include/tests_api.h
+++ b/framework/include/tests_api.h
@@ -114,70 +114,6 @@ typedef enum {
*/
typedef TEST_RESULT (*TFTF_TASK)(unsigned core_pos, void *argument);
-/*
- * Dispatch a task on a single CPU.
- *
- * core_pos Linear id of the CPU to dispatch the task on.
- * Note that the list of cpus present in the system overrules this
- * id. If this cpu is not present in the system then no tasks will
- * be dispatched to it, even when requested explicitly.
- * This affords the caller the flexibility of writing tests without
- * being aware of the exact platform topology.
- * task The task to dispatch
- * arguments Arguments to pass to the task function pointer
- * wait Boolean stating whether the function should be blocking or not,
- * i.e. whether it should wait for the task to complete before
- * returning or not
- */
-TEST_RESULT tftf_dispatch_task_single_core_pos(unsigned core_pos,
- TFTF_TASK task,
- void *arguments,
- int wait);
-
-/*
- * Dispatch a task on several CPUs.
- * All CPUs involved will execute the task at the same time.
- *
- * cores_mask Bitmask of CPUs to receive this task.
- * This bitmask is useful for dispatching a test to a subset of
- * the CPUs present in the system.
- * Note that the list of cpus present in the system overrules the
- * bitmask. If a cpu is not present in the system no tasks will be
- * dispatched to it, even if the bitmask includes the cpu for
- * dispatching tasks.
- * This allows the caller to assert all bits in the mask to
- * include all cpus, even if the caller is unaware of the exact
- * platform topology.
- * task The task to dispatch
- * arguments Arguments to pass to the task function pointer
- * wait Boolean stating whether the function should be blocking or not,
- * i.e. whether it should wait for the task to complete before
- * returning or not
- */
-TEST_RESULT tftf_dispatch_task_multi_core_pos(unsigned cores_mask,
- TFTF_TASK task,
- void *arguments,
- int wait);
-
-/*
- * Wait for a task to finish on some CPUs.
- * It is mandatory to call this function in case tftf_dispatch_task*()
- * has been previously called with wait=0.
- *
- * cores_mask Bitmask of CPUs to receive this task.
- * This bitmask is useful for dispatching a test to a subset of
- * the CPUs.
- *
- */
-TEST_RESULT tftf_wait_until_task_completed(int cores_mask);
-
-/*
- * This functions generates a core mask of all the cores present
- * in the system with each bit from 0, signifying the presence
- * of a core at that linear ID.
- */
-unsigned extract_cores_mask(unsigned cores_mask);
-
void tftf_hotplug_entry(void);
bool tftf_is_core_enabled(unsigned int core_pos);
diff --git a/framework/include/tftf.h b/framework/include/tftf.h
index 9b0640c..d3de9d5 100644
--- a/framework/include/tftf.h
+++ b/framework/include/tftf.h
@@ -27,19 +27,14 @@
/* Maximum size of test output (in bytes) */
#define TESTCASE_OUTPUT_MAX_SIZE 512
-#define END_OF_TEST ((TFTF_TASK)-1)
-
#define TEST_REPORT_FORMAT_RAW 0
#define TEST_REPORT_FORMAT_JUNIT 1
-typedef unsigned TFTF_TASK_STATE;
-
extern const char build_message[];
typedef TEST_RESULT (*TESTCASE_FUNC)(void);
typedef struct {
- TFTF_TASK_STATE state;
TFTF_TASK task;
TEST_RESULT result;
void* arguments;
@@ -114,22 +109,6 @@ STATUS tftf_testcase_set_result(const TESTCASE* testcase, TEST_RESULT result, co
STATUS tftf_testcase_get_result(const TESTCASE* testcase, TESTCASE_RESULT *result, char *test_output);
STATUS tftf_testcase_update_result(const TESTCASE* testcase, TEST_RESULT result);
-bool i_am_dispatcher(void);
-
-void tftf_task_set_state(TFTF_TASK_STATE state);
-void tftf_task_signal_state(TFTF_TASK_STATE state);
-void tftf_task_wait_state(unsigned core_pos, TFTF_TASK_STATE state_mask);
-TFTF_TASK_STATE tftf_task_get_state(void);
-// Change the core state from 'old_state' to 'new_state'.
-// In debug builds, this function will check the core is indeed in 'old_state'
-// before switching to 'new_state' and trigger an assertion if not.
-// The goal of this function is also to clarify the code by helping to keep
-// track of the execution flow.
-void tftf_task_change_state(TFTF_TASK_STATE old_state,
- TFTF_TASK_STATE new_state);
-
-extern TASK_ENTRY mp_task_entries[];
-
typedef unsigned TEST_REPORT_FORMAT;
void tftf_report_generate(void);
@@ -142,9 +121,6 @@ void tftf_register_gic_id(void);
uint8_t tftf_get_gic_cpu_id_from_mpidr(unsigned long mpidr);
uint8_t tftf_get_cpu_id_from_gic_id(uint8_t gic_id);
-STATUS tftf_bring_up_cores(void);
-STATUS tftf_shutdown_all_other_cores(void);
-
/* Print a debug message */
#if DEBUG
#define pr_debug(...) mp_printf(__VA_ARGS__)
diff --git a/framework/main.c b/framework/main.c
index aa8ddd8..9b79cc9 100644
--- a/framework/main.c
+++ b/framework/main.c
@@ -27,19 +27,9 @@
#include <platform.h>
#include <platform_def.h>
#include <mmio.h>
-#include <dispatcher.h>
#include <nvm.h>
#include <tests_api.h>
-void main_test_loop(void);
-void auxiliary_test_loop(void);
-
-/* Hack: silent debug messages related to the dispatcher */
-#ifndef DEBUG_DISPATCHER
-#undef pr_debug
-#define pr_debug(...) /* do nothing */
-#endif
-
// Index of the current testsuite and the current testcase.
unsigned int cur_testsuite;
unsigned int cur_testcase;
@@ -66,8 +56,6 @@ static char *testcase_output_ptr;
static spinlock_t testcase_output_lock;
-#define GET_TASK(core_pos) (TFTF_TASK)mmio_read_64((UINTN)&(mp_task_entries[core_pos].task))
-
void tftf_testcase_output(const char* string) {
unsigned string_length = strlen(string);
@@ -76,7 +64,7 @@ void tftf_testcase_output(const char* string) {
/* If the pointer is outside of the buffer do not copy the output */
if (testcase_output_ptr >=
testcase_output + TESTCASE_OUTPUT_MAX_SIZE) {
- printf("Warning: the buffer cannot handle the test output.\n");
+ mp_printf("Warning: the buffer cannot handle the test output\n");
/* TESTCASE_OUTPUT_MAX_SIZE could need to be increased */
goto release_lock;
}
@@ -169,139 +157,32 @@ static const TESTCASE *move_to_next_test(void) {
return current_testcase();
}
-// That's where the real work begins.
-// All CPUs enter this function once they have finished their initialisations.
-void main_test_loop(void)
+void run_tests(void)
{
- while (1) {
- if (i_am_dispatcher()) {
- pr_debug("I am the dispatcher!\n");
+ while (1) {
+ mp_printf("Starting unittest '%s - %s'\n",
+ current_testsuite()->name, current_testcase()->name);
- tftf_task_change_state(TFTF_TASK_SETUP, TFTF_TASK_WAITING);
+ tftf_testcase_start(current_testcase());
- /* Boot all the cores in the device */
- tftf_bring_up_cores();
-
- for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++) {
- if (tftf_platform_is_core_pos_present(i))
- tftf_task_wait_state(i, TFTF_TASK_WAITING);
+ /* The test is finished, let's move to the next one, if any */
+ if (move_to_next_test() == NULL)
+ break;
}
- printf("Starting unittest '%s - %s'\n",
- current_testsuite()->name, current_testcase()->name);
- tftf_testcase_start(current_testcase());
-
- /*
- * TODO: Ensure all CPUs are in the WAITING state, otherwise it means
- * the test function is not well written.
- */
-
-#if TEST_JUNO_DISPATCHER
- void update_dispatcher(void);
- update_dispatcher();
-#endif /* TEST_JUNO_DISPATCHER */
-
- /* Dispatch the END_OF_TEST special task to signal the end of the test */
- tftf_dispatch_task_multi_core_pos(~0,
- END_OF_TEST,
- NULL,
- 1);
- tftf_task_change_state(TFTF_TASK_WAITING, TFTF_TASK_SETUP);
-
- /* ToDo: Check for tests in progress (submitted with wait) before shutdown */
-
- /* Tests have completed, shutdown all cores except the dispatcher */
- tftf_shutdown_all_other_cores();
-
- /* The test is finished, let's move to the next one, if any */
- if (move_to_next_test() == NULL)
- break;
-
- } else {
- /* I am not the dispatcher */
- auxiliary_test_loop();
- }
- }
-
- /*
- * Test session has finished.
- * Only the dispatcher will execute the following code.
- * All other cores have been shut down.
- */
-
- // Generate the test report
- tftf_report_generate();
+ /*
+ * Test session has finished.
+ * Let's generate the test report.
+ */
+ tftf_report_generate();
}
-void auxiliary_test_loop(void)
-{
- TFTF_TASK task = NULL;
- unsigned int mpid, core_pos;
-
- mpid = read_mpidr();
- core_pos = platform_get_core_pos(mpid);
-
- // Signal that we are ready to receive tasks
- tftf_task_change_state(TFTF_TASK_SETUP, TFTF_TASK_WAITING);
-
- while (task != END_OF_TEST) {
- /* The dispatcher CPU will send an event to signal the task dispatching */
- wfe();
- dsb();
-
- task = GET_TASK(core_pos);
-
- if (task != NULL) {
- if (task != END_OF_TEST) {
- // We are going to start the task
- tftf_task_change_state(TFTF_TASK_WAITING, TFTF_TASK_RUNNING);
-
- // Run the test
- mp_task_entries[core_pos].result = task(core_pos, mp_task_entries[core_pos].arguments);
-
- // Signal we have completed the task
- tftf_task_change_state(TFTF_TASK_RUNNING, TFTF_TASK_COMPLETED);
- } else {
- /* Nothing to execute, signal the task is completed */
- tftf_task_change_state(TFTF_TASK_WAITING, TFTF_TASK_COMPLETED);
- }
-
- // Wait for the dispatcher to acknowledge that we completed the test.
- // It will do so by resetting our task pointer.
- task = GET_TASK(core_pos);
- while (task != NULL) {
- wfe();
- task = GET_TASK(core_pos);
- }
-
- if (task != END_OF_TEST) {
- // Signal we are ready to receive a new task.
- tftf_task_change_state(TFTF_TASK_COMPLETED, TFTF_TASK_WAITING);
- } else {
- tftf_task_change_state(TFTF_TASK_COMPLETED, TFTF_TASK_SETUP);
- }
- }
-
- /*
- * All other events are spurious, ignore them and wait for meaningful
- * events.
- */
- }
-}
void tftf_warm_boot_main(void)
{
- unsigned int primary_core_mpid, primary_core_pos;
- unsigned int rc;
+ int rc;
tftf_arch_setup();
-
- /*
- * Enable this debug printf to trace the test progress.
- * It may generate a lot of messages so it is commented out by default.
- */
- /* pr_debug("Entering TFTF: tftf_warm_boot_main\n"); */
-
tftf_register_gic_id();
arm_gic_cpuif_setup();
@@ -315,35 +196,11 @@ void tftf_warm_boot_main(void)
enable_irq();
- /*
- * Before changing the state of the secondary core, we need to wait for the
- * primary core to have initialised its internal dispatcher data structure.
- * Without this synchronisation point, secondary cores might reach this
- * function before the primary core initialised the mp_task_entries[] array
- * in tftf_dispatcher_init() and so their state will be overwritten.
- */
- primary_core_mpid = platform_get_primary_core_mpid();
- primary_core_pos = platform_get_core_pos(primary_core_mpid);
- tftf_task_wait_state(primary_core_pos, TFTF_TASK_ARCH_INIT | TFTF_TASK_SETUP |
- TFTF_TASK_WAITING);
-
- // State initialization
- tftf_task_change_state(TFTF_TASK_OFF, TFTF_TASK_ARCH_INIT);
-
- // Signal we are ready to start the test session.
- tftf_task_change_state(TFTF_TASK_ARCH_INIT, TFTF_TASK_SETUP);
-
- // Wait for the primary core to finish all its initialisations, including the
- // dispatcher internal structure initialisations.
- tftf_task_wait_state(primary_core_pos, TFTF_TASK_SETUP | TFTF_TASK_WAITING);
-
- /*
- * Always go to the main test loop.
- * One of the secondary cores may be the dispatcher,
- * so go to the main_test_loop.
- * Do not presume that this core will jump to the auxiliary_test_loop.
- */
- main_test_loop();
+ /* TODO: Let the core in the test session */
+ /* For now, make it spin in an infinite loop */
+ pr_debug("CPU initialised, now spin in a loop\n");
+ while (1)
+ continue;
}
void tftf_cold_boot_main(void)
@@ -376,13 +233,6 @@ void tftf_cold_boot_main(void)
tftf_abort();
}
- // Initialize the dispatcher
- status = tftf_dispatcher_init();
- if (status != STATUS_SUCCESS) {
- printf("Error: Failed to initialize the task dispatcher (%d).\n", status);
- tftf_abort();
- }
-
// Initialize NVM if necessary.
status = tftf_init_nvm();
if (status != STATUS_SUCCESS) {
@@ -426,13 +276,9 @@ void tftf_cold_boot_main(void)
tftf_testcase_set_result_as_crashed(crashed_testcase_function);
}
- // Signal the secondary CPUs that the primary has finished all initialisations
- // and the test session can begin.
- tftf_task_change_state(TFTF_TASK_ARCH_INIT, TFTF_TASK_SETUP);
-
enable_irq();
- main_test_loop();
+ run_tests();
clean_nvm:
if (tftf_clean_nvm() != STATUS_SUCCESS)