|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v3 1/1] plat/xen: Add grant table support for Xen PV (x86_64)
Simple grant table implementation ported and adapted from Mini-OS.
Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
plat/xen/Config.uk | 2 +
plat/xen/Makefile.uk | 2 +
plat/xen/gnttab.c | 241 +++++++++++++++++++++++++++++++++++++++
plat/xen/include/common/gnttab.h | 48 ++++++++
plat/xen/memory.c | 2 +
plat/xen/x86/gnttab.c | 59 ++++++++++
6 files changed, 354 insertions(+)
create mode 100644 plat/xen/gnttab.c
create mode 100644 plat/xen/include/common/gnttab.h
create mode 100644 plat/xen/x86/gnttab.c
diff --git a/plat/xen/Config.uk b/plat/xen/Config.uk
index f5ccd46..9c398f1 100644
--- a/plat/xen/Config.uk
+++ b/plat/xen/Config.uk
@@ -3,6 +3,8 @@ menuconfig PLAT_XEN
default n
depends on (ARCH_X86_32 || ARCH_X86_64 || ARCH_ARM_32)
select LIBUKDEBUG
+ select LIBUKLOCK
+ select LIBUKLOCK_SEMAPHORE
select LIBNOLIBC if !HAVE_LIBC
select LIBFDT if ARCH_ARM_32
select XEN_DBGEMERGENCY if ARCH_ARM_32
diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk
index 3305a84..45096cb 100644
--- a/plat/xen/Makefile.uk
+++ b/plat/xen/Makefile.uk
@@ -45,6 +45,7 @@ LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
$(LIBXENPLAT_BASE)/x86/entry64.S
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/mm.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/arch_events.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/arch_time.c
+LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/gnttab.c|x86
ifneq ($(XEN_HVMLITE),y)
LIBXENPLAT_ASFLAGS-y += -DCONFIG_PARAVIRT
@@ -70,3 +71,4 @@ LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/lcpu.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/console.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/shutdown.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/events.c
+LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/gnttab.c
diff --git a/plat/xen/gnttab.c b/plat/xen/gnttab.c
new file mode 100644
index 0000000..72fc075
--- /dev/null
+++ b/plat/xen/gnttab.c
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ * File: gnttab.c
+ * Author: Steven Smith (sos22@xxxxxxxxx)
+ * Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *
+ * Date: July 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Simple grant tables implementation. About as stupid as it's
+ * possible to be and still work.
+ *
+ ****************************************************************************
+ */
+#include <stdint.h>
+#ifdef DBGGNT
+#include <string.h>
+#endif
+#include <uk/arch/limits.h>
+#include <uk/arch/atomic.h>
+#include <uk/plat/lcpu.h>
+#include <uk/semaphore.h>
+#include <common/gnttab.h>
+#include <xen-x86/mm.h>
+
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#define NR_GRANT_FRAMES 4
+#define NR_GRANT_ENTRIES \
+ (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_v1_t))
+
+static struct gnttab {
+ int initialized;
+ struct uk_semaphore sem;
+ grant_entry_v1_t *table;
+ grant_ref_t gref_list[NR_GRANT_ENTRIES];
+#ifdef DBGGNT
+ char inuse[NR_GRANT_ENTRIES];
+#endif
+} gnttab;
+
+
+static grant_ref_t get_free_entry(void)
+{
+ grant_ref_t gref;
+ unsigned long flags;
+
+ uk_semaphore_down(&gnttab.sem);
+
+ flags = ukplat_lcpu_save_irqf();
+
+ gref = gnttab.gref_list[0];
+ UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES &&
+ gref < NR_GRANT_ENTRIES);
+ gnttab.gref_list[0] = gnttab.gref_list[gref];
+#ifdef DBGGNT
+ UK_ASSERT(!gnttab.inuse[gref]);
+ gnttab.inuse[gref] = 1;
+#endif
+
+ ukplat_lcpu_restore_irqf(flags);
+
+ return gref;
+}
+
+static void put_free_entry(grant_ref_t gref)
+{
+ unsigned long flags;
+
+ flags = ukplat_lcpu_save_irqf();
+
+#ifdef DBGGNT
+ UK_ASSERT(gnttab.inuse[gref]);
+ gnttab.inuse[gref] = 0;
+#endif
+ gnttab.gref_list[gref] = gnttab.gref_list[0];
+ gnttab.gref_list[0] = gref;
+
+ ukplat_lcpu_restore_irqf(flags);
+
+ uk_semaphore_up(&gnttab.sem);
+}
+
+grant_ref_t gnttab_grant_access(domid_t domid, unsigned long mfn,
+ int readonly)
+{
+ grant_ref_t gref;
+
+ gref = get_free_entry();
+ gnttab.table[gref].frame = mfn;
+ gnttab.table[gref].domid = domid;
+ wmb();
+ readonly *= GTF_readonly;
+ gnttab.table[gref].flags = GTF_permit_access | readonly;
+
+ return gref;
+}
+
+grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long mfn)
+{
+ grant_ref_t gref;
+
+ gref = get_free_entry();
+ gnttab.table[gref].frame = mfn;
+ gnttab.table[gref].domid = domid;
+ wmb();
+ gnttab.table[gref].flags = GTF_accept_transfer;
+
+ return gref;
+}
+
+int gnttab_end_access(grant_ref_t gref)
+{
+ __u16 flags, nflags;
+ __u16 *pflags;
+
+ UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES &&
+ gref < NR_GRANT_ENTRIES);
+
+ pflags = &gnttab.table[gref].flags;
+ nflags = *pflags;
+ do {
+ if ((flags = nflags) & (GTF_reading | GTF_writing)) {
+ uk_printd(DLVL_WARN,
+ "gref=%u still in use! (0x%x)\n", gref, flags);
+ return 0;
+ }
+ } while ((nflags = ukarch_compare_exchange_sync(pflags, flags, 0)) !=
flags);
+
+ put_free_entry(gref);
+
+ return 1;
+}
+
+unsigned long gnttab_end_transfer(grant_ref_t gref)
+{
+ unsigned long frame;
+ __u16 flags;
+ __u16 *pflags;
+
+ UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES &&
+ gref < NR_GRANT_ENTRIES);
+
+ pflags = &gnttab.table[gref].flags;
+ while (!((flags = *pflags) & GTF_transfer_committed)) {
+ if (ukarch_compare_exchange_sync(pflags, flags, 0) == flags) {
+ uk_printd(DLVL_INFO,
+ "Release unused transfer grant.\n");
+ put_free_entry(gref);
+ return 0;
+ }
+ }
+
+ /* If a transfer is in progress then wait until it is completed. */
+ while (!(flags & GTF_transfer_completed))
+ flags = *pflags;
+
+ /* Read the frame number /after/ reading completion status. */
+ rmb();
+ frame = gnttab.table[gref].frame;
+
+ put_free_entry(gref);
+
+ return frame;
+}
+
+grant_ref_t gnttab_alloc_and_grant(void **map, struct uk_alloc *a)
+{
+ void *page;
+ unsigned long mfn;
+ grant_ref_t gref;
+
+ UK_ASSERT(map != NULL);
+ UK_ASSERT(a != NULL);
+
+ page = uk_malloc_page(a);
+ if (page == NULL)
+ return GRANT_INVALID_REF;
+
+ mfn = virt_to_mfn(page);
+ gref = gnttab_grant_access(0, mfn, 0);
+
+ *map = page;
+
+ return gref;
+}
+
+static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
+
+const char *gnttabop_error(__s16 status)
+{
+ status = -status;
+ if (status < 0 || (__u16) status >= ARRAY_SIZE(gnttabop_error_msgs))
+ return "bad status";
+ else
+ return gnttabop_error_msgs[status];
+}
+
+void gnttab_init(void)
+{
+ grant_ref_t gref;
+
+ UK_ASSERT(gnttab.initialized == 0);
+
+ uk_semaphore_init(&gnttab.sem, 0);
+
+#ifdef DBGGNT
+ memset(gnttab.inuse, 1, sizeof(gnttab.inuse));
+#endif
+ for (gref = GNTTAB_NR_RESERVED_ENTRIES; gref < NR_GRANT_ENTRIES; gref++)
+ put_free_entry(gref);
+
+ gnttab.table = gnttab_arch_init(NR_GRANT_FRAMES);
+ if (gnttab.table == NULL)
+ UK_CRASH("Failed to initialize grant table\n");
+
+ uk_printd(DLVL_INFO, "Grant table mapped at %p.\n", gnttab.table);
+
+ gnttab.initialized = 1;
+}
+
+void gnttab_fini(void)
+{
+ struct gnttab_setup_table setup;
+ int rc;
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = 0;
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (rc) {
+ uk_printd(DLVL_ERR, "Hypercall error: %d\n", rc);
+ return;
+ }
+
+ gnttab.initialized = 0;
+}
diff --git a/plat/xen/include/common/gnttab.h b/plat/xen/include/common/gnttab.h
new file mode 100644
index 0000000..d4bb417
--- /dev/null
+++ b/plat/xen/include/common/gnttab.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* Taken from Mini-OS */
+
+#ifndef __GNTTAB_H__
+#define __GNTTAB_H__
+
+#include <uk/alloc.h>
+#include <xen/grant_table.h>
+
+#define GRANT_INVALID_REF 0
+
+void gnttab_init(void);
+void gnttab_fini(void);
+
+grant_ref_t gnttab_alloc_and_grant(void **map, struct uk_alloc *a);
+grant_ref_t gnttab_grant_access(domid_t domid, unsigned long pfn,
+ int readonly);
+grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
+unsigned long gnttab_end_transfer(grant_ref_t gref);
+int gnttab_end_access(grant_ref_t gref);
+
+const char *gnttabop_error(__s16 status);
+
+grant_entry_v1_t *gnttab_arch_init(int nr_grant_frames);
+
+#endif /* !__GNTTAB_H__ */
diff --git a/plat/xen/memory.c b/plat/xen/memory.c
index 6ae92f4..f84dca7 100644
--- a/plat/xen/memory.c
+++ b/plat/xen/memory.c
@@ -35,6 +35,7 @@
#include <string.h>
+#include <common/gnttab.h>
#if (defined __X86_32__) || (defined __X86_64__)
#include <xen-x86/setup.h>
#elif (defined __ARM_32__) || (defined __ARM_64__)
@@ -122,5 +123,6 @@ int ukplat_memregion_get(int i, struct
ukplat_memregion_desc *m)
int _ukplat_mem_mappings_init(void)
{
+ gnttab_init();
return 0;
}
diff --git a/plat/xen/x86/gnttab.c b/plat/xen/x86/gnttab.c
new file mode 100644
index 0000000..add3444
--- /dev/null
+++ b/plat/xen/x86/gnttab.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* Taken from Mini-OS */
+
+#include <stdint.h>
+#include <uk/print.h>
+#include <xen/xen.h>
+#include <xen/grant_table.h>
+#include <common/hypervisor.h>
+#include <xen-x86/mm.h>
+
+
+grant_entry_v1_t *gnttab_arch_init(int grant_frames_num)
+{
+ grant_entry_v1_t *gnte = NULL;
+ struct gnttab_setup_table setup;
+ unsigned long frames[grant_frames_num];
+ int rc;
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = grant_frames_num;
+ set_xen_guest_handle(setup.frame_list, frames);
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (rc) {
+ uk_printd(DLVL_ERR, "Hypercall error: %d\n", rc);
+ goto out;
+ }
+ if (setup.status != GNTST_okay) {
+ uk_printd(DLVL_ERR, "Hypercall status: %d\n", setup.status);
+ goto out;
+ }
+
+ gnte = map_frames(frames, grant_frames_num, ukplat_memallocator_get());
+
+out:
+ return gnte;
+}
--
2.11.0
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |