[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.