fix(hftest): define stacks for all secondary cores

The hftest common libraries was reusing the same stack section
for all secondary cores.
This means some tests would fail unexpectidly.

Adding a function to common.c and service_common.c, which have
the same purpose in the target they are used in, to retrieve
the buffers for the secondary core stacks defined globally.

Signed-off-by: J-Alves <joao.alves@arm.com>
Signed-off-by: K-Meakin <karl.meakin@arm.com>
Change-Id: If93aed330a88c3b52e5771d09911296f2c6214ed
diff --git a/test/hftest/common.c b/test/hftest/common.c
index 1f85694..7aeda22 100644
--- a/test/hftest/common.c
+++ b/test/hftest/common.c
@@ -27,6 +27,8 @@
 
 static struct hftest_context global_context;
 
+static alignas(PAGE_SIZE) uint8_t secondary_ec_stack[MAX_CPUS][PAGE_SIZE];
+
 struct hftest_context *hftest_get_context(void)
 {
 	return &global_context;
@@ -295,6 +297,12 @@
 	return index;
 }
 
+uint8_t *hftest_get_secondary_ec_stack(size_t id)
+{
+	assert(id < MAX_CPUS);
+	return secondary_ec_stack[id];
+}
+
 /**
  * Get the ID of the CPU with the given index.
  */
diff --git a/test/hftest/power_mgmt.c b/test/hftest/power_mgmt.c
index 7b8c041..787a7fe 100644
--- a/test/hftest/power_mgmt.c
+++ b/test/hftest/power_mgmt.c
@@ -22,12 +22,6 @@
 	struct spinlock lock;
 };
 
