Export policy for selecting message recipient.

Previously this was a first come first served policy but the scheduler
may be in the position to make a better choice. This also conforms to
our intent of exporting policy outside of the hypervisor.

Change-Id: I8cee6ce9b976e5ed990616c896cd53ecd0f083c8
diff --git a/inc/hf/cpu.h b/inc/hf/cpu.h
index 6b4705a..6f358cd 100644
--- a/inc/hf/cpu.h
+++ b/inc/hf/cpu.h
@@ -63,11 +63,6 @@
 	uint32_t enabled_and_pending_count;
 };
 
-struct retval_state {
-	uintptr_t value;
-	bool force;
-};
-
 struct vcpu_fault_info {
 	ipaddr_t ipaddr;
 	vaddr_t vaddr;
@@ -78,19 +73,18 @@
 
 struct vcpu {
 	struct spinlock lock;
-	enum vcpu_state state;
-	struct cpu *cpu;
-	struct vm *vm;
-	struct vcpu *mailbox_next;
-	struct arch_regs regs;
-	struct interrupts interrupts;
 
 	/*
-	 * The following field is used to force a return value to be set the
-	 * next time a vCPU belonging to a secondary VM runs. For primary VMs,
-	 * 'regs' can be set directly.
+	 * The state is only changed in the context of the vCPU being run. This
+	 * ensures the scheduler can easily keep track of the vCPU state as
+	 * transitions are indicated by the return code from the run call.
 	 */
-	struct retval_state retval;
+	enum vcpu_state state;
+
+	struct cpu *cpu;
+	struct vm *vm;
+	struct arch_regs regs;
+	struct interrupts interrupts;
 
 	/*
 	 * Determine whether the 'regs' field is available for use. This is set
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 0eb8324..b3b7492 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -57,7 +57,6 @@
 	int16_t recv_bytes;
 	void *recv;
 	const void *send;
-	struct vcpu *recv_waiter;
 
 	/**
 	 * List of wait_entry structs representing VMs that want to be notified
diff --git a/inc/vmapi/hf/abi.h b/inc/vmapi/hf/abi.h
index b51d3a5..c24700c 100644
--- a/inc/vmapi/hf/abi.h
+++ b/inc/vmapi/hf/abi.h
@@ -36,34 +36,38 @@
 	/**
 	 * The vCPU is blocked waiting for an interrupt. The scheduler MUST take
 	 * it off the run queue and not call `hf_vcpu_run` on the vCPU until it
-	 * has injected an interrupt, sent it a message, or got a
-	 * `HF_VCPU_RUN_WAKE_UP` for it from another vCPU.
+	 * has injected an interrupt, received `HF_VCPU_RUN_WAKE_UP` for it
+	 * from another vCPU or the timeout provided in
+	 * `hf_vcpu_run_return.sleep` is not `HF_SLEEP_INDEFINITE` and the
+	 * specified duration has expired.
 	 */
 	HF_VCPU_RUN_WAIT_FOR_INTERRUPT = 2,
 
 	/**
-	 * The vCPU would like `hf_vcpu_run` to be called on another vCPU,
-	 * specified by `hf_vcpu_run_return.wake_up`. The scheduler MUST
-	 * either wake the vCPU in question up if it is blocked, or preempt and
-	 * re-run it if it is already running somewhere. This gives Hafnium a
-	 * chance to update any CPU state which might have changed.
+	 * The vCPU is blocked waiting for a message. The scheduler MUST take it
+	 * off the run queue and not call `hf_vcpu_run` on the vCPU until it has
+	 * injected an interrupt, sent it a message, or received
+	 * `HF_VCPU_RUN_WAKE_UP` for it from another vCPU from another vCPU or
+	 * the timeout provided in `hf_vcpu_run_return.sleep` is not
+	 * `HF_SLEEP_INDEFINITE` and the specified duration has expired.
 	 */
-	HF_VCPU_RUN_WAKE_UP = 3,
+	HF_VCPU_RUN_WAIT_FOR_MESSAGE = 3,
 
 	/**
-	 * A new message is available for the scheduler VM, as specified by
-	 * `hf_vcpu_run_return.message`.
+	 * Hafnium would like `hf_vcpu_run` to be called on another vCPU,
+	 * specified by `hf_vcpu_run_return.wake_up`. The scheduler MUST either
+	 * wake the vCPU in question up if it is blocked, or preempt and re-run
+	 * it if it is already running somewhere. This gives Hafnium a chance to
+	 * update any CPU state which might have changed.
 	 */
-	HF_VCPU_RUN_MESSAGE = 4,
+	HF_VCPU_RUN_WAKE_UP = 4,
 
 	/**
-	 * Like `HF_VCPU_RUN_WAIT_FOR_INTERRUPT`, but for a limited amount of
-	 * time, specified by `hf_vcpu_run_return.sleep`. After at least that
-	 * amount of time has passed, or any of the events listed for
-	 * `HF_VCPU_RUN_WAIT_FOR_INTERRUPT` occur, the scheduler MUST call
-	 * `hf_vcpu_run` on it again.
+	 * A message has been sent by the vCPU. The scheduler MUST run a vCPU
+	 * from the recipient VM and priority SHOULD be given to those vCPUs
+	 * that are waiting for a message.
 	 */
-	HF_VCPU_RUN_SLEEP = 5,
+	HF_VCPU_RUN_MESSAGE = 5,
 
 	/**
 	 * The vCPU has made the mailbox writable and there are pending waiters.
@@ -88,6 +92,7 @@
 			uint16_t vcpu;
 		} wake_up;
 		struct {
+			uint16_t vm_id;
 			uint32_t size;
 		} message;
 		struct {
@@ -135,8 +140,10 @@
 		break;
 	case HF_VCPU_RUN_MESSAGE:
 		ret |= (uint64_t)res.message.size << 32;
+		ret |= (uint64_t)res.message.vm_id << 16;
 		break;
-	case HF_VCPU_RUN_SLEEP:
+	case HF_VCPU_RUN_WAIT_FOR_INTERRUPT:
+	case HF_VCPU_RUN_WAIT_FOR_MESSAGE:
 		ret |= res.sleep.ns << 8;
 		break;
 	default:
@@ -163,8 +170,10 @@
 		break;
 	case HF_VCPU_RUN_MESSAGE:
 		ret.message.size = res >> 32;
+		ret.message.vm_id = (res >> 16) & 0xffff;
 		break;
-	case HF_VCPU_RUN_SLEEP:
+	case HF_VCPU_RUN_WAIT_FOR_INTERRUPT:
+	case HF_VCPU_RUN_WAIT_FOR_MESSAGE:
 		ret.sleep.ns = res >> 8;
 		break;
 	default:
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 7159379..5c8b1c6 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -115,12 +115,7 @@
  * 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.
  *
- * Returns -1 on failure, and on success either:
- *  - 0, if the caller is a secondary VM
- *  - the ID of the vCPU to run to receive the message, if the caller is the
- *    primary VM.
- *  - HF_INVALID_VCPU if the caller is the primary VM and no vCPUs on the target
- *    VM are currently waiting to receive a message.
+ * Returns -1 on failure and 0 on success.
  */
 static inline int64_t hf_mailbox_send(uint32_t vm_id, size_t size, bool notify)
 {
diff --git a/inc/vmapi/hf/types.h b/inc/vmapi/hf/types.h
index a575d4a6..5826e70 100644
--- a/inc/vmapi/hf/types.h
+++ b/inc/vmapi/hf/types.h
@@ -38,7 +38,9 @@
 
 /* Invalid values for fields to indicate absence or errors. */
 #define HF_INVALID_VM_ID 0xffffffff
-#define HF_INVALID_VCPU 0xffff
+
+/* Sleep value for an indefinite period of time. */
+#define HF_SLEEP_INDEFINITE 0xffffffffffffff
 
 /** The number of virtual interrupt IDs which are supported. */
 #define HF_NUM_INTIDS 64