Add support for notifying VMs when mailboxes become writable.
This allows VMs to know when they can retry sending messages to another
VM after an attempt fails because the recipient's mailbox is not
available.
Change-Id: Ib20159f7ecf81544e40149edcd663876c58851c7
diff --git a/inc/hf/api.h b/inc/hf/api.h
index f3e189a..8357a89 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -29,14 +29,16 @@
struct hf_vcpu_run_return api_vcpu_run(uint32_t vm_id, uint32_t vcpu_idx,
const struct vcpu *current,
struct vcpu **next);
-int64_t api_vm_configure(ipaddr_t send, ipaddr_t recv,
- const struct vcpu *current);
+int64_t api_vm_configure(ipaddr_t send, ipaddr_t recv, struct vcpu *current,
+ struct vcpu **next);
int64_t api_mailbox_send(uint32_t vm_id, size_t size, bool notify,
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(const struct vcpu *current);
+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);
struct vcpu *api_preempt(struct vcpu *current);
struct vcpu *api_yield(struct vcpu *current);
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 6a140b8..75096a5 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -17,6 +17,7 @@
#pragma once
#include "hf/cpu.h"
+#include "hf/list.h"
#include "hf/mm.h"
#include "hf/mpool.h"
@@ -31,6 +32,23 @@
mailbox_state_read,
};
+struct wait_entry {
+ /** The VM that is waiting for a mailbox to become writable. */
+ struct vm *waiting_vm;
+
+ /**
+ * Links used to add entry to a VM's waiter_list. This is protected by
+ * the notifying VM's lock.
+ */
+ struct list_entry wait_links;
+
+ /**
+ * Links used to add entry to a VM's ready_list. This is protected by
+ * the waiting VM's lock.
+ */
+ struct list_entry ready_links;
+};
+
struct mailbox {
enum mailbox_state state;
uint32_t recv_from_id;
@@ -38,6 +56,20 @@
void *recv;
const void *send;
struct vcpu *recv_waiter;
+
+ /**
+ * List of wait_entry structs representing VMs that want to be notified
+ * when the mailbox becomes writable. Once the mailbox does become
+ * writable, the entry is removed from this list and added to the
+ * waiting VM's ready_list.
+ */
+ struct list_entry waiter_list;
+
+ /**
+ * List of wait_entry structs representing VMs whose mailboxes became
+ * writable since the owner of the mailbox registers for notification.
+ */
+ struct list_entry ready_list;
};
struct vm {
@@ -48,9 +80,19 @@
struct vcpu vcpus[MAX_CPUS];
struct mm_ptable ptable;
struct mailbox mailbox;
+
+ /** Wait entries to be used when waiting on other VM mailboxes. */
+ struct wait_entry wentry[MAX_VMS];
+};
+
+/** Encapsulates a VM whose lock is held. */
+struct vm_locked {
+ struct vm *vm;
};
bool vm_init(uint32_t vcpu_count, struct mpool *ppool, struct vm **new_vm);
uint32_t vm_get_count(void);
struct vm *vm_get(uint32_t id);
void vm_start_vcpu(struct vm *vm, size_t index, ipaddr_t entry, uintreg_t arg);
+void vm_lock(struct vm *vm, struct vm_locked *locked);
+void vm_unlock(struct vm_locked *locked);