Update spci_msg_send to new SPCI beta API.

This removes the header in the message buffers, as the header data is now
passed in the SPCI_MSG_SEND parameters.

Bug: 141469322
Change-Id: I3a61f5470fd95ba2d47df33f5c96466ba286af85
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 1b81c4a..16e8197 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -158,7 +158,6 @@
     "manifest_test.cc",
     "mm_test.cc",
     "mpool_test.cc",
-    "spci_test.cc",
     "string_test.cc",
   ]
   sources += [ "layout_fake.c" ]
diff --git a/src/api.c b/src/api.c
index 2034ae9..d11b305 100644
--- a/src/api.c
+++ b/src/api.c
@@ -352,9 +352,9 @@
 {
 	return (struct spci_value){
 		.func = SPCI_MSG_SEND_32,
-		.arg1 = receiver->mailbox.recv->source_vm_id << 16 |
-			receiver->id,
-		.arg3 = receiver->mailbox.recv->length};
+		.arg1 = (receiver->mailbox.recv_sender << 16) | receiver->id,
+		.arg3 = receiver->mailbox.recv_size,
+		.arg4 = receiver->mailbox.recv_attributes};
 }
 
 /**
@@ -846,8 +846,10 @@
  * If the recipient's receive buffer is busy, it can optionally register the
  * caller to be notified when the recipient's receive buffer becomes available.
  */
-spci_return_t api_spci_msg_send(uint32_t attributes, struct vcpu *current,
-				struct vcpu **next)
+struct spci_value api_spci_msg_send(spci_vm_id_t sender_vm_id,
+				    spci_vm_id_t receiver_vm_id, uint32_t size,
+				    uint32_t attributes, struct vcpu *current,
+				    struct vcpu **next)
 {
 	struct vm *from = current->vm;
 	struct vm *to;
@@ -857,59 +859,49 @@
 	struct hf_vcpu_run_return primary_ret = {
 		.code = HF_VCPU_RUN_MESSAGE,
 	};
-	struct spci_message from_msg_replica;
-	struct spci_message *to_msg;
-	const struct spci_message *from_msg;
+	const void *from_msg;
 
-	uint32_t size;
-
-	int64_t ret;
+	struct spci_value ret;
 	bool notify = (attributes & SPCI_MSG_SEND_NOTIFY_MASK) ==
 		      SPCI_MSG_SEND_NOTIFY;
 
+	/* Ensure sender VM ID corresponds to the current VM. */
+	if (sender_vm_id != from->id) {
+		return spci_error(SPCI_INVALID_PARAMETERS);
+	}
+
+	/* Disallow reflexive requests as this suggests an error in the VM. */
+	if (receiver_vm_id == from->id) {
+		return spci_error(SPCI_INVALID_PARAMETERS);
+	}
+
+	/* Limit the size of transfer. */
+	if (size > SPCI_MSG_PAYLOAD_MAX) {
+		return spci_error(SPCI_INVALID_PARAMETERS);
+	}
+
 	/*
-	 * Check that the sender has configured its send buffer. Copy the
-	 * message header. If the tx mailbox at from_msg is configured (i.e.
-	 * from_msg != NULL) then it can be safely accessed after releasing the
-	 * lock since the tx mailbox address can only be configured once.
+	 * Check that the sender has configured its send buffer. If the tx
+	 * mailbox at from_msg is configured (i.e. from_msg != NULL) then it can
+	 * be safely accessed after releasing the lock since the tx mailbox
+	 * address can only be configured once.
 	 */
 	sl_lock(&from->lock);
 	from_msg = from->mailbox.send;
 	sl_unlock(&from->lock);
 
 	if (from_msg == NULL) {
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
-	/*
-	 * Note that the payload is not copied when the message header is.
-	 */
-	from_msg_replica = *from_msg;
-
-	/* Ensure source VM id corresponds to the current VM. */
-	if (from_msg_replica.source_vm_id != from->id) {
-		return SPCI_INVALID_PARAMETERS;
-	}
-
-	size = from_msg_replica.length;
-	/* Limit the size of transfer. */
-	if (size > SPCI_MSG_PAYLOAD_MAX) {
-		return SPCI_INVALID_PARAMETERS;
-	}
-
-	/* Disallow reflexive requests as this suggests an error in the VM. */
-	if (from_msg_replica.target_vm_id == from->id) {
-		return SPCI_INVALID_PARAMETERS;
-	}
-
-	/* Ensure the target VM exists. */
-	to = vm_find(from_msg_replica.target_vm_id);
+	/* Ensure the receiver VM exists. */
+	to = vm_find(receiver_vm_id);
 	if (to == NULL) {
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
 	/*
-	 * Hf needs to hold the lock on <to> before the mailbox state is
+	 * Hafnium needs to hold the lock on <to> before the mailbox state is
 	 * checked. The lock on <to> must be held until the information is
 	 * copied to <to> Rx buffer. Since in
 	 * spci_msg_handle_architected_message we may call api_spci_share_memory
@@ -921,13 +913,12 @@
 	if (to->mailbox.state != MAILBOX_STATE_EMPTY ||
 	    to->mailbox.recv == NULL) {
 		/*
-		 * Fail if the target isn't currently ready to receive data,
+		 * Fail if the receiver isn't currently ready to receive data,
 		 * setting up for notification if requested.
 		 */
 		if (notify) {
 			struct wait_entry *entry =
-				&current->vm->wait_entries
-					 [from_msg_replica.target_vm_id];
+				&from->wait_entries[receiver_vm_id];
 
 			/* Append waiter only if it's not there yet. */
 			if (list_empty(&entry->wait_links)) {
@@ -936,72 +927,68 @@
 			}
 		}
 
-		ret = SPCI_BUSY;
+		ret = spci_error(SPCI_BUSY);
 		goto out;
 	}
 
-	to_msg = to->mailbox.recv;
-
-	/* Handle architected messages. */
-	if ((from_msg_replica.flags & SPCI_MESSAGE_IMPDEF_MASK) !=
-	    SPCI_MESSAGE_IMPDEF) {
+	/* Handle legacy memory sharing messages. */
+	if ((attributes & SPCI_MSG_SEND_LEGACY_MEMORY_MASK) ==
+	    SPCI_MSG_SEND_LEGACY_MEMORY) {
 		/*
 		 * Buffer holding the internal copy of the shared memory
 		 * regions.
 		 */
-		uint8_t *message_buffer = cpu_get_buffer(current->cpu->id);
+		struct spci_architected_message_header
+			*architected_message_replica =
+				(struct spci_architected_message_header *)
+					cpu_get_buffer(current->cpu->id);
 		uint32_t message_buffer_size =
 			cpu_get_buffer_size(current->cpu->id);
 
 		struct spci_architected_message_header *architected_header =
-			spci_get_architected_message_header(from->mailbox.send);
+			(struct spci_architected_message_header *)from_msg;
 
-		const struct spci_architected_message_header
-			*architected_message_replica;
-
-		if (from_msg_replica.length > message_buffer_size) {
-			ret = SPCI_INVALID_PARAMETERS;
+		if (size > message_buffer_size) {
+			ret = spci_error(SPCI_INVALID_PARAMETERS);
 			goto out;
 		}
 
-		if (from_msg_replica.length <
-		    sizeof(struct spci_architected_message_header)) {
-			ret = SPCI_INVALID_PARAMETERS;
+		if (size < sizeof(struct spci_architected_message_header)) {
+			ret = spci_error(SPCI_INVALID_PARAMETERS);
 			goto out;
 		}
 
-		/* Copy the architected message into an internal buffer. */
-		memcpy_s(message_buffer, message_buffer_size,
-			 architected_header, from_msg_replica.length);
-
-		architected_message_replica =
-			(struct spci_architected_message_header *)
-				message_buffer;
+		/* Copy the architected message into the internal buffer. */
+		memcpy_s(architected_message_replica, message_buffer_size,
+			 architected_header, size);
 
 		/*
-		 * Note that message_buffer is passed as the third parameter to
-		 * spci_msg_handle_architected_message. The execution flow
-		 * commencing at spci_msg_handle_architected_message will make
-		 * several accesses to fields in message_buffer. The memory area
-		 * message_buffer must be exclusively owned by Hf so that TOCTOU
-		 * issues do not arise.
+		 * Note that architected_message_replica is passed as the third
+		 * parameter to spci_msg_handle_architected_message. The
+		 * execution flow commencing at
+		 * spci_msg_handle_architected_message will make several
+		 * accesses to fields in architected_message_replica. The memory
+		 * area architected_message_replica must be exclusively owned by
+		 * Hafnium so that TOCTOU issues do not arise.
 		 */
 		ret = spci_msg_handle_architected_message(
 			vm_from_to_lock.vm1, vm_from_to_lock.vm2,
-			architected_message_replica, &from_msg_replica, to_msg);
+			architected_message_replica, size);
 
-		if (ret != SPCI_SUCCESS) {
+		if (ret.func != SPCI_SUCCESS_32) {
 			goto out;
 		}
 	} else {
 		/* Copy data. */
-		memcpy_s(to_msg->payload, SPCI_MSG_PAYLOAD_MAX,
-			 from->mailbox.send->payload, size);
-		*to_msg = from_msg_replica;
+		memcpy_s(to->mailbox.recv, SPCI_MSG_PAYLOAD_MAX, from_msg,
+			 size);
+		to->mailbox.recv_size = size;
+		to->mailbox.recv_sender = sender_vm_id;
+		to->mailbox.recv_attributes = 0;
+		ret = (struct spci_value){.func = SPCI_SUCCESS_32};
 	}
 
 	primary_ret.message.vm_id = to->id;
-	ret = SPCI_SUCCESS;
 
 	/* Messages for the primary VM are delivered directly. */
 	if (to->id == HF_PRIMARY_VM_ID) {
@@ -1429,11 +1416,10 @@
  *     the request.
  *  Success is indicated by SPCI_SUCCESS.
  */
-spci_return_t api_spci_share_memory(struct vm_locked to_locked,
-				    struct vm_locked from_locked,
-				    struct spci_memory_region *memory_region,
-				    uint32_t memory_to_attributes,
-				    enum spci_memory_share share)
+struct spci_value api_spci_share_memory(
+	struct vm_locked to_locked, struct vm_locked from_locked,
+	struct spci_memory_region *memory_region, uint32_t memory_to_attributes,
+	enum spci_memory_share share)
 {
 	struct vm *to = to_locked.vm;
 	struct vm *from = from_locked.vm;
@@ -1441,7 +1427,7 @@
 	int from_mode;
 	int to_mode;
 	struct mpool local_page_pool;
-	int64_t ret;
+	struct spci_value ret;
 	paddr_t pa_begin;
 	paddr_t pa_end;
 	ipaddr_t begin;
@@ -1451,7 +1437,7 @@
 
 	/* Disallow reflexive shares as this suggests an error in the VM. */
 	if (to == from) {
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
 	/*
@@ -1475,7 +1461,7 @@
 	if (!spci_msg_check_transition(to, from, share, &orig_from_mode, begin,
 				       end, memory_to_attributes, &from_mode,
 				       &to_mode)) {
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
 	pa_begin = pa_from_ipa(begin);
@@ -1487,7 +1473,7 @@
 	 */
 	if (!mm_vm_identity_map(&from->ptable, pa_begin, pa_end, from_mode,
 				NULL, &local_page_pool)) {
-		ret = SPCI_NO_MEMORY;
+		ret = spci_error(SPCI_NO_MEMORY);
 		goto out;
 	}
 
@@ -1498,7 +1484,7 @@
 		/* Recover any memory consumed in failed mapping. */
 		mm_vm_defrag(&from->ptable, &local_page_pool);
 
-		ret = SPCI_NO_MEMORY;
+		ret = spci_error(SPCI_NO_MEMORY);
 
 		CHECK(mm_vm_identity_map(&from->ptable, pa_begin, pa_end,
 					 orig_from_mode, NULL,
@@ -1507,10 +1493,9 @@
 		goto out;
 	}
 
-	ret = SPCI_SUCCESS;
+	ret = (struct spci_value){.func = SPCI_SUCCESS_32};
 
 out:
-
 	mpool_fini(&local_page_pool);
 
 	return ret;
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 00ba80b..c4719ab 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -324,7 +324,11 @@
 
 		return true;
 	case SPCI_MSG_SEND_32:
-		args->func = api_spci_msg_send(args->arg1, current(), next);
+		*args = api_spci_msg_send(spci_msg_send_sender(*args),
+					  spci_msg_send_receiver(*args),
+					  spci_msg_send_size(*args),
+					  spci_msg_send_attributes(*args),
+					  current(), next);
 		return true;
 	case SPCI_MSG_WAIT_32:
 		*args = api_spci_msg_recv(true, current(), next);
diff --git a/src/spci_architected_message.c b/src/spci_architected_message.c
index 28d5fc7..ec2041e 100644
--- a/src/spci_architected_message.c
+++ b/src/spci_architected_message.c
@@ -23,7 +23,7 @@
  * Check if the message length and the number of memory region constituents
  * match, if the check is correct call the memory sharing routine.
  */
-static spci_return_t spci_validate_call_share_memory(
+static struct spci_value spci_validate_call_share_memory(
 	struct vm_locked to_locked, struct vm_locked from_locked,
 	struct spci_memory_region *memory_region, uint32_t memory_share_size,
 	uint32_t memory_to_attributes, enum spci_memory_share share)
@@ -38,7 +38,7 @@
 	    sizeof(struct spci_memory_region) +
 		    (sizeof(struct spci_memory_region_constituent) *
 		     max_count)) {
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
 	return api_spci_share_memory(to_locked, from_locked, memory_region,
@@ -50,13 +50,13 @@
  * corresponding api functions implementing the functionality requested
  * in the architected message.
  */
-spci_return_t spci_msg_handle_architected_message(
+struct spci_value spci_msg_handle_architected_message(
 	struct vm_locked to_locked, struct vm_locked from_locked,
 	const struct spci_architected_message_header
 		*architected_message_replica,
-	struct spci_message *from_msg_replica, struct spci_message *to_msg)
+	uint32_t size)
 {
-	int64_t ret;
+	struct spci_value ret;
 	struct spci_memory_region *memory_region;
 	uint32_t to_mode;
 	uint32_t message_type;
@@ -70,8 +70,7 @@
 					architected_message_replica->payload;
 
 		memory_share_size =
-			from_msg_replica->length -
-			sizeof(struct spci_architected_message_header);
+			size - sizeof(struct spci_architected_message_header);
 
 		/* TODO: Add memory attributes. */
 		to_mode = MM_MODE_R | MM_MODE_W | MM_MODE_X;
@@ -87,8 +86,7 @@
 					architected_message_replica->payload;
 
 		memory_share_size =
-			from_msg_replica->length -
-			sizeof(struct spci_architected_message_header);
+			size - sizeof(struct spci_architected_message_header);
 
 		to_mode = MM_MODE_R | MM_MODE_W | MM_MODE_X;
 
@@ -111,8 +109,7 @@
 		memory_region =
 			(struct spci_memory_region *)lend_descriptor->payload;
 		memory_share_size =
-			from_msg_replica->length -
-			sizeof(struct spci_architected_message_header) -
+			size - sizeof(struct spci_architected_message_header) -
 			sizeof(struct spci_memory_lend);
 
 		to_mode = spci_memory_attrs_to_mode(borrower_attributes);
@@ -126,7 +123,7 @@
 
 	default:
 		dlog("Invalid memory sharing message.\n");
-		return SPCI_INVALID_PARAMETERS;
+		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
 	/* Copy data to the destination Rx. */
@@ -138,11 +135,14 @@
 	 * in the destination Rx buffer. This mechanism will be defined at the
 	 * spec level.
 	 */
-	if (ret == SPCI_SUCCESS) {
-		memcpy_s(to_msg->payload, SPCI_MSG_PAYLOAD_MAX,
-			 architected_message_replica, from_msg_replica->length);
+	if (ret.func == SPCI_SUCCESS_32) {
+		memcpy_s(to_locked.vm->mailbox.recv, SPCI_MSG_PAYLOAD_MAX,
+			 architected_message_replica, size);
+		to_locked.vm->mailbox.recv_size = size;
+		to_locked.vm->mailbox.recv_sender = from_locked.vm->id;
+		to_locked.vm->mailbox.recv_attributes =
+			SPCI_MSG_SEND_LEGACY_MEMORY;
 	}
-	*to_msg = *from_msg_replica;
 
 	return ret;
 }
diff --git a/src/spci_test.cc b/src/spci_test.cc
deleted file mode 100644
index a3191cc..0000000
--- a/src/spci_test.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2019 The Hafnium Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-extern "C" {
-#include "vmapi/hf/spci.h"
-}
-
-#include <gmock/gmock.h>
-
-namespace
-{
-using ::testing::Eq;
-
-/**
- * Ensure that spci_message_init is correctly setting the expected fields in the
- * SPCI common message header.
- */
-TEST(spci, spci_message_init)
-{
-	spci_message header;
-	spci_message compare_header = {
-		.flags = SPCI_MESSAGE_IMPDEF_MASK,
-		.length = 1,
-		.target_vm_id = 2,
-		.source_vm_id = 3,
-	};
-
-	memset(&header, 0xff, sizeof(header));
-	spci_message_init(&header, 1, 2, 3);
-
-	EXPECT_THAT(memcmp(&header, &compare_header, sizeof(header)), 0);
-}
-} /* namespace */