Revert "Call spci_run directly in tests rather than hf_vcpu_run."

This reverts commit d1e52b4e430dadd6e1cca2feac6d855e04c35599.

Reason for revert: Flaky timer_secondary tests

Change-Id: Ie69772c7fd196ea198c28b85b0fe8079b5cd8971
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 90397c4..dd39c26 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -60,24 +60,15 @@
 }
 
 /**
- * Runs the given vCPU of the given VM.
- */
-static inline struct spci_value spci_run(spci_vm_id_t vm_id,
-					 spci_vcpu_index_t vcpu_idx)
-{
-	return spci_call((struct spci_value){.func = SPCI_RUN_32,
-					     (uint32_t)vm_id << 16 | vcpu_idx});
-}
-
-/**
- * Runs the given vCPU of the given VM.
+ * Runs the given vcpu of the given vm.
  *
  * Returns an hf_vcpu_run_return struct telling the scheduler what to do next.
  */
 static inline struct hf_vcpu_run_return hf_vcpu_run(spci_vm_id_t vm_id,
 						    spci_vcpu_index_t vcpu_idx)
 {
-	return hf_vcpu_run_return_decode(spci_run(vm_id, vcpu_idx));
+	return hf_vcpu_run_return_decode(spci_call((struct spci_value){
+		.func = SPCI_RUN_32, (uint32_t)vm_id << 16 | vcpu_idx}));
 }
 
 /**
diff --git a/test/hftest/inc/hftest_impl.h b/test/hftest/inc/hftest_impl.h
index ed2fa91..f3c9ffa 100644
--- a/test/hftest/inc/hftest_impl.h
+++ b/test/hftest/inc/hftest_impl.h
@@ -280,7 +280,7 @@
  */
 #define HFTEST_SERVICE_SELECT(vm_id, service, send_buffer)                    \
 	do {                                                                  \
-		struct spci_value run_res;                                    \
+		struct hf_vcpu_run_return run_res;                            \
 		uint32_t msg_length =                                         \
 			strnlen_s(service, SERVICE_NAME_MAX_LENGTH);          \
                                                                               \
@@ -288,9 +288,9 @@
 		 * Let the service configure its mailbox and wait for a       \
 		 * message.                                                   \
 		 */                                                           \
-		run_res = spci_run(vm_id, 0);                                 \
-		ASSERT_EQ(run_res.func, SPCI_MSG_WAIT_32);                    \
-		ASSERT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);               \
+		run_res = hf_vcpu_run(vm_id, 0);                              \
+		ASSERT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);        \
+		ASSERT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);             \
                                                                               \
 		/* Send the selected service to run and let it be handled. */ \
 		memcpy_s(send_buffer, SPCI_MSG_PAYLOAD_MAX, service,          \
@@ -299,8 +299,8 @@
 		ASSERT_EQ(spci_msg_send(hf_vm_get_id(), vm_id, msg_length, 0) \
 				  .func,                                      \
 			  SPCI_SUCCESS_32);                                   \
-		run_res = spci_run(vm_id, 0);                                 \
-		ASSERT_EQ(run_res.func, SPCI_YIELD_32);                       \
+		run_res = hf_vcpu_run(vm_id, 0);                              \
+		ASSERT_EQ(run_res.code, HF_VCPU_RUN_YIELD);                   \
 	} while (0)
 
 #define HFTEST_SERVICE_SEND_BUFFER() hftest_get_context()->send
