Use more macros for the API.

 * Constants
 * Packing and unpacking return values
 * Avoid hack of shifting vcpu indicies

Change-Id: I965d01fb561eeb437be9804588fa8a8bfc69d486
diff --git a/driver/linux b/driver/linux
index 5570423..b3a61b5 160000
--- a/driver/linux
+++ b/driver/linux
@@ -1 +1 @@
-Subproject commit 5570423fa47f8559d85b4db39a93ba3afba05cad
+Subproject commit b3a61b5fe4faf0f1111c203e385b1f100ecadc74
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index e8391f6..2195113 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -19,12 +19,6 @@
 /* Keep macro alignment */
 /* clang-format off */
 
-/* Return values for vcpu_run() hypervisor call. */
-#define HF_VCPU_YIELD              0x00
-#define HF_VCPU_WAIT_FOR_INTERRUPT 0x01
-#define HF_VCPU_WAKE_UP            0x02
-#define HF_VCPU_RESPONSE_READY     0x03
-
 /* TODO: Define constants below according to spec. */
 #define HF_VCPU_RUN         0xff00
 #define HF_VM_GET_COUNT     0xff01
@@ -35,6 +29,19 @@
 #define HF_RPC_ACK          0xff06
 #define HF_RPC_REPLY        0xff07
 
+/* Return codes for hf_vcpu_run(). */
+#define HF_VCPU_RUN_YIELD              0x00
+#define HF_VCPU_RUN_WAIT_FOR_INTERRUPT 0x01
+#define HF_VCPU_RUN_WAKE_UP            0x02
+#define HF_VCPU_RUN_RESPONSE_READY     0x03
+
+/* Construct and destruct the hf_vcpu_run() response. */
+#define HF_VCPU_RUN_RESPONSE(code, data) ((code & 0xff) | (data << 8))
+#define HF_VCPU_RUN_CODE(ret) (ret & 0xff)
+#define HF_VCPU_RUN_DATA(ret) (ret >> 8)
+
+#define HF_RPC_REQUEST_MAX_SIZE 4096
+
 /* clang-format on */
 
 /**
diff --git a/src/api.c b/src/api.c
index 4176941..947982c 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1,10 +1,16 @@
 #include "hf/api.h"
 
+#include <assert.h>
+
 #include "hf/std.h"
 #include "hf/vm.h"
 
 #include "vmapi/hf/call.h"
 
+static_assert(HF_RPC_REQUEST_MAX_SIZE == PAGE_SIZE,
+	      "Currently, a page is mapped for the send and receive buffers so "
+	      "the maximum request is the size of a page.");
+
 struct vm secondary_vm[MAX_VMS];
 uint32_t secondary_vm_count;
 struct vm primary_vm;
@@ -66,28 +72,28 @@
 
 	/* Only the primary VM can switch vcpus. */
 	if (cpu()->current->vm != &primary_vm) {
-		return HF_VCPU_WAIT_FOR_INTERRUPT;
+		return HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0);
 	}
 
 	if (vm_idx >= secondary_vm_count) {
-		return HF_VCPU_WAIT_FOR_INTERRUPT;
+		return HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0);
 	}
 
 	vm = secondary_vm + vm_idx;
 	if (vcpu_idx >= vm->vcpu_count) {
-		return HF_VCPU_WAIT_FOR_INTERRUPT;
+		return HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0);
 	}
 
 	vcpu = vm->vcpus + vcpu_idx;
 
 	sl_lock(&vcpu->lock);
 	if (vcpu->state != vcpu_state_ready) {
-		ret = HF_VCPU_WAIT_FOR_INTERRUPT;
+		ret = HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0);
 	} else {
 		vcpu->state = vcpu_state_running;
 		vm_set_current(vm);
 		*next = vcpu;
-		ret = HF_VCPU_YIELD;
+		ret = HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_YIELD, 0);
 	}
 	sl_unlock(&vcpu->lock);
 
@@ -100,8 +106,9 @@
  */
 struct vcpu *api_wait_for_interrupt(void)
 {
-	return api_switch_to_primary(HF_VCPU_WAIT_FOR_INTERRUPT,
-				     vcpu_state_blocked_interrupt);
+	return api_switch_to_primary(
+		HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0),
+		vcpu_state_blocked_interrupt);
 }
 
 /**
@@ -230,7 +237,7 @@
 
 		if (!to->rpc.recv_waiter) {
 			to->rpc.state = rpc_state_pending;
-			ret = 0;
+			ret = to->vcpu_count;
 		} else {
 			struct vcpu *to_vcpu = to->rpc.recv_waiter;
 
@@ -246,7 +253,7 @@
 			arch_regs_set_retval(&to_vcpu->regs, size);
 			sl_unlock(&to_vcpu->lock);
 
-			ret = to_vcpu - to->vcpus + 1;
+			ret = to_vcpu - to->vcpus;
 		}
 	}
 
@@ -298,8 +305,10 @@
 		 * Inidicate to primary VM that this vcpu blocked waiting for an
 		 * interrupt.
 		 */
-		arch_regs_set_retval(&(*next)->regs,
-				     HF_VCPU_WAIT_FOR_INTERRUPT);
+		arch_regs_set_retval(
+			&(*next)->regs,
+			HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT,
+					     0));
 		ret = 0;
 	}
 	sl_unlock(&vm->lock);
@@ -368,8 +377,9 @@
 	 * Switch back to primary VM so that it is aware that a response was
 	 * received. But we leave the current vcpu still runnable.
 	 */
-	*next = api_switch_to_primary((size << 8) | HF_VCPU_RESPONSE_READY,
-				      vcpu_state_ready);
+	*next = api_switch_to_primary(
+		HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_RESPONSE_READY, size),
+		vcpu_state_ready);
 
 	return 0;
 }
diff --git a/src/arch/aarch64/handler.c b/src/arch/aarch64/handler.c
index d79ac4c..82ae461 100644
--- a/src/arch/aarch64/handler.c
+++ b/src/arch/aarch64/handler.c
@@ -214,7 +214,8 @@
 	/* TODO: Only switch if we know the interrupt was not for the secondary
 	 * VM. */
 	/* Switch back to primary VM, interrupts will be handled there. */
-	return api_switch_to_primary(HF_VCPU_YIELD, vcpu_state_ready);
+	return api_switch_to_primary(HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_YIELD, 0),
+				     vcpu_state_ready);
 }
 
 struct vcpu *sync_lower_exception(uint64_t esr)