[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 5/9] xen/arm: Add XEN_DOMCTL_dt_overlay and device attachment to domains
On Thu, 23 May 2024, Julien Grall wrote: > Hi Henry, > > On 23/05/2024 08:40, Henry Wang wrote: > > In order to support the dynamic dtbo device assignment to a running > > VM, the add/remove of the DT overlay and the attach/detach of the > > device from the DT overlay should happen separately. Therefore, > > repurpose the existing XEN_SYSCTL_dt_overlay to only add the DT > > overlay to Xen device tree > > I think it would be worth mentioning in the commit message why changing the > sysctl behavior is fine. The feature is experimental and therefore breaking > compatibility is ok. Added > > , instead of assigning the device to the > > hardware domain at the same time. Add the XEN_DOMCTL_dt_overlay with > > operations XEN_DOMCTL_DT_OVERLAY_ATTACH to do the device assignment > > to the domain. > > > > The hypervisor firstly checks the DT overlay passed from the toolstack > > is valid. Then the device nodes are retrieved from the overlay tracker > > based on the DT overlay. The attach of the device is implemented by > > mapping the IRQ and IOMMU resources. > > So, the expectation is the user will always want to attach all the devices in > the overlay to a single domain. Is that correct? Yes, also added to the commit message > > > > Signed-off-by: Henry Wang <xin.wang2@xxxxxxx> > > Signed-off-by: Vikram Garhwal <fnu.vikram@xxxxxxxxxx> > > --- > > v4: > > - Split the original patch, only do the device attachment. > > v3: > > - Style fixes for arch-selection #ifdefs. > > - Do not include public/domctl.h, only add a forward declaration of > > struct xen_domctl_dt_overlay. > > - Extract the overlay track entry finding logic to a function, drop > > the unused variables. > > - Use op code 1&2 for XEN_DOMCTL_DT_OVERLAY_{ATTACH,DETACH}. > > v2: > > - New patch. > > --- > > xen/arch/arm/domctl.c | 3 + > > xen/common/dt-overlay.c | 199 ++++++++++++++++++++++++++--------- > > xen/include/public/domctl.h | 14 +++ > > xen/include/public/sysctl.h | 11 +- > > xen/include/xen/dt-overlay.h | 7 ++ > > 5 files changed, 176 insertions(+), 58 deletions(-) > > > > diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c > > index ad56efb0f5..12a12ee781 100644 > > --- a/xen/arch/arm/domctl.c > > +++ b/xen/arch/arm/domctl.c > > @@ -5,6 +5,7 @@ > > * Copyright (c) 2012, Citrix Systems > > */ > > +#include <xen/dt-overlay.h> > > #include <xen/errno.h> > > #include <xen/guest_access.h> > > #include <xen/hypercall.h> > > @@ -176,6 +177,8 @@ long arch_do_domctl(struct xen_domctl *domctl, struct > > domain *d, > > return rc; > > } > > + case XEN_DOMCTL_dt_overlay: > > + return dt_overlay_domctl(d, &domctl->u.dt_overlay); > > default: > > return subarch_do_domctl(domctl, d, u_domctl); > > } > > diff --git a/xen/common/dt-overlay.c b/xen/common/dt-overlay.c > > index 9cece79067..1087f9b502 100644 > > --- a/xen/common/dt-overlay.c > > +++ b/xen/common/dt-overlay.c > > @@ -356,6 +356,42 @@ static int overlay_get_nodes_info(const void *fdto, > > char **nodes_full_path) > > return 0; > > } > > +/* This function should be called with the overlay_lock taken */ > > +static struct overlay_track * > > +find_track_entry_from_tracker(const void *overlay_fdt, > > + uint32_t overlay_fdt_size) > > +{ > > + struct overlay_track *entry, *temp; > > + bool found_entry = false; > > + > > + ASSERT(spin_is_locked(&overlay_lock)); > > + > > + /* > > + * First check if dtbo is correct i.e. it should one of the dtbo which > > was > > + * used when dynamically adding the node. > > + * Limitation: Cases with same node names but different property are > > not > > + * supported currently. We are relying on user to provide the same dtbo > > + * as it was used when adding the nodes. > > + */ > > + list_for_each_entry_safe( entry, temp, &overlay_tracker, entry ) > > + { > > + if ( memcmp(entry->overlay_fdt, overlay_fdt, overlay_fdt_size) == 0 > > ) > > + { > > + found_entry = true; > > + break; > > + } > > + } > > + > > + if ( !found_entry ) > > + { > > + printk(XENLOG_ERR "Cannot find any matching tracker with input > > dtbo." > > + " Operation is supported only for prior added dtbo.\n"); > > + return NULL; > > + } > > + > > + return entry; > > +} > > + > > /* Check if node itself can be removed and remove node from IOMMU. */ > > static int remove_node_resources(struct dt_device_node *device_node) > > { > > @@ -485,8 +521,7 @@ static long handle_remove_overlay_nodes(const void > > *overlay_fdt, > > uint32_t overlay_fdt_size) > > { > > int rc; > > - struct overlay_track *entry, *temp, *track; > > - bool found_entry = false; > > + struct overlay_track *entry; > > rc = check_overlay_fdt(overlay_fdt, overlay_fdt_size); > > if ( rc ) > > @@ -494,29 +529,10 @@ static long handle_remove_overlay_nodes(const void > > *overlay_fdt, > > spin_lock(&overlay_lock); > > - /* > > - * First check if dtbo is correct i.e. it should one of the dtbo which > > was > > - * used when dynamically adding the node. > > - * Limitation: Cases with same node names but different property are > > not > > - * supported currently. We are relying on user to provide the same dtbo > > - * as it was used when adding the nodes. > > - */ > > - list_for_each_entry_safe( entry, temp, &overlay_tracker, entry ) > > - { > > - if ( memcmp(entry->overlay_fdt, overlay_fdt, overlay_fdt_size) == 0 > > ) > > - { > > - track = entry; > > - found_entry = true; > > - break; > > - } > > - } > > - > > - if ( !found_entry ) > > + entry = find_track_entry_from_tracker(overlay_fdt, overlay_fdt_size); > > + if ( entry == NULL ) > > { > > rc = -EINVAL; > > - > > - printk(XENLOG_ERR "Cannot find any matching tracker with input > > dtbo." > > - " Removing nodes is supported only for prior added > > dtbo.\n"); > > goto out; > > } > > @@ -620,15 +636,7 @@ static long add_nodes(struct overlay_track *tr, char > > **nodes_full_path) > > return -EFAULT; > > } > > - rc = handle_device(hardware_domain, overlay_node, > > p2m_mmio_direct_c, > > - tr->iomem_ranges, > > - tr->irq_ranges); > > write_unlock(&dt_host_lock); > > - if ( rc ) > > - { > > - printk(XENLOG_ERR "Adding IRQ and IOMMU failed\n"); > > - return rc; > > - } > > /* Keep overlay_node address in tracker. */ > > tr->nodes_address[j] = (unsigned long)overlay_node; > > @@ -638,9 +646,7 @@ static long add_nodes(struct overlay_track *tr, char > > **nodes_full_path) > > } > > /* > > * Adds device tree nodes under target node. > > - * We use tr->dt_host_new to unflatten the updated device_tree_flattened. > > This > > - * is done to avoid the removal of device_tree generation, iomem regions > > mapping > > - * to hardware domain done by handle_node(). > > + * We use tr->dt_host_new to unflatten the updated device_tree_flattened. > > */ > > static long handle_add_overlay_nodes(void *overlay_fdt, > > uint32_t overlay_fdt_size) > > @@ -774,20 +780,6 @@ static long handle_add_overlay_nodes(void *overlay_fdt, > > goto err; > > } > > - tr->irq_ranges = rangeset_new(hardware_domain, "Overlays: > > Interrupts", 0); > > - if (tr->irq_ranges == NULL) > > - { > > - printk(XENLOG_ERR "Creating IRQ rangeset failed"); > > - goto err; > > - } > > - > > - tr->iomem_ranges = rangeset_new(hardware_domain, "Overlay: I/O Memory", > > 0); > > - if (tr->iomem_ranges == NULL) > > - { > > - printk(XENLOG_ERR "Creating IOMMU rangeset failed"); > > - goto err; > > - } > > - > > rc = add_nodes(tr, nodes_full_path); > > if ( rc ) > > { > > @@ -843,14 +835,83 @@ static long handle_add_overlay_nodes(void > > *overlay_fdt, > > xfree(tr->nodes_address); > > xfree(tr->fdt); > > - rangeset_destroy(tr->irq_ranges); > > - rangeset_destroy(tr->iomem_ranges); > > - > > xfree(tr); > > return rc; > > } > > +static long handle_attach_overlay_nodes(struct domain *d, > > + const void *overlay_fdt, > > + uint32_t overlay_fdt_size) > > +{ > > + int rc; > > + unsigned int j; > > + struct overlay_track *entry; > > + > > + rc = check_overlay_fdt(overlay_fdt, overlay_fdt_size); > > + if ( rc ) > > + return rc; > > + > > + spin_lock(&overlay_lock); > > + > > + entry = find_track_entry_from_tracker(overlay_fdt, overlay_fdt_size); > > + if ( entry == NULL ) > > + { > > + rc = -EINVAL; > > + goto out; > > + } > > + > > + entry->irq_ranges = rangeset_new(d, "Overlays: Interrupts", 0); > > + if (entry->irq_ranges == NULL) > > + { > > + rc = -ENOMEM; > > + printk(XENLOG_ERR "Creating IRQ rangeset failed"); > > + goto out; > > + } > > + > > + entry->iomem_ranges = rangeset_new(d, "Overlay: I/O Memory", 0); > > + if (entry->iomem_ranges == NULL) > > + { > > + rc = -ENOMEM; > > + printk(XENLOG_ERR "Creating IOMMU rangeset failed"); > > + goto out; > > + } > > + > > + for ( j = 0; j < entry->num_nodes; j++ ) > > + { > > + struct dt_device_node *overlay_node; > > + > > + overlay_node = (struct dt_device_node *)entry->nodes_address[j]; > > + if ( overlay_node == NULL ) > > + { > > + rc = -EINVAL; > > + goto out; > > + } > > + > > + write_lock(&dt_host_lock); > > + rc = handle_device(d, overlay_node, p2m_mmio_direct_c, > > + entry->iomem_ranges, entry->irq_ranges); > > + write_unlock(&dt_host_lock); > > + if ( rc ) > > + { > > + printk(XENLOG_ERR "Adding IRQ and IOMMU failed\n"); > > + goto out; > > + } > > + } > > + > > + spin_unlock(&overlay_lock); > > + > > + return 0; > > + > > + out: > > + spin_unlock(&overlay_lock); > > + > > + rangeset_destroy(entry->irq_ranges); > > + rangeset_destroy(entry->iomem_ranges); > > + > > + return rc; > > +} > > + > > long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op) > > { > > long ret; > > @@ -890,6 +951,42 @@ long dt_overlay_sysctl(struct xen_sysctl_dt_overlay > > *op) > > return ret; > > } > > +long dt_overlay_domctl(struct domain *d, struct xen_domctl_dt_overlay > > *op) > > +{ > > + long ret; > > + void *overlay_fdt; > > + > > + if ( op->overlay_op != XEN_DOMCTL_DT_OVERLAY_ATTACH ) > > + return -EOPNOTSUPP; > > + > > + if ( op->overlay_fdt_size == 0 || op->overlay_fdt_size > KB(500) ) > > Let's avoid to hardocode KB(500) a second time (it alredy exists in the sysctl > path). > > But I would actually consider to allow up to 512KB because... I left it as is because I wasn't sure what you wanted as a change. Did you mean that you would like the check to be removed, or did you mean that you would like an #define instead of writing KB(500)? It is fine either way for me, or to keep it as is, please make the desired change on commit. > > + return -EINVAL; > > + > > + if ( op->pad[0] || op->pad[1] || op->pad[2] ) > > + return -EINVAL; > > + > > + overlay_fdt = xmalloc_bytes(op->overlay_fdt_size); > > ... xmalloc_bytes() will be more efficient. If the size is not power of 2 > pages, it will free the leftover. Anyway, this could be a follow-up patch. Leaving this as is for now > > + > > + if ( overlay_fdt == NULL ) > > + return -ENOMEM; > > + > > + ret = copy_from_guest(overlay_fdt, op->overlay_fdt, > > op->overlay_fdt_size); > > + if ( ret ) > > + { > > + gprintk(XENLOG_ERR, "copy from guest failed\n"); > > + xfree(overlay_fdt); > > + > > + return -EFAULT; > > + } > > + > > + if ( op->overlay_op == XEN_DOMCTL_DT_OVERLAY_ATTACH ) > > + ret = handle_attach_overlay_nodes(d, overlay_fdt, > > op->overlay_fdt_size); > > I think you would return 0 if the operation is not supported. But I think we > need to return -EOPNOTSUPP. I made the change > > + > > + xfree(overlay_fdt); > > + > > + return ret; > > +} > > + > > /* > > * Local variables: > > * mode: C > > diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h > > index a33f9ec32b..ac3c2a7c4c 100644 > > --- a/xen/include/public/domctl.h > > +++ b/xen/include/public/domctl.h > > If I am not mistkane, this is the first change in the domctl header for 4.19. > So you want to bump XEN_DOMCTL_INTERFACE_VERSION. Done > > @@ -1190,6 +1190,16 @@ struct xen_domctl_vmtrace_op { > > typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t; > > DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t); > > +#if defined(__arm__) || defined(__aarch64__) > > +struct xen_domctl_dt_overlay { > > + XEN_GUEST_HANDLE_64(const_void) overlay_fdt; /* IN: overlay fdt. */ > > + uint32_t overlay_fdt_size; /* IN: Overlay dtb size. */ > > +#define XEN_DOMCTL_DT_OVERLAY_ATTACH 1 > > OOI, why not starting from 0? I think it was to avoid the risk of confusing zero as uninitialized with a real operation. > > + uint8_t overlay_op; /* IN: Attach. */ > > + uint8_t pad[3]; /* IN: Must be zero. */ > > +}; > > +#endif > > + > > struct xen_domctl { > > uint32_t cmd; > > #define XEN_DOMCTL_createdomain 1 > > @@ -1277,6 +1287,7 @@ struct xen_domctl { > > #define XEN_DOMCTL_vmtrace_op 84 > > #define XEN_DOMCTL_get_paging_mempool_size 85 > > #define XEN_DOMCTL_set_paging_mempool_size 86 > > +#define XEN_DOMCTL_dt_overlay 87 > > #define XEN_DOMCTL_gdbsx_guestmemio 1000 > > #define XEN_DOMCTL_gdbsx_pausevcpu 1001 > > #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 > > @@ -1339,6 +1350,9 @@ struct xen_domctl { > > struct xen_domctl_vuart_op vuart_op; > > struct xen_domctl_vmtrace_op vmtrace_op; > > struct xen_domctl_paging_mempool paging_mempool; > > +#if defined(__arm__) || defined(__aarch64__) > > + struct xen_domctl_dt_overlay dt_overlay; > > +#endif > > uint8_t pad[128]; > > } u; > > }; > > diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h > > index febaa4b16a..3a6e7d48f0 100644 > > --- a/xen/include/public/sysctl.h > > +++ b/xen/include/public/sysctl.h > > @@ -1184,14 +1184,11 @@ typedef struct xen_sysctl_cpu_policy > > xen_sysctl_cpu_policy_t; > > DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_policy_t); > > #endif > > -#if defined(__arm__) || defined (__aarch64__) > > +#if defined(__arm__) || defined(__aarch64__) > > This seems like unrelated change. Maybe mention in the commit message that you > are fixing the coding style? Done > > /* > > * XEN_SYSCTL_dt_overlay > > - * Performs addition/removal of device tree nodes under parent node using > > dtbo. > > - * This does in three steps: > > - * - Adds/Removes the nodes from dt_host. > > - * - Adds/Removes IRQ permission for the nodes. > > - * - Adds/Removes MMIO accesses. > > + * Performs addition/removal of device tree nodes under parent node using > > dtbo > > + * from dt_host. > > */ > > struct xen_sysctl_dt_overlay { > > XEN_GUEST_HANDLE_64(const_void) overlay_fdt; /* IN: overlay fdt. */ > > @@ -1265,7 +1262,7 @@ struct xen_sysctl { > > struct xen_sysctl_cpu_policy cpu_policy; > > #endif > > -#if defined(__arm__) || defined (__aarch64__) > > +#if defined(__arm__) || defined(__aarch64__) > > struct xen_sysctl_dt_overlay dt_overlay; > > #endif > > uint8_t pad[128]; > > diff --git a/xen/include/xen/dt-overlay.h b/xen/include/xen/dt-overlay.h > > index c0567741ee..7f0f3741b5 100644 > > --- a/xen/include/xen/dt-overlay.h > > +++ b/xen/include/xen/dt-overlay.h > > @@ -39,15 +39,22 @@ struct overlay_track { > > }; > > struct xen_sysctl_dt_overlay; > > +struct xen_domctl_dt_overlay; > > #ifdef CONFIG_OVERLAY_DTB > > long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op); > > +long dt_overlay_domctl(struct domain *d, struct xen_domctl_dt_overlay *op); > > #else > > #include <xen/errno.h> > > static inline long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op) > > { > > return -EOPNOTSUPP; > > } > > NIT: Newline here please. Done > > > +static inline long dt_overlay_domctl(struct domain *d, > > + struct xen_domctl_dt_overlay *op) > > +{ > > + return -EOPNOTSUPP; > > +} > > #endif > > #endif /* __XEN_DT_OVERLAY_H__ */ > > Cheers, > > -- > Julien Grall >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |