[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)



On 06/27/2018 04:49 PM, Yuri Volchkov wrote:
> 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?

Ack.

>> +/* 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?

Right.

>> +{
>> +    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? :)

Already answered by Wei.

>> +    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?

Ack.

>> +                    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

Here the initial intention was to read the value the first time without
changing it. So maybe it would be better to just leave it as it is.

>> +
>> +    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

 


Rackspace

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