From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julien Grall Date: Wed, 1 Jul 2020 17:59:31 +0100 Subject: [PATCH 11/17] xen: Port Xen grant table driver from mini-os In-Reply-To: <20200701162959.9814-12-vicooodin@gmail.com> References: <20200701162959.9814-1-vicooodin@gmail.com> <20200701162959.9814-12-vicooodin@gmail.com> Message-ID: <2ff283c9-2bf0-85b5-57e0-822787cf9947@xen.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 01/07/2020 17:29, Anastasiia Lukianenko wrote: > From: Oleksandr Andrushchenko > > 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 | 258 ++++++++++++++++++++++ > drivers/xen/hypervisor.c | 2 + > include/xen/gnttab.h | 25 +++ > 5 files changed, 299 insertions(+) > 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 e8621f7174..b4e1650f99 100644 > --- a/board/xen/xenguest_arm64/xenguest_arm64.c > +++ b/board/xen/xenguest_arm64/xenguest_arm64.c > @@ -22,6 +22,7 @@ > > #include > > +#include > #include > > DECLARE_GLOBAL_DATA_PTR; > @@ -64,6 +65,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 > @@ -97,6 +100,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..b18102e329 > --- /dev/null > +++ b/drivers/xen/gnttab.c > @@ -0,0 +1,258 @@ > +/* > + **************************************************************************** > + * (C) 2006 - Cambridge University > + * (C) 2020 - EPAM Systems Inc. > + **************************************************************************** > + * > + * File: gnttab.c > + * Author: Steven Smith (sos22 at cam.ac.uk) > + * Changes: Grzegorz Milos (gm281 at 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 > +#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; > +} > + > +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; > +} > + > +grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn) It is not possible to transfer grant on Arm. So I would suggest to remove the code related to it. [...] > +unsigned long gnttab_end_transfer(grant_ref_t ref) likewise. > +{ > + unsigned long frame; > + u16 flags; > + > + BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES); > + > + while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) { > + if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) { > + printf("Release unused transfer grant.\n"); > + put_free_entry(ref); > + return 0; > + } > + } > + > + /* If a transfer is in progress then wait until it is completed. */ > + while (!(flags & GTF_transfer_completed)) > + flags = gnttab_table[ref].flags; > + > + /* Read the frame number /after/ reading completion status. */ > + rmb(); > + frame = gnttab_table[ref].frame; > + > + put_free_entry(ref); > + > + return frame; > +} > + > +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); > + rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); > + if (rc || setup.status) { > + printf("GNTTABOP_setup_table failed; status = %s\n", > + gnttabop_error(setup.status)); > + BUG(); > + } GNTTAOP_grant_table_op is not needed on Arm. > +} > + > +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; > + > + HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); > + if (setup.status) { > + printf("GNTTABOP_setup_table failed; status = %s\n", > + gnttabop_error(setup.status)); > + BUG(); > + } The hypercall doesn't do any clean-up in Xen. So why are you calling this from fini_gnttab()? Cheers, -- Julien Grall