SPCI: SPCI_MSG_RECV.

Morph the existing vmapi api_mailbox_receive onto
api_spci_msg_recv.

Change-Id: Ie78f8985cfc55509fcd71eece22d6397b52d717d
diff --git a/inc/hf/api.h b/inc/hf/api.h
index e588575..c63f95c 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -32,9 +32,6 @@
 				       struct vcpu **next);
 int64_t api_vm_configure(ipaddr_t send, ipaddr_t recv, struct vcpu *current,
 			 struct vcpu **next);
-struct hf_mailbox_receive_return api_mailbox_receive(bool block,
-						     struct vcpu *current,
-						     struct vcpu **next);
 int64_t api_mailbox_clear(struct vcpu *current, struct vcpu **next);
 int64_t api_mailbox_writable_get(const struct vcpu *current);
 int64_t api_mailbox_waiter_get(uint32_t vm_id, const struct vcpu *current);
@@ -54,3 +51,5 @@
 
 int32_t api_spci_msg_send(uint32_t attributes, struct vcpu *current,
 			  struct vcpu **next);
+int32_t api_spci_msg_recv(uint32_t attributes, struct vcpu *current,
+			  struct vcpu **next);
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 069a265..9511d0d 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -54,8 +54,6 @@
 
 struct mailbox {
 	enum mailbox_state state;
-	uint32_t recv_from_id;
-	int16_t recv_bytes;
 	struct spci_message *recv;
 	const struct spci_message *send;
 
diff --git a/inc/vmapi/hf/abi.h b/inc/vmapi/hf/abi.h
index c24700c..f46ed29 100644
--- a/inc/vmapi/hf/abi.h
+++ b/inc/vmapi/hf/abi.h
@@ -101,11 +101,6 @@
 	};
 };
 
-struct hf_mailbox_receive_return {
-	uint32_t vm_id;
-	uint32_t size;
-};
-
 enum hf_share {
 	/**
 	 * Relinquish ownership and access to the memory and pass them to the
@@ -182,24 +177,3 @@
 
 	return ret;
 }
-
-/**
- * Encode an hf_mailbox_receive_return struct in the 64-bit packing ABI.
- */
-static inline uint64_t hf_mailbox_receive_return_encode(
-	struct hf_mailbox_receive_return res)
-{
-	return res.vm_id | ((uint64_t)res.size << 32);
-}
-
-/**
- * Decode an hf_mailbox_receive_return struct from the 64-bit packing ABI.
- */
-static inline struct hf_mailbox_receive_return hf_mailbox_receive_return_decode(
-	uint64_t res)
-{
-	return (struct hf_mailbox_receive_return){
-		.vm_id = (uint32_t)(res & 0xffffffff),
-		.size = (uint32_t)(res >> 32),
-	};
-}
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 8bc9627..a10517c 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -30,7 +30,6 @@
 #define HF_VCPU_RUN             0xff03
 #define HF_VCPU_YIELD           0xff04
 #define HF_VM_CONFIGURE         0xff05
-#define HF_MAILBOX_RECEIVE      0xff07
 #define HF_MAILBOX_CLEAR        0xff08
 #define HF_MAILBOX_WRITABLE_GET 0xff09
 #define HF_MAILBOX_WAITER_GET   0xff0a
@@ -140,10 +139,9 @@
  * instruction on aarch64, except that a message becoming available is also
  * treated like a wake-up event.
  */
-static inline struct hf_mailbox_receive_return hf_mailbox_receive(bool block)
+static inline int32_t spci_msg_recv(int32_t attributes)
 {
-	return hf_mailbox_receive_return_decode(
-		hf_call(HF_MAILBOX_RECEIVE, block, 0, 0));
+	return hf_call(SPCI_MSG_RECV_32, attributes, 0, 0);
 }
 
 /**
diff --git a/src/abi_test.cc b/src/abi_test.cc
index 12dde09..f8cefa5 100644
--- a/src/abi_test.cc
+++ b/src/abi_test.cc
@@ -37,18 +37,6 @@
 }
 
 /**
- * Simulate an uninitialized hf_mailbox_receive_return so it can be detected if
- * any uninitialized fields make their way into the encoded form which would
- * indicate a data leak.
- */
-struct hf_mailbox_receive_return dirty_mailbox_receive_return()
-{
-	struct hf_mailbox_receive_return res;
-	memset(&res, 0xc5, sizeof(res));
-	return res;
-}
-
-/**
  * Encode a preempted response without leaking.
  */
 TEST(abi, hf_vcpu_run_return_encode_preempted)
@@ -244,27 +232,4 @@
 	EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_ABORTED));
 }
 