-/*
- * Stack for secondary execution contexts.
- * Used in tests for MP partitions where multicore functionality is tested.
- */
-alignas(PAGE_SIZE) uint8_t secondary_ec_stack[MAX_CPUS - 1][PAGE_SIZE];
-
 static noreturn void cpu_entry(uintptr_t arg)
 {
 	/*
@@ -56,18 +50,18 @@
 	arch_cpu_stop();
 }
 
-bool hftest_cpu_start(cpu_id_t id, cpu_entry_point *entry, uintptr_t arg)
+bool hftest_cpu_start(cpu_id_t id, const uint8_t *secondary_ec_stack,
+		      cpu_entry_point *entry, uintptr_t arg)
 {
 	struct cpu_start_state s;
 	struct arch_cpu_start_state s_arch;
-	size_t stack_size = sizeof(secondary_ec_stack[0]);
 
 	/*
 	 * Config for arch_cpu_start() which will start a new CPU and
 	 * immediately jump to cpu_entry(). This function must guarantee that
 	 * the state struct is not be freed until cpu_entry() is called.
 	 */
-	s_arch.initial_sp = (uintptr_t)secondary_ec_stack + stack_size;
+	s_arch.initial_sp = (uintptr_t)secondary_ec_stack;
 	s_arch.entry = cpu_entry;
 	s_arch.arg = (uintptr_t)&s;
 
diff --git a/test/hftest/service_common.c b/test/hftest/service_common.c
index b277b38..f0ab701 100644
--- a/test/hftest/service_common.c
+++ b/test/hftest/service_common.c
@@ -29,6 +29,14 @@
 
 static struct hftest_context global_context;
 
+static alignas(PAGE_SIZE) uint8_t secondary_ec_stack[MAX_CPUS][PAGE_SIZE];
+
+uint8_t *hftest_get_secondary_ec_stack(size_t id)
+{
+	assert(id < MAX_CPUS);
+	return secondary_ec_stack[id];
+}
+
 struct hftest_context *hftest_get_context(void)
 {
 	return &global_context;
diff --git a/test/inc/test/hftest.h b/test/inc/test/hftest.h
index a7f23a6..fe2a074 100644
--- a/test/inc/test/hftest.h
+++ b/test/inc/test/hftest.h
@@ -183,10 +183,13 @@
  * with the provided argument. It is a wrapper around the generic cpu_start()
  * and takes care of MMU initialization.
  */
-bool hftest_cpu_start(cpu_id_t id, void (*entry)(uintptr_t arg), uintptr_t arg);
+bool hftest_cpu_start(cpu_id_t id, const uint8_t *secondary_ec_stack,
+		      void (*entry)(uintptr_t arg), uintptr_t arg);
 
 cpu_id_t hftest_get_cpu_id(size_t index);
 
+uint8_t *hftest_get_secondary_ec_stack(size_t id);
+
 /*
  * The type of CPU entry points: a function that takes one `uintptr_t` argument
  * and returns `void`.
diff --git a/test/vmapi/ffa_secure_partitions/dir_msg.c b/test/vmapi/ffa_secure_partitions/dir_msg.c
index 68a90d7..d5d1ea5 100644
--- a/test/vmapi/ffa_secure_partitions/dir_msg.c
+++ b/test/vmapi/ffa_secure_partitions/dir_msg.c
@@ -160,9 +160,10 @@
 		id = hftest_get_cpu_id(i);
 		HFTEST_LOG("Booting CPU %zu - %lx", i, id);
 
-		EXPECT_EQ(hftest_cpu_start(id, migrate_busy_up_sp,
-					   (uintptr_t)&args),
-			  true);
+		EXPECT_EQ(
+			hftest_cpu_start(id, hftest_get_secondary_ec_stack(i),
+					 migrate_busy_up_sp, (uintptr_t)&args),
+			true);
 
 		HFTEST_LOG("Done with CPU %zu", i);
 	}
diff --git a/test/vmapi/ffa_secure_partitions/notifications.c b/test/vmapi/ffa_secure_partitions/notifications.c
index b50e30e..94e4a81 100644
--- a/test/vmapi/ffa_secure_partitions/notifications.c
+++ b/test/vmapi/ffa_secure_partitions/notifications.c
@@ -205,8 +205,9 @@
 
 		args.vcpu_id = i;
 
-		EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(i), cpu_entry,
-					   (uintptr_t)&args),
+		EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(i),
+					   hftest_get_secondary_ec_stack(i),
+					   cpu_entry, (uintptr_t)&args),
 			  true);
 
 		/* Wait for CPU to release the lock. */
diff --git a/test/vmapi/ffa_secure_partitions/power_mgt.c b/test/vmapi/ffa_secure_partitions/power_mgt.c
index e1feafb..29d7e8e 100644
--- a/test/vmapi/ffa_secure_partitions/power_mgt.c
+++ b/test/vmapi/ffa_secure_partitions/power_mgt.c
@@ -148,8 +148,9 @@
 		 */
 		args.vcpu_id = (ffa_vcpu_index_t)i;
 
-		EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(i), entry,
-					   (uintptr_t)&args),
+		EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(i),
+					   hftest_get_secondary_ec_stack(i),
+					   entry, (uintptr_t)&args),
 			  true);
 
 		/* Wait for CPU to release the lock. */
diff --git a/test/vmapi/ffa_secure_partitions/secure_interrupts.c b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
index da0e171..0f5e3ce 100644
--- a/test/vmapi/ffa_secure_partitions/secure_interrupts.c
+++ b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
@@ -549,8 +549,9 @@
 		args.vcpu_id = i;
 		HFTEST_LOG("Booting CPU %u - %lx", i, cpu_id);
 
-		EXPECT_EQ(hftest_cpu_start(cpu_id, cpu_entry_sp_sleep_loop,
-					   (uintptr_t)&args),
+		EXPECT_EQ(hftest_cpu_start(
+				  cpu_id, hftest_get_secondary_ec_stack(i),
+				  cpu_entry_sp_sleep_loop, (uintptr_t)&args),
 			  true);
 
 		/* Wait for CPU to release the lock. */
diff --git a/test/vmapi/primary_only/faults.c b/test/vmapi/primary_only/faults.c
index 0618674..215aac8 100644
--- a/test/vmapi/primary_only/faults.c
+++ b/test/vmapi/primary_only/faults.c
@@ -70,7 +70,8 @@
 	 * MAX_CPUS - index internally. Since legacy VMs do not follow this
 	 * convention, index 7 is passed into `hftest_cpu_get_id`.
 	 */
-	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(7), rx_reader,
+	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(7),
+				   hftest_get_secondary_ec_stack(0), rx_reader,
 				   (uintptr_t)&s),
 		  true);
 
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 385f312..629f173 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -91,8 +91,9 @@
 	 * MAX_CPUS - index internally. Since legacy VMs do not follow this
 	 * convention, index 7 is passed into `hftest_cpu_get_id`.
 	 */
-	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(7), vm_cpu_entry,
-				   (uintptr_t)&lock),
+	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(7),
+				   hftest_get_secondary_ec_stack(0),
+				   vm_cpu_entry, (uintptr_t)&lock),
 		  true);
 
 	/* Wait for CPU to release the lock. */
@@ -139,6 +140,7 @@
 	sl_lock(&lock);
 	dlog("Starting second CPU.\n");
 	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(secondary_cpu_index),
+				   hftest_get_secondary_ec_stack(0),
 				   vm_cpu_entry_stop, (uintptr_t)&lock),
 		  true);
 
@@ -154,6 +156,7 @@
 
 	dlog("Starting second CPU again.\n");
 	EXPECT_EQ(hftest_cpu_start(hftest_get_cpu_id(secondary_cpu_index),
+				   hftest_get_secondary_ec_stack(0),
 				   vm_cpu_entry_stop, (uintptr_t)&lock),
 		  true);
 
diff --git a/test/vmapi/primary_with_secondaries/dir_msg.c b/test/vmapi/primary_with_secondaries/dir_msg.c
index 5096595..2a632d3 100644
--- a/test/vmapi/primary_with_secondaries/dir_msg.c
+++ b/test/vmapi/primary_with_secondaries/dir_msg.c
@@ -1068,6 +1068,7 @@
 	HFTEST_LOG("Starting secondary core...");
 
 	ASSERT_TRUE(hftest_cpu_start(hftest_get_cpu_id(vcpu_id),
+				     hftest_get_secondary_ec_stack(vcpu_id),
 				     cpu_entry_echo_mp, (uintptr_t)&args));
 
 	/* Wait for secondary core to return before finishing the test. */
@@ -1102,6 +1103,7 @@
 	HFTEST_LOG("Starting secondary core...");
 
 	ASSERT_TRUE(hftest_cpu_start(hftest_get_cpu_id(vcpu_id),
+				     hftest_get_secondary_ec_stack(vcpu_id - 1),
 				     cpu_entry_echo_mp, (uintptr_t)&args));
 
 	/* Wait for secondary core to return before finishing the test. */
diff --git a/test/vmapi/primary_with_secondaries/run_race.c b/test/vmapi/primary_with_secondaries/run_race.c
index 2a6705a..ff4d984 100644
--- a/test/vmapi/primary_with_secondaries/run_race.c
+++ b/test/vmapi/primary_with_secondaries/run_race.c
@@ -111,8 +111,9 @@
 	 * MAX_CPUS - index internally. Since legacy VMs do not follow this
 	 * convention, index 7 is passed into `hftest_cpu_get_id`.
 	 */
-	ASSERT_TRUE(hftest_cpu_start(hftest_get_cpu_id(7), vm_cpu_entry,
-				     (uintptr_t)&state));
+	ASSERT_TRUE(hftest_cpu_start(hftest_get_cpu_id(7),
+				     hftest_get_secondary_ec_stack(0),
+				     vm_cpu_entry, (uintptr_t)&state));
 
 	/* Run on a loop until the secondary VM is done. */
 	EXPECT_TRUE(run_loop(&mb));
diff --git a/test/vmapi/primary_with_secondaries/services/smp.c b/test/vmapi/primary_with_secondaries/services/smp.c
index e0530f4..3e64204 100644
--- a/test/vmapi/primary_with_secondaries/services/smp.c
+++ b/test/vmapi/primary_with_secondaries/services/smp.c
@@ -56,7 +56,8 @@
 
 	/* Start second vCPU. */
 	dlog("Secondary starting second vCPU.\n");
-	ASSERT_TRUE(hftest_cpu_start(1, vm_cpu_entry, ARG_VALUE));
+	ASSERT_TRUE(hftest_cpu_start(1, hftest_get_secondary_ec_stack(0),
+				     vm_cpu_entry, ARG_VALUE));
 	dlog("Secondary started second vCPU.\n");
 
 	/* Check that vCPU statuses are as expected. */