diff --git a/test/vmapi/arch/aarch64/gicv3/busy_secondary.c b/test/vmapi/arch/aarch64/gicv3/busy_secondary.c
index 3bf660b..1ed1031 100644
--- a/test/vmapi/arch/aarch64/gicv3/busy_secondary.c
+++ b/test/vmapi/arch/aarch64/gicv3/busy_secondary.c
@@ -45,7 +45,7 @@
 TEST(busy_secondary, virtual_timer)
 {
 	const char message[] = "loop";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	interrupt_enable(VIRTUAL_TIMER_IRQ, true);
 	interrupt_set_priority(VIRTUAL_TIMER_IRQ, 0x80);
@@ -62,9 +62,9 @@
 	arch_irq_enable();
 
 	/* Let the secondary get started and wait for our message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Check that no interrupts are active or pending to start with. */
 	EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
@@ -84,8 +84,8 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_INTERRUPT_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_PREEMPTED);
 
 	dlog("Waiting for interrupt\n");
 	while (last_interrupt_id == 0) {
@@ -111,7 +111,7 @@
 TEST(busy_secondary, physical_timer)
 {
 	const char message[] = "loop";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	interrupt_enable(PHYSICAL_TIMER_IRQ, true);
 	interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
@@ -120,9 +120,9 @@
 	arch_irq_enable();
 
 	/* Let the secondary get started and wait for our message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Check that no interrupts are active or pending to start with. */
 	EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
@@ -142,8 +142,8 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_INTERRUPT_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_PREEMPTED);
 
 	dlog("Waiting for interrupt\n");
 	while (last_interrupt_id == 0) {
diff --git a/test/vmapi/arch/aarch64/gicv3/gicv3.c b/test/vmapi/arch/aarch64/gicv3/gicv3.c
index a96f55a..bc00deb 100644
--- a/test/vmapi/arch/aarch64/gicv3/gicv3.c
+++ b/test/vmapi/arch/aarch64/gicv3/gicv3.c
@@ -87,14 +87,13 @@
  */
 TEST(system, icc_ctlr_read_trapped_secondary)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
 	SERVICE_SELECT(SERVICE_VM0, "read_systemreg_ctlr", send_buffer);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_ERROR_32);
-	EXPECT_EQ(run_res.arg2, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /*
@@ -103,14 +102,13 @@
  */
 TEST(system, icc_ctlr_write_trapped_secondary)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
 	SERVICE_SELECT(SERVICE_VM0, "write_systemreg_ctlr", send_buffer);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_ERROR_32);
-	EXPECT_EQ(run_res.arg2, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /*
@@ -119,13 +117,12 @@
  */
 TEST(system, icc_sre_write_trapped_secondary)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
 	SERVICE_SELECT(SERVICE_VM0, "write_systemreg_sre", send_buffer);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_TRUE((run_res.func == SPCI_ERROR_32 &&
-		     run_res.arg2 == SPCI_ABORTED) ||
-		    run_res.func == SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_TRUE(run_res.code == HF_VCPU_RUN_ABORTED ||
+		    run_res.code == HF_VCPU_RUN_YIELD);
 }
diff --git a/test/vmapi/arch/aarch64/gicv3/timer_secondary.c b/test/vmapi/arch/aarch64/gicv3/timer_secondary.c
index 4ac87a8..e38a2fc 100644
--- a/test/vmapi/arch/aarch64/gicv3/timer_secondary.c
+++ b/test/vmapi/arch/aarch64/gicv3/timer_secondary.c
@@ -41,12 +41,12 @@
 {
 	const char message[] = "loop 0099999";
 	const char expected_response[] = "Got IRQ 03.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	/* Let the secondary get started and wait for our message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Send the message for the secondary to set a timer. */
 	memcpy_s(send_buffer, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -58,23 +58,23 @@
 	/*
 	 * Let the secondary handle the message and set the timer. It will loop
 	 * until the hardware interrupt fires, at which point we'll get and
-	 * ignore the interrupt, and see a SPCI_YIELD return code.
+	 * ignore the interrupt, and see a HF_VCPU_RUN_YIELD return code.
 	 */
 	dlog("running secondary after sending timer message.\n");
 	last_interrupt_id = 0;
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_INTERRUPT_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_PREEMPTED);
 	dlog("secondary yielded after receiving timer message\n");
 	EXPECT_EQ(last_interrupt_id, VIRTUAL_TIMER_IRQ);
 
 	/*
-	 * Now that the timer has expired, when we call spci_run again Hafnium
-	 * should inject a virtual timer interrupt into the secondary, which
-	 * should get it and respond.
+	 * Now that the timer has expired, when we call hf_vcpu_run again
+	 * Hafnium should inject a virtual timer interrupt into the secondary,
+	 * which should get it and respond.
 	 */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(recv_buffer, expected_response,
 			 sizeof(expected_response)),
 		  0);
@@ -95,16 +95,17 @@
 	timer_busywait_secondary();
 }
 
-static void timer_secondary(const char message[], uint64_t expected_code)
+static void timer_secondary(const char message[],
+			    enum hf_vcpu_run_code expected_code)
 {
 	const char expected_response[] = "Got IRQ 03.";
 	size_t message_length = strnlen_s(message, 64) + 1;
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	/* Let the secondary get started and wait for our message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Send the message for the secondary to set a timer. */
 	memcpy_s(send_buffer, SPCI_MSG_PAYLOAD_MAX, message, message_length);
@@ -115,62 +116,63 @@
 
 	/* Let the secondary handle the message and set the timer. */
 	last_interrupt_id = 0;
-	run_res = spci_run(SERVICE_VM0, 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 
 	/*
 	 * There's a race for whether the secondary manages to block and switch
 	 * to the primary before the hardware timer fires, so we need to handle
 	 * three cases:
-	 * 1. The (hardware) timer fires immediately, we get SPCI_INTERRUPT.
+	 * 1. The (hardware) timer fires immediately, we get
+	 *   HF_VCPU_RUN_PREEMPTED.
 	 * 2. The secondary blocks and switches back, we get expected_code until
 	 *   the timer fires.
 	 *  2a. The timer then expires while we are in the primary, so Hafnium
-	 *   can inject the timer interrupt the next time we call spci_run.
+	 *   can inject the timer interrupt the next time we call hf_vcpu_run.
 	 *  2b. The timer fires while the secondary is running, so we get
-	 *   SPCI_INTERRUPT as in case 1.
+	 *   HF_VCPU_RUN_PREEMPTED as in case 1.
 	 */
 
-	if (run_res.func != expected_code &&
-	    run_res.func != SPCI_INTERRUPT_32) {
-		FAIL("Expected run to return SPCI_INTERRUPT or %#x, but "
-		     "got %#x",
-		     expected_code, run_res.func);
+	if (run_res.code != expected_code &&
+	    run_res.code != HF_VCPU_RUN_PREEMPTED) {
+		FAIL("Expected run to return HF_VCPU_RUN_PREEMPTED or %d, but "
+		     "got %d",
+		     expected_code, run_res.code);
 	}
 
 	/* Loop until the timer fires. */
-	while (run_res.func == expected_code) {
+	while (run_res.code == expected_code) {
 		/*
 		 * This case happens if the secondary manages to block and
 		 * switch to the primary before the timer fires.
 		 */
 		dlog("Primary looping until timer fires\n");
-		if (expected_code == HF_SPCI_RUN_WAIT_FOR_INTERRUPT ||
-		    expected_code == SPCI_MSG_WAIT_32) {
-			EXPECT_NE(run_res.arg2, SPCI_SLEEP_INDEFINITE);
-			dlog("%d ns remaining\n", run_res.arg2);
+		if (expected_code == HF_VCPU_RUN_WAIT_FOR_INTERRUPT ||
+		    expected_code == HF_VCPU_RUN_WAIT_FOR_MESSAGE) {
+			EXPECT_NE(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
+			dlog("%d ns remaining\n", run_res.sleep.ns);
 		}
-		run_res = spci_run(SERVICE_VM0, 0);
+		run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	}
 	dlog("Primary done looping\n");
 
-	if (run_res.func == SPCI_INTERRUPT_32) {
+	if (run_res.code == HF_VCPU_RUN_PREEMPTED) {
 		/*
 		 * This case happens if the (hardware) timer fires before the
 		 * secondary blocks and switches to the primary, either
 		 * immediately after setting the timer or during the loop above.
 		 * Then we get the interrupt to the primary, ignore it, and see
-		 * a SPCI_INTERRUPT code from the spci_run call, so we should
-		 * call it again for the timer interrupt to be injected
+		 * a HF_VCPU_RUN_PREEMPTED code from the hf_vcpu_run call, so we
+		 * should call it again for the timer interrupt to be injected
 		 * automatically by Hafnium.
 		 */
 		EXPECT_EQ(last_interrupt_id, VIRTUAL_TIMER_IRQ);
 		dlog("Preempted by timer interrupt, running again\n");
-		run_res = spci_run(SERVICE_VM0, 0);
+		run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	}
 
 	/* Once we wake it up it should get the timer interrupt and respond. */
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(recv_buffer, expected_response,
 			 sizeof(expected_response)),
 		  0);
@@ -190,8 +192,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("WFI  0000001", HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
-	timer_secondary("WFI  0000001", HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
+	timer_secondary("WFI  0000001", HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	timer_secondary("WFI  0000001", HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
 }
 
 TEST(timer_secondary, wfi_long)
@@ -200,8 +202,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("WFI  0099999", HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
-	timer_secondary("WFI  0099999", HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
+	timer_secondary("WFI  0099999", HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	timer_secondary("WFI  0099999", HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
 }
 
 TEST(timer_secondary, wfe_short)
@@ -210,8 +212,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("WFE  0000001", SPCI_YIELD_32);
-	timer_secondary("WFE  0000001", SPCI_YIELD_32);
+	timer_secondary("WFE  0000001", HF_VCPU_RUN_YIELD);
+	timer_secondary("WFE  0000001", HF_VCPU_RUN_YIELD);
 }
 
 TEST(timer_secondary, wfe_long)
@@ -220,8 +222,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("WFE  0099999", SPCI_YIELD_32);
-	timer_secondary("WFE  0099999", SPCI_YIELD_32);
+	timer_secondary("WFE  0099999", HF_VCPU_RUN_YIELD);
+	timer_secondary("WFE  0099999", HF_VCPU_RUN_YIELD);
 }
 
 TEST(timer_secondary, receive_short)
@@ -230,8 +232,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("RECV 0000001", SPCI_MSG_WAIT_32);
-	timer_secondary("RECV 0000001", SPCI_MSG_WAIT_32);
+	timer_secondary("RECV 0000001", HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	timer_secondary("RECV 0000001", HF_VCPU_RUN_WAIT_FOR_MESSAGE);
 }
 
 TEST(timer_secondary, receive_long)
@@ -240,8 +242,8 @@
 	 * Run the test twice in a row, to check that the state doesn't get
 	 * messed up.
 	 */
-	timer_secondary("RECV 0099999", SPCI_MSG_WAIT_32);
-	timer_secondary("RECV 0099999", SPCI_MSG_WAIT_32);
+	timer_secondary("RECV 0099999", HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	timer_secondary("RECV 0099999", HF_VCPU_RUN_WAIT_FOR_MESSAGE);
 }
 
 /**
@@ -251,12 +253,12 @@
 {
 	const char message[] = "WFI  9999999";
 	size_t message_length = strnlen_s(message, 64) + 1;
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	/* Let the secondary get started and wait for our message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Send the message for the secondary to set a timer. */
 	memcpy_s(send_buffer, SPCI_MSG_PAYLOAD_MAX, message, message_length);
@@ -270,10 +272,10 @@
 	 */
 	last_interrupt_id = 0;
 	for (int i = 0; i < 20; ++i) {
-		run_res = spci_run(SERVICE_VM0, 0);
-		EXPECT_EQ(run_res.func, HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
+		run_res = hf_vcpu_run(SERVICE_VM0, 0);
+		EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
 		dlog("Primary looping until timer fires; %d ns "
 		     "remaining\n",
-		     run_res.arg2);
+		     run_res.sleep.ns);
 	}
 }
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 067cfc1..74302c6 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -85,23 +85,25 @@
 }
 
 /**
- * Confirm it is an error when running a vcpu from the primary VM.
+ * Confirm it is a no-op with a valid return code when running a vcpu from the
+ * primary VM.
  */
-TEST(spci_run, cannot_run_primary)
+TEST(hf_vcpu_run, cannot_run_primary)
 {
-	struct spci_value res = spci_run(HF_PRIMARY_VM_ID, 0);
-	EXPECT_EQ(res.func, SPCI_ERROR_32);
-	EXPECT_EQ(res.arg2, SPCI_INVALID_PARAMETERS);
+	struct hf_vcpu_run_return res = hf_vcpu_run(HF_PRIMARY_VM_ID, 0);
+	EXPECT_EQ(res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
- * Confirm it is an error when running a vcpu from a non-existant secondary VM.
+ * Confirm it is a no-op with a valid return code when running a vcpu from a
+ * non-existant secondary VM.
  */
-TEST(spci_run, cannot_run_absent_secondary)
+TEST(hf_vcpu_run, cannot_run_absent_secondary)
 {
-	struct spci_value res = spci_run(1, 0);
-	EXPECT_EQ(res.func, SPCI_ERROR_32);
-	EXPECT_EQ(res.arg2, SPCI_INVALID_PARAMETERS);
+	struct hf_vcpu_run_return res = hf_vcpu_run(1, 0);
+	EXPECT_EQ(res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
diff --git a/test/vmapi/primary_with_secondaries/abort.c b/test/vmapi/primary_with_secondaries/abort.c
index 5337d18..ce7f778 100644
--- a/test/vmapi/primary_with_secondaries/abort.c
+++ b/test/vmapi/primary_with_secondaries/abort.c
@@ -25,13 +25,13 @@
  */
 TEST(abort, data_abort)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "data_abort", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -39,13 +39,13 @@
  */
 TEST(abort, straddling_data_abort)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "straddling_data_abort", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -53,13 +53,13 @@
  */
 TEST(abort, instruction_abort)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "instruction_abort", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -67,11 +67,11 @@
  */
 TEST(abort, straddling_instruction_abort)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "straddling_instruction_abort", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
diff --git a/test/vmapi/primary_with_secondaries/boot.c b/test/vmapi/primary_with_secondaries/boot.c
index a793d28..d6aa553 100644
--- a/test/vmapi/primary_with_secondaries/boot.c
+++ b/test/vmapi/primary_with_secondaries/boot.c
@@ -27,13 +27,13 @@
  */
 TEST(boot, memory_size)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "boot_memory", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -41,13 +41,13 @@
  */
 TEST(boot, beyond_memory_size)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "boot_memory_overrun", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -55,11 +55,11 @@
  */
 TEST(boot, memory_before_image)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "boot_memory_underrun", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
diff --git a/test/vmapi/primary_with_secondaries/debug_el1.c b/test/vmapi/primary_with_secondaries/debug_el1.c
index 5f826c8..74d2647 100644
--- a/test/vmapi/primary_with_secondaries/debug_el1.c
+++ b/test/vmapi/primary_with_secondaries/debug_el1.c
@@ -33,57 +33,57 @@
 
 TEST(debug_el1, secondary_mdccint_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "debug_el1_secondary_mdccint_el1", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(debug_el1, secondary_dbgbcr0_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "debug_el1_secondary_dbgbcr0_el1", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(debug_el1, secondary_dbgbvr0_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "debug_el1_secondary_dbgbvr0_el1", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(debug_el1, secondary_dbgwcr0_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "debug_el1_secondary_dbgwcr0_el1", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(debug_el1, secondary_dbgwvr0_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "debug_el1_secondary_dbgwvr0_el1", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
diff --git a/test/vmapi/primary_with_secondaries/floating_point.c b/test/vmapi/primary_with_secondaries/floating_point.c
index 23660ce..a480a8b 100644
--- a/test/vmapi/primary_with_secondaries/floating_point.c
+++ b/test/vmapi/primary_with_secondaries/floating_point.c
@@ -35,18 +35,18 @@
 {
 	const double first = 1.2;
 	const double second = -2.3;
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	fill_fp_registers(first);
 	SERVICE_SELECT(SERVICE_VM0, "fp_fill", mb.send);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 	EXPECT_EQ(check_fp_register(first), true);
 
 	fill_fp_registers(second);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 	EXPECT_EQ(check_fp_register(second), true);
 }
 
@@ -57,17 +57,17 @@
 TEST(floating_point, fp_fpcr)
 {
 	uintreg_t value = 0;
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	EXPECT_EQ(read_msr(fpcr), value);
 
 	SERVICE_SELECT(SERVICE_VM0, "fp_fpcr", mb.send);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 	EXPECT_EQ(read_msr(fpcr), value);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 	EXPECT_EQ(read_msr(fpcr), value);
 }
diff --git a/test/vmapi/primary_with_secondaries/interrupts.c b/test/vmapi/primary_with_secondaries/interrupts.c
index dfd6b20..31db0b0 100644
--- a/test/vmapi/primary_with_secondaries/interrupts.c
+++ b/test/vmapi/primary_with_secondaries/interrupts.c
@@ -32,14 +32,14 @@
 {
 	const char message[] = "Ping";
 	const char expected_response[] = "Got IRQ 05.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Set the message, echo it and wait for a response. */
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -47,9 +47,9 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -63,29 +63,29 @@
 TEST(interrupts, inject_interrupt_twice)
 {
 	const char expected_response[] = "Got IRQ 07.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Inject the interrupt and wait for a message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 
 	/* Inject the interrupt again, and wait for the same message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -99,29 +99,29 @@
 {
 	const char expected_response[] = "Got IRQ 07.";
 	const char expected_response_2[] = "Got IRQ 08.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Inject the interrupt and wait for a message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 
 	/* Inject a different interrupt and wait for a different message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_B);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response_2));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response_2));
 	EXPECT_EQ(memcmp(mb.recv, expected_response_2,
 			 sizeof(expected_response_2)),
 		  0);
@@ -138,27 +138,27 @@
 	const char expected_response[] = "Got IRQ 07.";
 	const char message[] = "Ping";
 	const char expected_response_2[] = "Got IRQ 05.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Inject the interrupt and wait for a message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Now send a message to the secondary. */
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -166,9 +166,9 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response_2));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response_2));
 	EXPECT_EQ(memcmp(mb.recv, expected_response_2,
 			 sizeof(expected_response_2)),
 		  0);
@@ -184,16 +184,16 @@
 {
 	const char expected_response[] = "Got IRQ 09.";
 	const char message[] = "Enable interrupt C";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible", mb.send);
 
 	/* Inject the interrupt and expect not to get a message. */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_C);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/*
 	 * Now send a message to the secondary to enable the interrupt ID, and
@@ -204,9 +204,9 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -220,7 +220,7 @@
 TEST(interrupts, pending_interrupt_no_blocking_receive)
 {
 	const char expected_response[] = "Done waiting";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "receive_block", mb.send);
@@ -231,9 +231,9 @@
 	 * back after failing to receive a message a few times.
 	 */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -247,7 +247,7 @@
 TEST(interrupts, pending_interrupt_wfi_not_trapped)
 {
 	const char expected_response[] = "Done waiting";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "wfi", mb.send);
@@ -258,9 +258,9 @@
 	 * back after running WFI a few times.
 	 */
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response));
 	EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
 		  0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -273,14 +273,14 @@
 TEST(interrupts, deliver_interrupt_and_message)
 {
 	const char message[] = "I\'ll see you again.";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "interruptible_echo", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
 	EXPECT_EQ(
@@ -288,9 +288,9 @@
 			.func,
 		SPCI_SUCCESS_32);
 	hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
 	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 }
diff --git a/test/vmapi/primary_with_secondaries/mailbox.c b/test/vmapi/primary_with_secondaries/mailbox.c
index 9593dc7..934f741 100644
--- a/test/vmapi/primary_with_secondaries/mailbox.c
+++ b/test/vmapi/primary_with_secondaries/mailbox.c
@@ -79,14 +79,14 @@
 TEST(mailbox, echo)
 {
 	const char message[] = "Echo this back to me!";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "echo", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Set the message, echo it and check it didn't change. */
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -94,10 +94,10 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
-	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
+	EXPECT_EQ(memcmp(mb.send, message, sizeof(message)), 0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 }
 
@@ -107,7 +107,7 @@
 TEST(mailbox, repeated_echo)
 {
 	char message[] = "Echo this back to me!";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	uint8_t i;
 	struct mailbox_buffers mb = set_up_mailbox();
 
@@ -115,9 +115,9 @@
 
 	for (i = 0; i < 100; i++) {
 		/* Run secondary until it reaches the wait for messages. */
-		run_res = spci_run(SERVICE_VM0, 0);
-		EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-		EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+		run_res = hf_vcpu_run(SERVICE_VM0, 0);
+		EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+		EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 		/* Set the message, echo it and check it didn't change. */
 		next_permutation(message, sizeof(message) - 1);
@@ -127,9 +127,9 @@
 					sizeof(message), 0)
 				  .func,
 			  SPCI_SUCCESS_32);
-		run_res = spci_run(SERVICE_VM0, 0);
-		EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-		EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+		run_res = hf_vcpu_run(SERVICE_VM0, 0);
+		EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+		EXPECT_EQ(run_res.message.size, sizeof(message));
 		EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 		EXPECT_EQ(hf_mailbox_clear(), 0);
 	}
@@ -142,18 +142,18 @@
 TEST(mailbox, relay)
 {
 	const char message[] = "Send this round the relay!";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "relay", mb.send);
 	SERVICE_SELECT(SERVICE_VM1, "relay", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
-	run_res = spci_run(SERVICE_VM1, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM1, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/*
 	 * Build the message chain so the message is sent from here to
@@ -176,18 +176,18 @@
 	}
 
 	/* Let SERVICE_VM0 forward the message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_receiver(run_res), SERVICE_VM1);
-	EXPECT_EQ(spci_msg_send_size(run_res), 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.vm_id, SERVICE_VM1);
+	EXPECT_EQ(run_res.message.size, 0);
 
 	/* Let SERVICE_VM1 forward the message. */
-	run_res = spci_run(SERVICE_VM1, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM1, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Ensure the message is intact. */
-	EXPECT_EQ(spci_msg_send_receiver(run_res), HF_PRIMARY_VM_ID);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+	EXPECT_EQ(run_res.message.vm_id, HF_PRIMARY_VM_ID);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
 	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 	EXPECT_EQ(hf_mailbox_clear(), 0);
 }
@@ -198,16 +198,15 @@
  */
 TEST(mailbox, no_primary_to_secondary_notification_on_configure)
 {
-	struct spci_value run_res;
-
+	struct hf_vcpu_run_return run_res;
 	set_up_mailbox();
 
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, 0, 0),
 			  SPCI_BUSY);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, 0, 0).func,
 		  SPCI_SUCCESS_32);
@@ -219,8 +218,7 @@
  */
 TEST(mailbox, secondary_to_primary_notification_on_configure)
 {
-	struct spci_value run_res;
-
+	struct hf_vcpu_run_return run_res;
 	set_up_mailbox();
 
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, 0,
@@ -231,8 +229,8 @@
 	 * Run first VM for it to configure itself. It should result in
 	 * notifications having to be issued.
 	 */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_RX_RELEASE_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_NOTIFY_WAITERS);
 
 	/* A single waiter is returned. */
 	EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM0), HF_PRIMARY_VM_ID);
@@ -251,14 +249,14 @@
 TEST(mailbox, primary_to_secondary)
 {
 	char message[] = "not ready echo";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "echo_with_notification", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Send a message to echo service, and get response back. */
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -266,15 +264,15 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
 	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 
 	/* Let secondary VM continue running so that it will wait again. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Without clearing our mailbox, send message again. */
 	reverse(message, strnlen_s(message, sizeof(message)));
@@ -285,9 +283,9 @@
 		spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, sizeof(message), 0)
 			.func,
 		SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Clear the mailbox. We expect to be told there are pending waiters. */
 	EXPECT_EQ(hf_mailbox_clear(), 1);
@@ -303,9 +301,9 @@
 	EXPECT_EQ(
 		hf_interrupt_inject(SERVICE_VM0, 0, HF_MAILBOX_WRITABLE_INTID),
 		1);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
 	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 }
 
@@ -317,14 +315,14 @@
 TEST(mailbox, secondary_to_primary_notification)
 {
 	const char message[] = "not ready echo";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "echo_with_notification", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 
 	/* Send a message to echo service twice. The second should fail. */
 	memcpy_s(mb.send, SPCI_MSG_PAYLOAD_MAX, message, sizeof(message));
@@ -337,14 +335,14 @@
 			  SPCI_BUSY);
 
 	/* Receive a reply for the first message. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(message));
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(message));
 	EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
 
 	/* Run VM again so that it clears its mailbox. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_RX_RELEASE_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_NOTIFY_WAITERS);
 
 	/* Retrieve a single waiter. */
 	EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM0), HF_PRIMARY_VM_ID);
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index 745bd8b..76d0739 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -286,7 +286,7 @@
  */
 TEST(memory_sharing, concurrent)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -307,15 +307,15 @@
 			  .func,
 		  SPCI_SUCCESS_32);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	for (int i = 0; i < PAGE_SIZE; ++i) {
 		page[i] = i;
 	}
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	for (int i = 0; i < PAGE_SIZE; ++i) {
 		uint8_t value = i + 1;
@@ -329,7 +329,7 @@
  */
 TEST(memory_sharing, share_concurrently_and_get_back)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -352,15 +352,15 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be returned. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 	for (int i = 0; i < PAGE_SIZE; ++i) {
 		ASSERT_EQ(ptr[i], 0);
 	}
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -387,7 +387,7 @@
  */
 TEST(memory_sharing, spci_give_and_get_back)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -411,10 +411,10 @@
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
 		  SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 
 	/* Let the memory be returned. */
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Ensure that the secondary VM accessed the region. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -422,8 +422,8 @@
 	}
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -431,7 +431,7 @@
  */
 TEST(memory_sharing, spci_lend_relinquish)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -454,10 +454,10 @@
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
 		  SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 
 	/* Let the memory be returned. */
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Ensure that the secondary VM accessed the region. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -465,8 +465,8 @@
 	}
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -474,7 +474,7 @@
  */
 TEST(memory_sharing, give_and_get_back)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -497,15 +497,15 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be returned. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 	for (int i = 0; i < PAGE_SIZE; ++i) {
 		ASSERT_EQ(ptr[i], 0);
 	}
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -513,7 +513,7 @@
  */
 TEST(memory_sharing, lend_and_get_back)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -536,15 +536,15 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be returned. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 	for (int i = 0; i < PAGE_SIZE; ++i) {
 		ASSERT_EQ(ptr[i], 0);
 	}
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -552,7 +552,7 @@
  */
 TEST(memory_sharing, reshare_after_return)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -574,8 +574,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be returned. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Share the memory again after it has been returned. */
 	ASSERT_EQ(hf_share_memory(SERVICE_VM0, (hf_ipaddr_t)&page, PAGE_SIZE,
@@ -583,9 +583,9 @@
 		  0);
 
 	/* Observe the service doesn't fault when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
@@ -593,7 +593,7 @@
  */
 TEST(memory_sharing, share_elsewhere_after_return)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 
@@ -615,8 +615,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be returned. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Share the memory with a differnt VM after it has been returned. */
 	ASSERT_EQ(hf_share_memory(SERVICE_VM1, (hf_ipaddr_t)&page, PAGE_SIZE,
@@ -624,8 +624,8 @@
 		  0);
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -633,15 +633,15 @@
  */
 TEST(memory_sharing, give_memory_and_lose_access)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr;
 
 	SERVICE_SELECT(SERVICE_VM0, "give_memory_and_fault", mb.send);
 
 	/* Have the memory be given. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Check the memory was cleared. */
 	ptr = *(uint8_t **)mb.recv;
@@ -650,8 +650,8 @@
 	}
 
 	/* Observe the service fault when it tries to access it. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -659,15 +659,15 @@
  */
 TEST(memory_sharing, lend_memory_and_lose_access)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr;
 
 	SERVICE_SELECT(SERVICE_VM0, "lend_memory_and_fault", mb.send);
 
 	/* Have the memory be lent. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Check the memory was cleared. */
 	ptr = *(uint8_t **)mb.recv;
@@ -676,8 +676,8 @@
 	}
 
 	/* Observe the service fault when it tries to access it. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -685,7 +685,7 @@
  */
 TEST(memory_sharing, spci_donate_check_upper_bounds)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -709,8 +709,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -718,7 +718,7 @@
  */
 TEST(memory_sharing, spci_donate_check_lower_bounds)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -742,8 +742,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Observe the service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -752,7 +752,7 @@
  */
 TEST(memory_sharing, spci_donate_elsewhere_after_return)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -776,10 +776,10 @@
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
 		  SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 
 	/* Let the memory be returned. */
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Share the memory with another VM. */
 	msg_size = spci_memory_donate_init(
@@ -792,8 +792,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Observe the original service faulting when accessing the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -802,7 +802,7 @@
  */
 TEST(memory_sharing, spci_donate_vms)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -818,8 +818,8 @@
 	};
 
 	/* Set up VM1 to wait for message. */
-	run_res = spci_run(SERVICE_VM1, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_WAIT_32);
+	run_res = hf_vcpu_run(SERVICE_VM1, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
 
 	/* Donate memory. */
 	msg_size = spci_memory_donate_init(
@@ -832,20 +832,20 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be sent from VM0 to VM1. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Receive memory in VM1. */
-	run_res = spci_run(SERVICE_VM1, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM1, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Try to access memory in VM0 and fail. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 
 	/* Ensure that memory in VM1 remains the same. */
-	run_res = spci_run(SERVICE_VM1, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM1, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -853,7 +853,7 @@
  */
 TEST(memory_sharing, spci_donate_twice)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -879,8 +879,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be received. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Fail to share memory again with any VM. */
 	spci_check_cannot_donate_memory(mb, constituents, 1, -1);
@@ -888,15 +888,15 @@
 	spci_check_cannot_relinquish_memory(mb, constituents, 1);
 
 	/* Let the memory be sent from VM0 to PRIMARY (returned). */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Check we have access again. */
 	ptr[0] = 'f';
 
 	/* Try and fail to donate memory from VM0 to VM1. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -977,7 +977,7 @@
  */
 TEST(memory_sharing, spci_donate_invalid_source)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1027,12 +1027,12 @@
 		  SPCI_SUCCESS_32);
 
 	/* Receive and return memory from VM0. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Use VM0 to fail to donate memory from the primary to VM1. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -1074,7 +1074,7 @@
  */
 TEST(memory_sharing, spci_lend_invalid_source)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1107,12 +1107,12 @@
 		  SPCI_SUCCESS_32);
 
 	/* Receive and return memory from VM0. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Try to lend memory from primary in VM0. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -1121,7 +1121,7 @@
  */
 TEST(memory_sharing, spci_lend_relinquish_X_RW)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1146,12 +1146,12 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Let service write to and return memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Re-initialise the memory before giving it. */
 	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
@@ -1167,12 +1167,12 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Observe the service faulting when writing to the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -1181,7 +1181,7 @@
  */
 TEST(memory_sharing, spci_share_relinquish_X_RW)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1206,8 +1206,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we still have access. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -1216,8 +1216,8 @@
 	}
 
 	/* Let service write to and return memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Re-initialise the memory before giving it. */
 	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
@@ -1233,8 +1233,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we still have access. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -1243,8 +1243,8 @@
 	}
 
 	/* Observe the service faulting when writing to the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -1253,7 +1253,7 @@
  */
 TEST(memory_sharing, spci_share_relinquish_NX_RW)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1278,8 +1278,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we still have access. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -1287,8 +1287,8 @@
 	}
 
 	/* Let service write to and return memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Re-initialise the memory before giving it. */
 	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
@@ -1304,8 +1304,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we still have access. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -1314,8 +1314,8 @@
 	}
 
 	/* Observe the service faulting when writing to the memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -1323,7 +1323,7 @@
  */
 TEST(memory_sharing, spci_lend_relinquish_RW_X)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1351,8 +1351,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Attempt to execute from memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	msg_size = spci_memory_lend_init(
 		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_NX,
@@ -1364,8 +1364,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Try and fail to execute from the memory region. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -1373,7 +1373,7 @@
  */
 TEST(memory_sharing, spci_lend_relinquish_RO_X)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1401,8 +1401,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Attempt to execute from memory. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	msg_size = spci_memory_lend_init(
 		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RO_NX,
@@ -1414,8 +1414,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Try and fail to execute from the memory region. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
@@ -1423,7 +1423,7 @@
  */
 TEST(memory_sharing, spci_lend_donate)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1449,8 +1449,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we can't donate any sub section of memory to another VM. */
 	constituents[0].page_count = 1;
@@ -1483,7 +1483,7 @@
  */
 TEST(memory_sharing, spci_share_donate)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1509,8 +1509,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Ensure we can't donate any sub section of memory to another VM. */
 	constituents[0].page_count = 1;
@@ -1543,7 +1543,7 @@
  */
 TEST(memory_sharing, spci_lend_twice)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1569,8 +1569,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Attempt to lend the same area of memory. */
 	spci_check_cannot_lend_memory(mb, constituents);
@@ -1602,7 +1602,7 @@
  */
 TEST(memory_sharing, spci_share_twice)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 	uint8_t *ptr = page;
 	uint32_t msg_size;
@@ -1628,8 +1628,8 @@
 		  SPCI_SUCCESS_32);
 
 	/* Let the memory be accessed. */
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 
 	/* Attempt to share the same area of memory. */
 	spci_check_cannot_share_memory(mb, constituents);
diff --git a/test/vmapi/primary_with_secondaries/no_services.c b/test/vmapi/primary_with_secondaries/no_services.c
index 9d43cd7..0f60bed 100644
--- a/test/vmapi/primary_with_secondaries/no_services.c
+++ b/test/vmapi/primary_with_secondaries/no_services.c
@@ -25,7 +25,6 @@
 
 #include "hftest.h"
 #include "primary_with_secondary.h"
-#include "util.h"
 
 static alignas(PAGE_SIZE) uint8_t send_page[PAGE_SIZE];
 static alignas(PAGE_SIZE) uint8_t recv_page[PAGE_SIZE];
@@ -83,28 +82,31 @@
 /**
  * The primary can't be run by the hypervisor.
  */
-TEST(spci_run, cannot_run_primary)
+TEST(hf_vcpu_run, cannot_run_primary)
 {
-	struct spci_value res = spci_run(HF_PRIMARY_VM_ID, 0);
-	EXPECT_SPCI_ERROR(res, SPCI_INVALID_PARAMETERS);
+	struct hf_vcpu_run_return res = hf_vcpu_run(HF_PRIMARY_VM_ID, 0);
+	EXPECT_EQ(res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
  * Can only run a VM that exists.
  */
-TEST(spci_run, cannot_run_absent_secondary)
+TEST(hf_vcpu_run, cannot_run_absent_secondary)
 {
-	struct spci_value res = spci_run(1234, 0);
-	EXPECT_SPCI_ERROR(res, SPCI_INVALID_PARAMETERS);
+	struct hf_vcpu_run_return res = hf_vcpu_run(1234, 0);
+	EXPECT_EQ(res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
  * Can only run a vcpu that exists.
  */
-TEST(spci_run, cannot_run_absent_vcpu)
+TEST(hf_vcpu_run, cannot_run_absent_vcpu)
 {
-	struct spci_value res = spci_run(SERVICE_VM0, 1234);
-	EXPECT_SPCI_ERROR(res, SPCI_INVALID_PARAMETERS);
+	struct hf_vcpu_run_return res = hf_vcpu_run(SERVICE_VM0, 1234);
+	EXPECT_EQ(res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
 
 /**
@@ -160,7 +162,7 @@
 }
 
 /**
- * The primary receives messages from spci_run().
+ * The primary receives messages from hf_vcpu_run().
  */
 TEST(hf_mailbox_receive, cannot_receive_from_primary_blocking)
 {
@@ -169,7 +171,7 @@
 }
 
 /**
- * The primary receives messages from spci_run().
+ * The primary receives messages from hf_vcpu_run().
  */
 TEST(hf_mailbox_receive, cannot_receive_from_primary_non_blocking)
 {
diff --git a/test/vmapi/primary_with_secondaries/perfmon.c b/test/vmapi/primary_with_secondaries/perfmon.c
index 8fd0aba..34165da 100644
--- a/test/vmapi/primary_with_secondaries/perfmon.c
+++ b/test/vmapi/primary_with_secondaries/perfmon.c
@@ -30,36 +30,36 @@
 
 TEST(perfmon, secondary_pmccfiltr_el0)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmccfiltr_el0", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(perfmon, secondary_pmcr_el0)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmcr_el0", mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 TEST(perfmon, secondary_pmintenset_el1)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmintenset_el1",
 		       mb.send);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_SPCI_ERROR(run_res, SPCI_ABORTED);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
 
 /**
diff --git a/test/vmapi/primary_with_secondaries/run_race.c b/test/vmapi/primary_with_secondaries/run_race.c
index 3a9ffcb..0ef3387 100644
--- a/test/vmapi/primary_with_secondaries/run_race.c
+++ b/test/vmapi/primary_with_secondaries/run_race.c
@@ -34,19 +34,19 @@
  */
 static bool run_loop(struct mailbox_buffers *mb)
 {
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	bool ok = false;
 
 	for (;;) {
 		/* Run until it manages to schedule vCPU on this CPU. */
 		do {
-			run_res = spci_run(SERVICE_VM0, 0);
-		} while (run_res.func == HF_SPCI_RUN_WAIT_FOR_INTERRUPT &&
-			 run_res.arg2 == HF_SLEEP_INDEFINITE);
+			run_res = hf_vcpu_run(SERVICE_VM0, 0);
+		} while (run_res.code == HF_VCPU_RUN_WAIT_FOR_INTERRUPT &&
+			 run_res.sleep.ns == HF_SLEEP_INDEFINITE);
 
 		/* Break out if we received a message with non-zero length. */
-		if (run_res.func == SPCI_MSG_SEND_32 &&
-		    spci_msg_send_size(run_res) != 0) {
+		if (run_res.code == HF_VCPU_RUN_MESSAGE &&
+		    run_res.message.size != 0) {
 			break;
 		}
 
@@ -55,7 +55,7 @@
 	}
 
 	/* Copies the contents of the received boolean to the return value. */
-	if (spci_msg_send_size(run_res) == sizeof(ok)) {
+	if (run_res.message.size == sizeof(ok)) {
 		ok = *(bool *)mb->recv;
 	}
 
diff --git a/test/vmapi/primary_with_secondaries/smp.c b/test/vmapi/primary_with_secondaries/smp.c
index 5ffda15..af5c637 100644
--- a/test/vmapi/primary_with_secondaries/smp.c
+++ b/test/vmapi/primary_with_secondaries/smp.c
@@ -32,22 +32,22 @@
 {
 	const char expected_response_0[] = "vCPU 0";
 	const char expected_response_1[] = "vCPU 1";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM2, "smp", mb.send);
 
 	/* Let the first vCPU start the second vCPU. */
-	run_res = spci_run(SERVICE_VM2, 0);
-	EXPECT_EQ(run_res.func, HF_SPCI_RUN_WAKE_UP);
-	EXPECT_EQ(wake_up_get_vm_id(run_res), SERVICE_VM2);
-	EXPECT_EQ(wake_up_get_vcpu(run_res), 1);
+	run_res = hf_vcpu_run(SERVICE_VM2, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAKE_UP);
+	EXPECT_EQ(run_res.wake_up.vm_id, SERVICE_VM2);
+	EXPECT_EQ(run_res.wake_up.vcpu, 1);
 
 	/* Run the second vCPU and wait for a message. */
 	dlog("Run second vCPU for message\n");
-	run_res = spci_run(SERVICE_VM2, 1);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response_1));
+	run_res = hf_vcpu_run(SERVICE_VM2, 1);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response_1));
 	EXPECT_EQ(memcmp(mb.recv, expected_response_1,
 			 sizeof(expected_response_1)),
 		  0);
@@ -55,9 +55,9 @@
 
 	/* Run the first vCPU and wait for a different message. */
 	dlog("Run first vCPU for message\n");
-	run_res = spci_run(SERVICE_VM2, 0);
-	EXPECT_EQ(run_res.func, SPCI_MSG_SEND_32);
-	EXPECT_EQ(spci_msg_send_size(run_res), sizeof(expected_response_0));
+	run_res = hf_vcpu_run(SERVICE_VM2, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+	EXPECT_EQ(run_res.message.size, sizeof(expected_response_0));
 	EXPECT_EQ(memcmp(mb.recv, expected_response_0,
 			 sizeof(expected_response_0)),
 		  0);
@@ -65,7 +65,7 @@
 
 	/* Run the second vCPU again, and expect it to turn itself off. */
 	dlog("Run second vCPU for poweroff.\n");
-	run_res = spci_run(SERVICE_VM2, 1);
-	EXPECT_EQ(run_res.func, HF_SPCI_RUN_WAIT_FOR_INTERRUPT);
-	EXPECT_EQ(run_res.arg2, SPCI_SLEEP_INDEFINITE);
+	run_res = hf_vcpu_run(SERVICE_VM2, 1);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
+	EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
 }
diff --git a/test/vmapi/primary_with_secondaries/spci.c b/test/vmapi/primary_with_secondaries/spci.c
index 017b080..f551830 100644
--- a/test/vmapi/primary_with_secondaries/spci.c
+++ b/test/vmapi/primary_with_secondaries/spci.c
@@ -33,7 +33,7 @@
 TEST(spci, msg_send)
 {
 	const char message[] = "spci_msg_send";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "spci_check", mb.send);
@@ -45,8 +45,8 @@
 			.func,
 		SPCI_SUCCESS_32);
 
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -88,7 +88,7 @@
 TEST(spci, spci_incorrect_length)
 {
 	const char message[] = "this should be truncated";
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 	struct mailbox_buffers mb = set_up_mailbox();
 
 	SERVICE_SELECT(SERVICE_VM0, "spci_length", mb.send);
@@ -98,8 +98,8 @@
 	/* Hard code incorrect length. */
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, 16, 0).func,
 		  SPCI_SUCCESS_32);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }
 
 /**
@@ -123,10 +123,10 @@
 TEST(spci, spci_recv_non_blocking)
 {
 	struct mailbox_buffers mb = set_up_mailbox();
-	struct spci_value run_res;
+	struct hf_vcpu_run_return run_res;
 
 	/* Check is performed in secondary vm. */
 	SERVICE_SELECT(SERVICE_VM0, "spci_recv_non_blocking", mb.send);
-	run_res = spci_run(SERVICE_VM0, 0);
-	EXPECT_EQ(run_res.func, SPCI_YIELD_32);
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
 }