[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |