|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH 6/6] plat/xen: Add grant table support for Xen (x86_64)
Costin Lupu <costin.lupu@xxxxxxxxx> writes:
> 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>
This introduces libuklock dependency. I guess we need to reflect this in
corresponding Config.uk
> +#include <common/gnttab.h>
> +#include <xen-x86/mm.h>
> +
> +
> +#define NR_RESERVED_ENTRIES GNTTAB_NR_RESERVED_ENTRIES
Can we use GNTTAB_NR_RESERVED_ENTRIES directly instead?
> +/* 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)
Is it supposed to be a mfn, not pfn?
> +{
> + grant_ref_t gref;
> +
> + gref = get_free_entry();
> + gnttab.table[gref].frame = pfn;
> + gnttab.table[gref].domid = domid;
> + wmb();
Why the barrier is here not after setting the readonly flag? MiniOS and
Linux are doing the same, so I assume that is the right way. Maybe you
could enlighten me? :)
> + 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);
Over 80 chars, and not hard to fix. Could please consult to checkpatch.pl?
> + return 0;
> + }
> + } while ((nflags = ukarch_compare_exchange_sync(pflags, flags, 0)) !=
> flags);
Let's use a similar while loop as in gnttab_end_transfer here
> +
> + 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
>
--
Yuri Volchkov
Software Specialist
NEC Europe Ltd
Kurfürsten-Anlage 36
D-69115 Heidelberg
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |