From: Simon Kuenzer Date: Wed, 11 Dec 2024 02:04:21 +0000 (-0800) Subject: drivers/xengnttab: Move grant table to own library X-Git-Tag: RELEASE-0.18.0~9 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=42c888a705f66a1cdec822980c550101ddb5f8c5;p=unikraft%2Funikraft.git drivers/xengnttab: Move grant table to own library This commit moves the code for the Xen grant table from the Xen platform library to a separate driver library. This follows the goal of decomposing `libxenplat`. All Xen drivers that require grant table support (`9pfront`, `blkfront`, `netfront`) will specify their dependency to `libxengnttab` with `select`. This simplifies the automatic configuration of dependencies. For example, if an application requires networking and selects `uknetdev`, `netfront` is automatically added to a build and will automatically resolve its dependencies. Signed-off-by: Simon Kuenzer Reviewed-by: Oleksii Moisieiev Reviewed-by: Oleksii Moisieiev Reviewed-by: Michalis Pappas Approved-by: Michalis Pappas GitHub-Closes: #1501 --- diff --git a/drivers/xen/9pfront/9pfront.h b/drivers/xen/9pfront/9pfront.h index 77be13400..c3f6381d7 100644 --- a/drivers/xen/9pfront/9pfront.h +++ b/drivers/xen/9pfront/9pfront.h @@ -43,7 +43,7 @@ #endif #include #include -#include +#include struct p9front_dev_ring { /* Backpointer to the p9front device. */ diff --git a/drivers/xen/9pfront/Config.uk b/drivers/xen/9pfront/Config.uk index 0ffa3bbc6..ed971c2c6 100644 --- a/drivers/xen/9pfront/Config.uk +++ b/drivers/xen/9pfront/Config.uk @@ -2,6 +2,7 @@ menuconfig LIB9PFRONT bool "9pfront: Xen 9pfs volumes" select LIBXENBUS select LIBXENHEADERS + select LIBXENGNTTAB depends on HAVE_XENBUS depends on LIBUK9P help diff --git a/drivers/xen/Makefile.uk b/drivers/xen/Makefile.uk index c017a7cdc..bf59397a9 100644 --- a/drivers/xen/Makefile.uk +++ b/drivers/xen/Makefile.uk @@ -7,6 +7,7 @@ UK_DRIV_XEN_BASE := $(UK_DRIV_BASE)/xen $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/xenheaders)) +$(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/xengnttab)) $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/9pfront)) $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/blkfront)) $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/netfront)) diff --git a/drivers/xen/blkfront/Config.uk b/drivers/xen/blkfront/Config.uk index 2b2f6ba69..fb8347154 100644 --- a/drivers/xen/blkfront/Config.uk +++ b/drivers/xen/blkfront/Config.uk @@ -2,6 +2,7 @@ menuconfig LIBBLKFRONT bool "blkfront: Xen block devices" select LIBXENHEADERS select LIBXENBUS + select LIBXENGNTTAB depends on HAVE_XENBUS depends on LIBUKBLKDEV help diff --git a/drivers/xen/blkfront/blkfront.h b/drivers/xen/blkfront/blkfront.h index 97e858371..440f4c3f7 100644 --- a/drivers/xen/blkfront/blkfront.h +++ b/drivers/xen/blkfront/blkfront.h @@ -47,7 +47,7 @@ #endif #include -#include +#include #include #define BLK_RING_PAGES_NUM 1 diff --git a/drivers/xen/netfront/Config.uk b/drivers/xen/netfront/Config.uk index 2323bfb45..70c6d1838 100644 --- a/drivers/xen/netfront/Config.uk +++ b/drivers/xen/netfront/Config.uk @@ -2,7 +2,7 @@ config LIBNETFRONT bool "netfront: Xen network interfaces" select LIBXENHEADERS select LIBXENBUS - depends on XEN_GNTTAB + select LIBXENGNTTAB depends on HAVE_XENBUS depends on LIBUKNETDEV help diff --git a/drivers/xen/netfront/netfront.h b/drivers/xen/netfront/netfront.h index f3870fdb6..0cb3314d7 100644 --- a/drivers/xen/netfront/netfront.h +++ b/drivers/xen/netfront/netfront.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #if defined(__aarch64__) #include diff --git a/drivers/xen/xengnttab/Config.uk b/drivers/xen/xengnttab/Config.uk new file mode 100644 index 000000000..7ca677a2f --- /dev/null +++ b/drivers/xen/xengnttab/Config.uk @@ -0,0 +1,11 @@ +config LIBXENGNTTAB + bool "xengnttab: Xen Grant Table" + select LIBXENHEADERS + select LIBXENBUS + select LIBUKALLOC + select LIBUKLOCK + select LIBUKLOCK_SEMAPHORE + depends on (ARCH_X86_64 || ARCH_ARM_64) + depends on HAVE_XENBUS + help + Support grant table operations diff --git a/drivers/xen/xengnttab/Makefile.uk b/drivers/xen/xengnttab/Makefile.uk new file mode 100644 index 000000000..29283fbd4 --- /dev/null +++ b/drivers/xen/xengnttab/Makefile.uk @@ -0,0 +1,7 @@ +$(eval $(call addlib_s,libxengnttab,$(CONFIG_LIBXENGNTTAB))) + +CINCLUDES-$(CONFIG_LIBXENGNTTAB) += -I$(LIBXENGNTTAB_BASE)/include + +LIBXENGNTTAB_SRCS-y += $(LIBXENGNTTAB_BASE)/gnttab.c +LIBXENGNTTAB_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBXENGNTTAB_BASE)/arch/x86_64/gnttab.c|x86_64 +LIBXENGNTTAB_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBXENGNTTAB_BASE)/arch/arm64/gnttab.c|arm64 diff --git a/drivers/xen/xengnttab/arch/arm64/gnttab.c b/drivers/xen/xengnttab/arch/arm64/gnttab.c new file mode 100644 index 000000000..7453b3852 --- /dev/null +++ b/drivers/xen/xengnttab/arch/arm64/gnttab.c @@ -0,0 +1,96 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern lpae_t fixmap_pgtable[512]; + +/* Get Xen's suggested physical page assignments for the grant table. */ +static paddr_t get_gnttab_base(void) +{ + int hypervisor; + int len = 0; + const uint64_t *regs; + paddr_t gnttab_base; + + hypervisor = + fdt_node_offset_by_compatible(HYPERVISOR_dtb, -1, "xen,xen"); + if (hypervisor < 0) + BUG(); + + regs = fdt_getprop(HYPERVISOR_dtb, hypervisor, "reg", &len); + /* The property contains the address and size, 8-bytes each. */ + if (regs == NULL || len < 16) { + uk_pr_debug("Bad 'reg' property: %p %d\n", regs, len); + BUG(); + } + + gnttab_base = fdt64_ld(regs); + + uk_pr_debug("FDT suggests grant table base %llx\n", + (unsigned long long) gnttab_base); + + return gnttab_base; +} + +static paddr_t map_gnttab(paddr_t phys) +{ + uk_pr_debug("%s, phys = 0x%lx\n", __func__, phys); + + set_pgt_entry(&fixmap_pgtable[l2_pgt_idx(FIX_GNT_START)], + ((phys & L2_MASK) | BLOCK_DEF_ATTR | L2_BLOCK)); + + return (paddr_t)(FIX_GNT_START + (phys & L2_OFFSET)); +} + +grant_entry_v1_t *gnttab_arch_init(int nr_grant_frames) +{ + struct xen_add_to_physmap xatp; + paddr_t gnttab_table; + int i; + + gnttab_table = get_gnttab_base(); + + for (i = 0; i < nr_grant_frames; i++) { + xatp.domid = DOMID_SELF; + xatp.size = 0; // Seems to be unused + xatp.space = XENMAPSPACE_grant_table; + xatp.idx = i; + xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) + BUG(); + } + + return (grant_entry_v1_t *)map_gnttab(gnttab_table); +} diff --git a/drivers/xen/xengnttab/arch/x86_64/gnttab.c b/drivers/xen/xengnttab/arch/x86_64/gnttab.c new file mode 100644 index 000000000..7a647481b --- /dev/null +++ b/drivers/xen/xengnttab/arch/x86_64/gnttab.c @@ -0,0 +1,60 @@ +/* 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 +#include +#include +#include +#include +#include +#include + + +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_pr_err("Hypercall error: %d\n", rc); + goto out; + } + if (setup.status != GNTST_okay) { + uk_pr_err("Hypercall status: %d\n", setup.status); + goto out; + } + + gnte = map_frames(frames, grant_frames_num, ukplat_memallocator_get()); + +out: + return gnte; +} diff --git a/drivers/xen/xengnttab/exportsyms.uk b/drivers/xen/xengnttab/exportsyms.uk new file mode 100644 index 000000000..22338f565 --- /dev/null +++ b/drivers/xen/xengnttab/exportsyms.uk @@ -0,0 +1,10 @@ +gnttab_init +gnttab_fini +gnttab_alloc_and_grant +gnttab_grant_access +gnttab_grant_transfer +gnttab_update_grant +gnttab_end_transfer +gnttab_end_access +gnttabop_error +gnttab_arch_init diff --git a/drivers/xen/xengnttab/gnttab.c b/drivers/xen/xengnttab/gnttab.c new file mode 100644 index 000000000..bd379e8e9 --- /dev/null +++ b/drivers/xen/xengnttab/gnttab.c @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: MIT */ +/* + **************************************************************************** + * (C) 2006 - Cambridge University + **************************************************************************** + * + * File: gnttab.c + * Author: Steven Smith (sos22@cam.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * 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 +#include +#ifdef DBGGNT +#include +#endif +#include +#include +#include +#include +#include +#if defined(__i386__) || defined(__x86_64__) +#include + +#include +#elif defined(__aarch64__) +#include + +#include +#else +#error "Unsupported architecture" +#endif + +/* 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 >= GNTTAB_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); +} + +static void gnttab_grant_init(grant_ref_t gref, domid_t domid, + unsigned long mfn) +{ + gnttab.table[gref].frame = mfn; + gnttab.table[gref].domid = domid; + + /* Memory barrier */ + wmb(); +} + +static void gnttab_grant_permit_access(grant_ref_t gref, domid_t domid, + unsigned long mfn, int readonly) +{ + gnttab_grant_init(gref, domid, mfn); + readonly *= GTF_readonly; + gnttab.table[gref].flags = GTF_permit_access | readonly; +} + +grant_ref_t gnttab_grant_access(domid_t domid, unsigned long mfn, + int readonly) +{ + grant_ref_t gref = get_free_entry(); + + gnttab_grant_permit_access(gref, domid, mfn, readonly); + + return gref; +} + +grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long mfn) +{ + grant_ref_t gref = get_free_entry(); + + gnttab_grant_init(gref, domid, mfn); + gnttab.table[gref].flags = GTF_accept_transfer; + + return gref; +} + +/* Reset flags to zero in order to stop using the grant */ +static int gnttab_reset_flags(grant_ref_t gref) +{ + __u16 flags, nflags; + __u16 *pflags; + + pflags = &gnttab.table[gref].flags; + nflags = *pflags; + + do { + if ((flags = nflags) & (GTF_reading | GTF_writing)) { + uk_pr_warn("gref=%u still in use! (0x%x)\n", + gref, flags); + return 0; + } + } while ((nflags = uk_compare_exchange_sync(pflags, flags, 0)) + != flags); + + return 1; +} + +int gnttab_update_grant(grant_ref_t gref, + domid_t domid, unsigned long mfn, + int readonly) +{ + int rc; + + UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES && + gref < NR_GRANT_ENTRIES); + + rc = gnttab_reset_flags(gref); + if (!rc) + return rc; + + gnttab_grant_permit_access(gref, domid, mfn, readonly); + + return 1; +} + +int gnttab_end_access(grant_ref_t gref) +{ + int rc; + + UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES && + gref < NR_GRANT_ENTRIES); + + rc = gnttab_reset_flags(gref); + if (!rc) + return rc; + + 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 >= GNTTAB_NR_RESERVED_ENTRIES && + gref < NR_GRANT_ENTRIES); + + pflags = &gnttab.table[gref].flags; + while (!((flags = *pflags) & GTF_transfer_committed)) { + if (uk_compare_exchange_sync(pflags, flags, 0) == flags) { + uk_pr_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_palloc(a, 1); + 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 = GNTTAB_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_pr_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_pr_err("Hypercall error: %d\n", rc); + return; + } + + gnttab.initialized = 0; +} diff --git a/drivers/xen/xengnttab/include/uk/xen/gnttab.h b/drivers/xen/xengnttab/include/uk/xen/gnttab.h new file mode 100644 index 000000000..991d5b18c --- /dev/null +++ b/drivers/xen/xengnttab/include/uk/xen/gnttab.h @@ -0,0 +1,52 @@ +/* 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 __UK_XEN_GNTTAB_H__ +#define __UK_XEN_GNTTAB_H__ + +#include +#include +#include + +#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); +int gnttab_update_grant(grant_ref_t gref, + domid_t domid, unsigned long pfn, + int readonly); +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 /* !__UK_XEN_GNTTAB_H__ */ diff --git a/plat/xen/Config.uk b/plat/xen/Config.uk index 84aa30a6f..4f49d50d3 100644 --- a/plat/xen/Config.uk +++ b/plat/xen/Config.uk @@ -44,16 +44,4 @@ config XEN_PV_BUILD_P2M Create and initialize physical to machine (p2m) table on a PV xen host -config XEN_GNTTAB - bool "Grant table support" - default y if (XEN_PV || ARCH_ARM_64) - depends on (ARCH_X86_64 || ARCH_ARM_64) - select LIBXENBUS - select LIBUKALLOC - select LIBUKLOCK - select LIBUKLOCK_SEMAPHORE - select LIBUKSCHED - help - Support grant table operations - endif diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk index 72c857528..9ff67449b 100644 --- a/plat/xen/Makefile.uk +++ b/plat/xen/Makefile.uk @@ -122,9 +122,3 @@ endif LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/lcpu.c LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/shutdown.c LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/events.c - -ifeq ($(CONFIG_XEN_GNTTAB),y) -LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/gnttab.c -LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBXENPLAT_BASE)/x86/gnttab.c|x86 -LIBXENPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBXENPLAT_BASE)/arm/gnttab.c|arm64 -endif diff --git a/plat/xen/arm/gnttab.c b/plat/xen/arm/gnttab.c deleted file mode 100644 index 7453b3852..000000000 --- a/plat/xen/arm/gnttab.c +++ /dev/null @@ -1,96 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern lpae_t fixmap_pgtable[512]; - -/* Get Xen's suggested physical page assignments for the grant table. */ -static paddr_t get_gnttab_base(void) -{ - int hypervisor; - int len = 0; - const uint64_t *regs; - paddr_t gnttab_base; - - hypervisor = - fdt_node_offset_by_compatible(HYPERVISOR_dtb, -1, "xen,xen"); - if (hypervisor < 0) - BUG(); - - regs = fdt_getprop(HYPERVISOR_dtb, hypervisor, "reg", &len); - /* The property contains the address and size, 8-bytes each. */ - if (regs == NULL || len < 16) { - uk_pr_debug("Bad 'reg' property: %p %d\n", regs, len); - BUG(); - } - - gnttab_base = fdt64_ld(regs); - - uk_pr_debug("FDT suggests grant table base %llx\n", - (unsigned long long) gnttab_base); - - return gnttab_base; -} - -static paddr_t map_gnttab(paddr_t phys) -{ - uk_pr_debug("%s, phys = 0x%lx\n", __func__, phys); - - set_pgt_entry(&fixmap_pgtable[l2_pgt_idx(FIX_GNT_START)], - ((phys & L2_MASK) | BLOCK_DEF_ATTR | L2_BLOCK)); - - return (paddr_t)(FIX_GNT_START + (phys & L2_OFFSET)); -} - -grant_entry_v1_t *gnttab_arch_init(int nr_grant_frames) -{ - struct xen_add_to_physmap xatp; - paddr_t gnttab_table; - int i; - - gnttab_table = get_gnttab_base(); - - for (i = 0; i < nr_grant_frames; i++) { - xatp.domid = DOMID_SELF; - xatp.size = 0; // Seems to be unused - xatp.space = XENMAPSPACE_grant_table; - xatp.idx = i; - xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i; - if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) - BUG(); - } - - return (grant_entry_v1_t *)map_gnttab(gnttab_table); -} diff --git a/plat/xen/gnttab.c b/plat/xen/gnttab.c deleted file mode 100644 index 388b392c7..000000000 --- a/plat/xen/gnttab.c +++ /dev/null @@ -1,292 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - **************************************************************************** - * (C) 2006 - Cambridge University - **************************************************************************** - * - * File: gnttab.c - * Author: Steven Smith (sos22@cam.ac.uk) - * Changes: Grzegorz Milos (gm281@cam.ac.uk) - * - * 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 -#include -#ifdef DBGGNT -#include -#endif -#include -#include -#include -#include -#include -#if defined(__i386__) || defined(__x86_64__) -#include - -#include -#elif defined(__aarch64__) -#include - -#include -#else -#error "Unsupported architecture" -#endif - -/* 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 >= GNTTAB_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); -} - -static void gnttab_grant_init(grant_ref_t gref, domid_t domid, - unsigned long mfn) -{ - gnttab.table[gref].frame = mfn; - gnttab.table[gref].domid = domid; - - /* Memory barrier */ - wmb(); -} - -static void gnttab_grant_permit_access(grant_ref_t gref, domid_t domid, - unsigned long mfn, int readonly) -{ - gnttab_grant_init(gref, domid, mfn); - readonly *= GTF_readonly; - gnttab.table[gref].flags = GTF_permit_access | readonly; -} - -grant_ref_t gnttab_grant_access(domid_t domid, unsigned long mfn, - int readonly) -{ - grant_ref_t gref = get_free_entry(); - - gnttab_grant_permit_access(gref, domid, mfn, readonly); - - return gref; -} - -grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long mfn) -{ - grant_ref_t gref = get_free_entry(); - - gnttab_grant_init(gref, domid, mfn); - gnttab.table[gref].flags = GTF_accept_transfer; - - return gref; -} - -/* Reset flags to zero in order to stop using the grant */ -static int gnttab_reset_flags(grant_ref_t gref) -{ - __u16 flags, nflags; - __u16 *pflags; - - pflags = &gnttab.table[gref].flags; - nflags = *pflags; - - do { - if ((flags = nflags) & (GTF_reading | GTF_writing)) { - uk_pr_warn("gref=%u still in use! (0x%x)\n", - gref, flags); - return 0; - } - } while ((nflags = uk_compare_exchange_sync(pflags, flags, 0)) - != flags); - - return 1; -} - -int gnttab_update_grant(grant_ref_t gref, - domid_t domid, unsigned long mfn, - int readonly) -{ - int rc; - - UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES && - gref < NR_GRANT_ENTRIES); - - rc = gnttab_reset_flags(gref); - if (!rc) - return rc; - - gnttab_grant_permit_access(gref, domid, mfn, readonly); - - return 1; -} - -int gnttab_end_access(grant_ref_t gref) -{ - int rc; - - UK_ASSERT(gref >= GNTTAB_NR_RESERVED_ENTRIES && - gref < NR_GRANT_ENTRIES); - - rc = gnttab_reset_flags(gref); - if (!rc) - return rc; - - 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 >= GNTTAB_NR_RESERVED_ENTRIES && - gref < NR_GRANT_ENTRIES); - - pflags = &gnttab.table[gref].flags; - while (!((flags = *pflags) & GTF_transfer_committed)) { - if (uk_compare_exchange_sync(pflags, flags, 0) == flags) { - uk_pr_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_palloc(a, 1); - 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 = GNTTAB_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_pr_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_pr_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 deleted file mode 100644 index 5a830ed61..000000000 --- a/plat/xen/include/common/gnttab.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 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 - -#ifdef CONFIG_XEN_GNTTAB - -#include -#include - -#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); -int gnttab_update_grant(grant_ref_t gref, - domid_t domid, unsigned long pfn, - int readonly); -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 /* CONFIG_XEN_GNTTAB */ - -#endif /* !__GNTTAB_H__ */ diff --git a/plat/xen/memory.c b/plat/xen/memory.c index fa1af9e04..fdf5baa89 100644 --- a/plat/xen/memory.c +++ b/plat/xen/memory.c @@ -31,9 +31,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include -#include +#if CONFIG_LIBXENGNTTAB +#include +#endif /* CONFIG_LIBXENGNTTAB */ #if (defined __X86_32__) || (defined __X86_64__) #include #include @@ -50,7 +53,8 @@ void mm_init(void) int _ukplat_mem_mappings_init(void) { mm_init(); -#ifdef CONFIG_XEN_GNTTAB +#ifdef CONFIG_LIBXENGNTTAB + /* TODO: Move `gnttab_init()` to (early) ctortab */ gnttab_init(); #endif return 0; diff --git a/plat/xen/x86/gnttab.c b/plat/xen/x86/gnttab.c deleted file mode 100644 index 7a647481b..000000000 --- a/plat/xen/x86/gnttab.c +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include -#include - - -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_pr_err("Hypercall error: %d\n", rc); - goto out; - } - if (setup.status != GNTST_okay) { - uk_pr_err("Hypercall status: %d\n", setup.status); - goto out; - } - - gnte = map_frames(frames, grant_frames_num, ukplat_memallocator_get()); - -out: - return gnte; -}