Remove race with test TEAR_DOWN.

If the first CPU finished the loop first and the second CPU received a
message but hasn't yet managed to release the RX buffer, the TEAR_DOWN
handler could find the RX buffer isn't empty and the second CPU meaning
the second CPU would find the RX buffer empty.

To avoid this race, the first CPU needs to wait for the second to
complete before exiting the test case.

Change-Id: Ic0e83385ebdd455e0b3b525d2459bf361645df1f
diff --git a/test/vmapi/primary_with_secondaries/run_race.c b/test/vmapi/primary_with_secondaries/run_race.c
index 222f17a..eba3536 100644
--- a/test/vmapi/primary_with_secondaries/run_race.c
+++ b/test/vmapi/primary_with_secondaries/run_race.c
@@ -28,6 +28,11 @@
 #include "test/hftest.h"
 #include "test/vmapi/spci.h"
 
+struct cpu_state {
+	struct mailbox_buffers *mb;
+	struct spinlock run_lock;
+};
+
 /**
  * Iterates trying to run vCPU of the secondary VM. Returns when a message
  * of non-zero length is received.
@@ -70,7 +75,10 @@
  */
 static void vm_cpu_entry(uintptr_t arg)
 {
-	run_loop((struct mailbox_buffers *)arg);
+	struct cpu_state *state = (struct cpu_state *)arg;
+
+	run_loop(state->mb);
+	sl_unlock(&state->run_lock);
 }
 
 TEAR_DOWN(vcpu_state)
@@ -90,15 +98,25 @@
 {
 	alignas(4096) static char stack[4096];
 	static struct mailbox_buffers mb;
+	struct cpu_state state;
 
 	mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM1, "check_state", mb.send);
 
-	/* Start second vCPU. */
+	/* Start second CPU. */
+	state.mb = &mb;
+	state.run_lock = SPINLOCK_INIT;
+	sl_lock(&state.run_lock);
 	ASSERT_TRUE(hftest_cpu_start(hftest_get_cpu_id(1), stack, sizeof(stack),
-				     vm_cpu_entry, (uintptr_t)&mb));
+				     vm_cpu_entry, (uintptr_t)&state));
 
 	/* Run on a loop until the secondary VM is done. */
 	EXPECT_TRUE(run_loop(&mb));
+
+	/*
+	 * Wait for the second CPU to release its runlock to show it has
+	 * finished handling messages so the RX buffer is not idle.
+	 */
+	sl_lock(&state.run_lock);
 }