-/**
- * Encode a mailbox receive response without leaking.
- */
-TEST(abi, hf_mailbox_receive_return_encode)
-{
-	struct hf_mailbox_receive_return res = dirty_mailbox_receive_return();
-	res.vm_id = 0x12345678;
-	res.size = 0xaabbccdd;
-	EXPECT_THAT(hf_mailbox_receive_return_encode(res),
-		    Eq(0xaabbccdd12345678));
-}
-
-/**
- * Decode a mailbox receive response.
- */
-TEST(abi, hf_mailbox_receive_return_decode)
-{
-	struct hf_mailbox_receive_return res =
-		hf_mailbox_receive_return_decode(0X8badf00d00ddba11);
-	EXPECT_THAT(res.vm_id, Eq(0X00ddba11));
-	EXPECT_THAT(res.size, Eq(0x8badf00d));
-}
-
 } /* namespace */
diff --git a/src/api.c b/src/api.c
index 1fdb54a..16620a1 100644
--- a/src/api.c
+++ b/src/api.c
@@ -395,13 +395,7 @@
 		 * be delivered directly.
 		 */
 		if (vcpu->vm->mailbox.state == mailbox_state_received) {
-			arch_regs_set_retval(
-				&vcpu->regs,
-				hf_mailbox_receive_return_encode((
-					struct hf_mailbox_receive_return){
-					.vm_id = vcpu->vm->mailbox.recv_from_id,
-					.size = vcpu->vm->mailbox.recv_bytes,
-				}));
+			arch_regs_set_retval(&vcpu->regs, SPCI_SUCCESS);
 			vcpu->vm->mailbox.state = mailbox_state_read;
 			break;
 		}
@@ -817,8 +811,6 @@
 	to_msg = to->mailbox.recv;
 	*to_msg = from_msg_replica;
 	memcpy(to_msg->payload, from->mailbox.send->payload, size);
-	to->mailbox.recv_bytes = size;
-	to->mailbox.recv_from_id = from->id;
 	primary_ret.message.vm_id = to->id;
 	ret = SPCI_SUCCESS;
 
@@ -851,21 +843,20 @@
  *
  * No new messages can be received until the mailbox has been cleared.
  */
