From c850674ff74b1625c17a77a454acec0e9cc6ec36 Mon Sep 17 00:00:00 2001 From: Oleksandr Andrushchenko Date: Thu, 6 Aug 2020 12:42:54 +0300 Subject: [PATCH] xen: Port Xen grant table driver from mini-os Make required updates to run on u-boot. Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Anastasiia Lukianenko --- board/xen/xenguest_arm64/xenguest_arm64.c | 13 ++ drivers/xen/Makefile | 1 + drivers/xen/gnttab.c | 216 ++++++++++++++++++++++ drivers/xen/hypervisor.c | 2 + include/xen.h | 3 +- include/xen/gnttab.h | 24 +++ 6 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 drivers/xen/gnttab.c create mode 100644 include/xen/gnttab.h diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c index c87ef70769..cd3693892a 100644 --- a/board/xen/xenguest_arm64/xenguest_arm64.c +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -21,6 +21,7 @@ #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -63,6 +64,8 @@ static int setup_mem_map(void) struct fdt_resource res; const void *blob = gd->fdt_blob; u64 gfn; + phys_addr_t gnttab_base; + phys_size_t gnttab_sz; /* * Add "magic" region which is used by Xen to provide some essentials @@ -96,6 +99,16 @@ static int setup_mem_map(void) PTE_BLOCK_INNER_SHARE); i++; + /* Get Xen's suggested physical page assignments for the grant table. */ + get_gnttab_base(&gnttab_base, &gnttab_sz); + + xen_mem_map[i].virt = gnttab_base; + xen_mem_map[i].phys = gnttab_base; + xen_mem_map[i].size = gnttab_sz; + xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE); + i++; + mem = get_next_memory_node(blob, -1); if (mem < 0) { printf("%s: Missing /memory node\n", __func__); diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 9d0f604aaa..243b13277a 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -5,3 +5,4 @@ obj-y += hypervisor.o obj-y += events.o obj-y += xenbus.o +obj-y += gnttab.o diff --git a/drivers/xen/gnttab.c b/drivers/xen/gnttab.c new file mode 100644 index 0000000000..becf7a79fb --- /dev/null +++ b/drivers/xen/gnttab.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) 2006 - Cambridge University + * (C) 2020 - EPAM Systems Inc. + * + * File: gnttab.c [1] + * Author: Steven Smith (sos22@cam.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * Date: July 2006 + * + * Description: Simple grant tables implementation. About as stupid as it's + * possible to be and still work. + * + * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define NR_RESERVED_ENTRIES 8 + +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ +#define NR_GRANT_FRAMES 1 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(struct grant_entry_v1)) + +static struct grant_entry_v1 *gnttab_table; +static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; + +static void put_free_entry(grant_ref_t ref) +{ + unsigned long flags; + + local_irq_save(flags); + gnttab_list[ref] = gnttab_list[0]; + gnttab_list[0] = ref; + local_irq_restore(flags); +} + +static grant_ref_t get_free_entry(void) +{ + unsigned int ref; + unsigned long flags; + + local_irq_save(flags); + ref = gnttab_list[0]; + BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES); + gnttab_list[0] = gnttab_list[ref]; + local_irq_restore(flags); + return ref; +} + +/** + * gnttab_grant_access() - Allow access to the given frame. + * The function creates an entry in the grant table according + * to the specified parameters. + * @domid: the id of the domain for which access is allowed + * @frame: the number of the shared frame + * @readonly: determines whether the frame is shared read-only or read-write + * + * Return: relevant grant reference + */ +grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame, int readonly) +{ + grant_ref_t ref; + + ref = get_free_entry(); + gnttab_table[ref].frame = frame; + gnttab_table[ref].domid = domid; + wmb(); + readonly *= GTF_readonly; + gnttab_table[ref].flags = GTF_permit_access | readonly; + + return ref; +} + +/** + * gnttab_end_access() - End of memory sharing. The function invalidates + * the entry in the grant table. + */ +int gnttab_end_access(grant_ref_t ref) +{ + u16 flags, nflags; + + BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES); + + nflags = gnttab_table[ref].flags; + do { + if ((flags = nflags) & (GTF_reading | GTF_writing)) { + printf("WARNING: g.e. still in use! (%x)\n", flags); + return 0; + } + } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) != + flags); + + put_free_entry(ref); + return 1; +} + +grant_ref_t gnttab_alloc_and_grant(void **map) +{ + unsigned long mfn; + grant_ref_t gref; + + *map = (void *)memalign(PAGE_SIZE, PAGE_SIZE); + mfn = virt_to_mfn(*map); + gref = gnttab_grant_access(0, mfn, 0); + return gref; +} + +static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs; + +const char *gnttabop_error(int16_t status) +{ + status = -status; + if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs)) + return "bad status"; + else + return gnttabop_error_msgs[status]; +} + +/* Get Xen's suggested physical page assignments for the grant table. */ +void get_gnttab_base(phys_addr_t *gnttab_base, phys_size_t *gnttab_sz) +{ + const void *blob = gd->fdt_blob; + struct fdt_resource res; + int mem; + + mem = fdt_node_offset_by_compatible(blob, -1, "xen,xen"); + if (mem < 0) { + printf("No xen,xen compatible found\n"); + BUG(); + } + + mem = fdt_get_resource(blob, mem, "reg", 0, &res); + if (mem == -FDT_ERR_NOTFOUND) { + printf("No grant table base in the device tree\n"); + BUG(); + } + + *gnttab_base = (phys_addr_t)res.start; + if (gnttab_sz) + *gnttab_sz = (phys_size_t)(res.end - res.start + 1); + + debug("FDT suggests grant table base at %llx\n", + *gnttab_base); +} + +void init_gnttab(void) +{ + struct xen_add_to_physmap xatp; + struct gnttab_setup_table setup; + xen_pfn_t frames[NR_GRANT_FRAMES]; + int i, rc; + + debug("%s\n", __func__); + + for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) + put_free_entry(i); + + get_gnttab_base((phys_addr_t *)&gnttab_table, NULL); + + for (i = 0; i < NR_GRANT_FRAMES; i++) { + xatp.domid = DOMID_SELF; + xatp.size = 0; + xatp.space = XENMAPSPACE_grant_table; + xatp.idx = i; + xatp.gpfn = PFN_DOWN((unsigned long)gnttab_table) + i; + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + if (rc) + printf("XENMEM_add_to_physmap failed; status = %d\n", + rc); + BUG_ON(rc != 0); + } + + setup.dom = DOMID_SELF; + setup.nr_frames = NR_GRANT_FRAMES; + set_xen_guest_handle(setup.frame_list, frames); +} + +void fini_gnttab(void) +{ + struct xen_remove_from_physmap xrtp; + struct gnttab_setup_table setup; + int i, rc; + + debug("%s\n", __func__); + + for (i = 0; i < NR_GRANT_FRAMES; i++) { + xrtp.domid = DOMID_SELF; + xrtp.gpfn = PFN_DOWN((unsigned long)gnttab_table) + i; + rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrtp); + if (rc) + printf("XENMEM_remove_from_physmap failed; status = %d\n", + rc); + BUG_ON(rc != 0); + } + + setup.dom = DOMID_SELF; + setup.nr_frames = 0; +} + diff --git a/drivers/xen/hypervisor.c b/drivers/xen/hypervisor.c index 1c7ae94bdf..58b0865e6a 100644 --- a/drivers/xen/hypervisor.c +++ b/drivers/xen/hypervisor.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -238,5 +239,6 @@ void xen_init(void) map_shared_info(NULL); init_events(); init_xenbus(); + init_gnttab(); } diff --git a/include/xen.h b/include/xen.h index 6fe30b83a2..686b7148b5 100644 --- a/include/xen.h +++ b/include/xen.h @@ -8,7 +8,8 @@ /** * xen_init() - Xen initialization * - * Map Xen memory pages, initialize event handler and xenbus. + * Map Xen memory pages, initialize event handler and xenbus, + * setup the grant table. */ void xen_init(void); diff --git a/include/xen/gnttab.h b/include/xen/gnttab.h new file mode 100644 index 0000000000..db1d5361fe --- /dev/null +++ b/include/xen/gnttab.h @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * + * (C) 2006, Steven Smith + * (C) 2006, Grzegorz Milos + * (C) 2020, EPAM Systems Inc. + */ +#ifndef __GNTTAB_H__ +#define __GNTTAB_H__ + +#include + +void init_gnttab(void); +void fini_gnttab(void); + +grant_ref_t gnttab_alloc_and_grant(void **map); +grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame, + int readonly); +int gnttab_end_access(grant_ref_t ref); +const char *gnttabop_error(int16_t status); + +void get_gnttab_base(phys_addr_t *gnttab_base, phys_size_t *gnttab_sz); + +#endif /* !__GNTTAB_H__ */ -- 2.39.5