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