-struct hf_mailbox_receive_return api_mailbox_receive(bool block,
-						     struct vcpu *current,
-						     struct vcpu **next)
+int32_t api_spci_msg_recv(uint32_t attributes, struct vcpu *current,
+			  struct vcpu **next)
 {
 	struct vm *vm = current->vm;
-	struct hf_mailbox_receive_return ret = {
-		.vm_id = HF_INVALID_VM_ID,
-	};
+	int32_t return_code;
+	bool block =
+		(attributes & SPCI_MSG_RECV_BLOCK_MASK) == SPCI_MSG_RECV_BLOCK;
 
 	/*
 	 * The primary VM will receive messages as a status code from running
 	 * vcpus and must not call this function.
 	 */
 	if (vm->id == HF_PRIMARY_VM_ID) {
-		return ret;
+		return SPCI_INTERRUPTED;
 	}
 
 	sl_lock(&vm->lock);
@@ -873,17 +864,28 @@
 	/* Return pending messages without blocking. */
 	if (vm->mailbox.state == mailbox_state_received) {
 		vm->mailbox.state = mailbox_state_read;
-		ret.vm_id = vm->mailbox.recv_from_id;
-		ret.size = vm->mailbox.recv_bytes;
+		return_code = SPCI_SUCCESS;
+		goto out;
+	}
+
+	/* No pending message so fail if not allowed to block. */
+	if (!block) {
+		return_code = SPCI_RETRY;
 		goto out;
 	}
 
 	/*
-	 * No pending message so fail if not allowed to block. Don't block if
-	 * there are enabled and pending interrupts, to match behaviour of
-	 * wait_for_interrupt.
+	 * From this point onward this call can only be interrupted or a message
+	 * received. If a message is received the return value will be set at
+	 * that time to SPCI_SUCCESS.
 	 */
-	if (!block || current->interrupts.enabled_and_pending_count > 0) {
+	return_code = SPCI_INTERRUPTED;
+
+	/*
+	 * Don't block if there are enabled and pending interrupts, to match
+	 * behaviour of wait_for_interrupt.
+	 */
+	if (current->interrupts.enabled_and_pending_count > 0) {
 		goto out;
 	}
 
@@ -899,7 +901,7 @@
 out:
 	sl_unlock(&vm->lock);
 
-	return ret;
+	return return_code;
 }
 
 /**
diff --git a/src/arch/aarch64/handler.c b/src/arch/aarch64/handler.c
index e29ddf0..871a38e 100644
--- a/src/arch/aarch64/handler.c
+++ b/src/arch/aarch64/handler.c
@@ -437,9 +437,8 @@
 		ret.user_ret = api_spci_msg_send(arg1, current(), &ret.new);
 		break;
 
-	case HF_MAILBOX_RECEIVE:
-		ret.user_ret = hf_mailbox_receive_return_encode(
-			api_mailbox_receive(arg1, current(), &ret.new));
+	case SPCI_MSG_RECV_32:
+		ret.user_ret = api_spci_msg_recv(arg1, current(), &ret.new);
 		break;
 
 	case HF_MAILBOX_CLEAR:
diff --git a/test/hftest/hftest_service.c b/test/hftest/hftest_service.c
index 2a1b2a0..98c237b 100644
--- a/test/hftest/hftest_service.c
+++ b/test/hftest/hftest_service.c
@@ -91,7 +91,7 @@
 	hf_vm_configure(send_addr, recv_addr);
 
 	/* Receive the name of the service to run. */
-	hf_mailbox_receive(true);
+	spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 	memiter_init(&args, recv_msg->payload, recv_msg->length);
 	service = find_service(&args);
 	hf_mailbox_clear();
diff --git a/test/vmapi/gicv3/services/common.c b/test/vmapi/gicv3/services/common.c
index 79a9690..b6edc56 100644
--- a/test/vmapi/gicv3/services/common.c
+++ b/test/vmapi/gicv3/services/common.c
@@ -18,15 +18,18 @@
 
 #include "vmapi/hf/call.h"
 
+#include "hftest.h"
 /**
  * Try to receive a message from the mailbox, blocking if necessary, and
  * retrying if interrupted.
  */
-struct hf_mailbox_receive_return mailbox_receive_retry(void)
+int32_t mailbox_receive_retry(void)
 {
-	struct hf_mailbox_receive_return received;
+	int32_t received;
+
 	do {
-		received = hf_mailbox_receive(true);
-	} while (received.vm_id == HF_INVALID_VM_ID && received.size == 0);
+		received = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+	} while (received == SPCI_INTERRUPTED);
+
 	return received;
 }
diff --git a/test/vmapi/gicv3/services/common.h b/test/vmapi/gicv3/services/common.h
index ec81f1d..635fa0f 100644
--- a/test/vmapi/gicv3/services/common.h
+++ b/test/vmapi/gicv3/services/common.h
@@ -16,4 +16,4 @@
 
 #include "vmapi/hf/call.h"
 
-struct hf_mailbox_receive_return mailbox_receive_retry(void);
+int32_t mailbox_receive_retry(void);
diff --git a/test/vmapi/gicv3/services/timer.c b/test/vmapi/gicv3/services/timer.c
index 79a2b8a..2daf2b9 100644
--- a/test/vmapi/gicv3/services/timer.c
+++ b/test/vmapi/gicv3/services/timer.c
@@ -112,14 +112,9 @@
 				event_wait();
 			}
 		} else if (receive) {
-			struct hf_mailbox_receive_return received =
-				hf_mailbox_receive(true);
-			/*
-			 * Expect to be interrupted, not to actually
-			 * receive a message.
-			 */
-			EXPECT_EQ(received.vm_id, HF_INVALID_VM_ID);
-			EXPECT_EQ(received.size, 0);
+			int32_t res = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+
+			EXPECT_EQ(res, SPCI_INTERRUPTED);
 		} else {
 			/* Busy wait until the timer fires. */
 			while (!timer_fired) {
diff --git a/test/vmapi/primary_with_secondaries/no_services.c b/test/vmapi/primary_with_secondaries/no_services.c
index 9d7f29b..4d9b213 100644
--- a/test/vmapi/primary_with_secondaries/no_services.c
+++ b/test/vmapi/primary_with_secondaries/no_services.c
@@ -147,9 +147,8 @@
  */
 TEST(hf_mailbox_receive, cannot_receive_from_primary_blocking)
 {
-	struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
-	EXPECT_EQ(res.vm_id, HF_INVALID_VM_ID);
-	EXPECT_EQ(res.size, 0);
+	int32_t res = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+	EXPECT_NE(res, SPCI_SUCCESS);
 }
 
 /**
@@ -157,7 +156,6 @@
  */
 TEST(hf_mailbox_receive, cannot_receive_from_primary_non_blocking)
 {
-	struct hf_mailbox_receive_return res = hf_mailbox_receive(false);
-	EXPECT_EQ(res.vm_id, HF_INVALID_VM_ID);
-	EXPECT_EQ(res.size, 0);
+	int32_t res = spci_msg_recv(0);
+	EXPECT_NE(res, SPCI_SUCCESS);
 }
diff --git a/test/vmapi/primary_with_secondaries/services/echo.c b/test/vmapi/primary_with_secondaries/services/echo.c
index c58ccfb..bc33a25 100644
--- a/test/vmapi/primary_with_secondaries/services/echo.c
+++ b/test/vmapi/primary_with_secondaries/services/echo.c
@@ -26,7 +26,7 @@
 {
 	/* Loop, echo messages back to the sender. */
 	for (;;) {
-		hf_mailbox_receive(true);
+		spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 		struct spci_message *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
 
diff --git a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c b/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
index e6c66c0..424e3ab 100644
--- a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
+++ b/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
@@ -53,7 +53,7 @@
 
 	/* Loop, echo messages back to the sender. */
 	for (;;) {
-		hf_mailbox_receive(true);
+		spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 
 		struct spci_message *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
diff --git a/test/vmapi/primary_with_secondaries/services/interruptible.c b/test/vmapi/primary_with_secondaries/services/interruptible.c
index c5c67a5..523eaca 100644
--- a/test/vmapi/primary_with_secondaries/services/interruptible.c
+++ b/test/vmapi/primary_with_secondaries/services/interruptible.c
@@ -21,6 +21,7 @@
 #include "hf/dlog.h"
 
 #include "vmapi/hf/call.h"
+#include "vmapi/hf/spci.h"
 
 #include "hftest.h"
 #include "primary_with_secondary.h"
@@ -49,15 +50,14 @@
  * Try to receive a message from the mailbox, blocking if necessary, and
  * retrying if interrupted.
  */
-struct hf_mailbox_receive_return mailbox_receive_retry()
+int32_t mailbox_receive_retry()
 {
-	struct hf_mailbox_receive_return received = {
-		.vm_id = HF_INVALID_VM_ID,
-		.size = 0,
-	};
-	while (received.vm_id == HF_INVALID_VM_ID && received.size == 0) {
-		received = hf_mailbox_receive(true);
-	}
+	int32_t received;
+
+	do {
+		received = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+	} while (received == SPCI_INTERRUPTED);
+
 	return received;
 }
 
diff --git a/test/vmapi/primary_with_secondaries/services/interruptible_echo.c b/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
index dff3b6d..036566c 100644
--- a/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
+++ b/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
@@ -38,19 +38,20 @@
 	arch_irq_enable();
 
 	for (;;) {
-		struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
+		uint32_t res = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 		struct spci_message *message = SERVICE_SEND_BUFFER();
+		struct spci_message *recv_message = SERVICE_RECV_BUFFER();
 
 		/* Retry if interrupted but made visible with the yield. */
-		while (res.vm_id == HF_INVALID_VM_ID && res.size == 0) {
+		while (res == SPCI_INTERRUPTED) {
 			hf_vcpu_yield();
-			res = hf_mailbox_receive(true);
+			res = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 		}
 
-		memcpy(message->payload, SERVICE_RECV_BUFFER()->payload,
-		       res.size);
-		spci_message_init(message, res.size, HF_PRIMARY_VM_ID,
-				  SERVICE_VM0);
+		memcpy(message->payload, recv_message->payload,
+		       recv_message->length);
+		spci_message_init(message, recv_message->length,
+				  HF_PRIMARY_VM_ID, SERVICE_VM0);
 
 		hf_mailbox_clear();
 		spci_msg_send(0);
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index a826184..babb911 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -28,7 +28,7 @@
 {
 	/* Loop, writing message to the shared memory. */
 	for (;;) {
-		hf_mailbox_receive(true);
+		spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 		uint8_t *ptr;
 		size_t i;
 
@@ -60,7 +60,7 @@
 {
 	/* Loop, giving memory back to the sender. */
 	for (;;) {
-		hf_mailbox_receive(true);
+		spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 		uint8_t *ptr;
 
 		/* Check the memory was cleared. */
diff --git a/test/vmapi/primary_with_secondaries/services/receive_block.c b/test/vmapi/primary_with_secondaries/services/receive_block.c
index 59a10a5..b241b76 100644
--- a/test/vmapi/primary_with_secondaries/services/receive_block.c
+++ b/test/vmapi/primary_with_secondaries/services/receive_block.c
@@ -46,9 +46,8 @@
 	hf_interrupt_enable(EXTERNAL_INTERRUPT_ID_A, true);
 
 	for (i = 0; i < 10; ++i) {
-		struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
-		EXPECT_EQ(res.vm_id, HF_INVALID_VM_ID);
-		EXPECT_EQ(res.size, 0);
+		int32_t res = spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+		EXPECT_EQ(res, SPCI_INTERRUPTED);
 	}
 
 	memcpy(SERVICE_SEND_BUFFER()->payload, message, sizeof(message));
diff --git a/test/vmapi/primary_with_secondaries/services/relay.c b/test/vmapi/primary_with_secondaries/services/relay.c
index 627a461..7ac7ade 100644
--- a/test/vmapi/primary_with_secondaries/services/relay.c
+++ b/test/vmapi/primary_with_secondaries/services/relay.c
@@ -36,7 +36,7 @@
 		uint32_t next_message_size;
 
 		/* Receive the message to relay. */
-		hf_mailbox_receive(true);
+		spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 
 		/* Prepare to relay the message. */
 		struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
diff --git a/test/vmapi/primary_with_secondaries/services/spci_check.c b/test/vmapi/primary_with_secondaries/services/spci_check.c
index a81fc01..53a063a 100644
--- a/test/vmapi/primary_with_secondaries/services/spci_check.c
+++ b/test/vmapi/primary_with_secondaries/services/spci_check.c
@@ -42,7 +42,7 @@
 	};
 
 	/* Wait for single message to be sent by the primary VM. */
-	hf_mailbox_receive(true);
+	spci_msg_recv(SPCI_MSG_RECV_BLOCK);
 
 	/* Ensure message header has all fields correctly set. */
 	EXPECT_EQ(recv_buf->flags, expected_message.flags);