[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 6/6] plat/xen: Add grant table support for Xen (x86_64)
Simple grant table implementation ported and adapted from Mini-OS. Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> --- plat/xen/Makefile.uk | 2 + plat/xen/gnttab.c | 237 +++++++++++++++++++++++++++++++++++++++ plat/xen/include/common/gnttab.h | 48 ++++++++ plat/xen/memory.c | 2 + plat/xen/x86/gnttab.c | 59 ++++++++++ 5 files changed, 348 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/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..a134632 --- /dev/null +++ b/plat/xen/gnttab.c @@ -0,0 +1,237 @@ +/* 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> + + +#define NR_RESERVED_ENTRIES GNTTAB_NR_RESERVED_ENTRIES +/* 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 >= 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 pfn, + int readonly) +{ + grant_ref_t gref; + + gref = get_free_entry(); + gnttab.table[gref].frame = pfn; + 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 pfn) +{ + grant_ref_t gref; + + gref = get_free_entry(); + gnttab.table[gref].frame = pfn; + 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 >= 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, "g.e. still in use! (%x)\n", 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 >= 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 = 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 |