Basic memory sharing.
The introduces the basic functionality for memory sharing. The API used
to invoke memory sharing is a placeholder while we decide on what the
proper interface should look like.
Change-Id: Ia5c2c224119d896b3fc2294b0828626ec325e1e7
diff --git a/inc/hf/api.h b/inc/hf/api.h
index 8357a89..e9ffe88 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -39,6 +39,8 @@
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);
+int64_t api_share_memory(uint32_t vm_id, ipaddr_t addr, size_t size,
+ enum hf_share share, struct vcpu *current);
struct vcpu *api_preempt(struct vcpu *current);
struct vcpu *api_yield(struct vcpu *current);
diff --git a/inc/hf/spinlock.h b/inc/hf/spinlock.h
index 7a307f6..57ce3a8 100644
--- a/inc/hf/spinlock.h
+++ b/inc/hf/spinlock.h
@@ -39,6 +39,21 @@
}
}
+/**
+ * Locks both locks, enforcing the lowest address first ordering for locks of
+ * the same kind.
+ */
+static inline void sl_lock_both(struct spinlock *a, struct spinlock *b)
+{
+ if (a < b) {
+ sl_lock(a);
+ sl_lock(b);
+ } else {
+ sl_lock(b);
+ sl_lock(a);
+ }
+}
+
static inline void sl_unlock(struct spinlock *l)
{
atomic_flag_clear_explicit(&l->v, memory_order_release);
diff --git a/inc/hf/std.h b/inc/hf/std.h
index c872fd4..6e5e82a 100644
--- a/inc/hf/std.h
+++ b/inc/hf/std.h
@@ -19,6 +19,8 @@
#include <stddef.h>
#include <stdint.h>
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
void *memset(void *s, int c, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
void *memmove(void *dst, const void *src, size_t n);
diff --git a/inc/vmapi/hf/abi.h b/inc/vmapi/hf/abi.h
index 451de41..4716f01 100644
--- a/inc/vmapi/hf/abi.h
+++ b/inc/vmapi/hf/abi.h
@@ -94,6 +94,26 @@
uint32_t size;
};
+enum hf_share {
+ /**
+ * Relinquish ownership and access to the memory and pass them to the
+ * recipient.
+ */
+ HF_MEMORY_GIVE,
+
+ /**
+ * Retain ownership of the memory but relinquish access to the
+ * recipient.
+ */
+ HF_MEMORY_LEND,
+
+ /**
+ * Retain ownership and access but additionally allow access to the
+ * recipient.
+ */
+ HF_MEMORY_SHARE,
+};
+
/**
* Encode an hf_vcpu_run_return struct in the 64-bit packing ABI.
*/
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 8014f8c..b0345e2 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -37,6 +37,7 @@
#define HF_INTERRUPT_ENABLE 0xff0b
#define HF_INTERRUPT_GET 0xff0c
#define HF_INTERRUPT_INJECT 0xff0d
+#define HF_SHARE_MEMORY 0xff0e
/** The amount of data that can be sent to a mailbox. */
#define HF_MAILBOX_SIZE 4096
@@ -223,3 +224,18 @@
return hf_call(HF_INTERRUPT_INJECT, target_vm_id, target_vcpu_idx,
intid);
}
+
+/**
+ * Shares a region of memory with another VM.
+ *
+ * Returns 0 on success or -1 if the sharing was not allowed or failed.
+ *
+ * TODO: replace this with a better API once we have decided what that should
+ * look like.
+ */
+static inline int64_t hf_share_memory(uint32_t vm_id, hf_ipaddr_t addr,
+ size_t size, enum hf_share share)
+{
+ return hf_call(HF_SHARE_MEMORY, (((uint64_t)vm_id) << 32) | share, addr,
+ size);
+}