|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC 03/19] xen/arm: follow-up to allow DOM0 manage IRQ and MMIO
On Mon, 16 Jun 2014, Julien Grall wrote:
> The commit 33233c2 "arch/arm: domain build: let dom0 access I/O memory of
> mapped series" fill the iomem_caps to allow DOM0 managing MMIO of mapped
> device.
>
> A device can be disabled (i.e by adding a property status="disabled" in the
> device tree) because the user may want to passthrough this device to a guest.
> This will avoid DOM0 loading (and few minutes after unloading) the driver to
> handle this device.
>
> Even though, we don't want to let DOM0 using this device, the domain needs
> to be able to manage the MMIO/IRQ range. Rework the function map_device
> (renamed into handle_device) to:
Is that so the toolstack in dom0 could re-assign the device to another
guest?
In any case it would be good to write down exactly why DOM0 would still
need to be able to manage the MMIO/IRQ range as a comment in the code.
> * For a given device node:
> - Give permission to manage IRQ/MMIO for this device
> - Retrieve the IRQ configuration (i.e edge/level) from the device
> tree
> * For available device (i.e status != disabled in the DT)
> - Assign the device to the guest if it's protected by an IOMMU
> - Map the IRQs and MMIOs regions to the guest
>
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> ---
> xen/arch/arm/domain_build.c | 66
> ++++++++++++++++++++++++++++---------------
> 1 file changed, 44 insertions(+), 22 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index c3783cf..6a711cc 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -680,8 +680,14 @@ static int make_timer_node(const struct domain *d, void
> *fdt,
> return res;
> }
>
> -/* Map the device in the domain */
> -static int map_device(struct domain *d, struct dt_device_node *dev)
> +/* For a given device node:
> + * - Give permission to the guest to manage IRQ and MMIO range
> + * - Retrieve the IRQ configuration (i.e edge/level) from device tree
> + * When the device is available:
> + * - Assign the device to the guest if it's protected by an IOMMU
> + * - Map the IRQs and iomem regions to DOM0
> + */
> +static int handle_device(struct domain *d, struct dt_device_node *dev,
> bool_t map)
This is confusing.
If map == true then we get a similar behavior as before. If map ==
false, what is the function supposed to achieve? Only permit IRQ access?
Could we split it into a separate function?
> {
> unsigned int nirq;
> unsigned int naddr;
> @@ -694,9 +700,10 @@ static int map_device(struct domain *d, struct
> dt_device_node *dev)
> nirq = dt_number_of_irq(dev);
> naddr = dt_number_of_address(dev);
>
> - DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr);
> + DPRINT("%s map = %d nirq = %d naddr = %u\n", dt_node_full_name(dev),
> + map, nirq, naddr);
>
> - if ( dt_device_is_protected(dev) )
> + if ( dt_device_is_protected(dev) && map )
> {
> DPRINT("%s setup iommu\n", dt_node_full_name(dev));
> res = iommu_assign_dt_device(d, dev);
> @@ -708,7 +715,7 @@ static int map_device(struct domain *d, struct
> dt_device_node *dev)
> }
> }
>
> - /* Map IRQs */
> + /* Give permission and map IRQs */
> for ( i = 0; i < nirq; i++ )
> {
> res = dt_device_get_raw_irq(dev, i, &rirq);
> @@ -741,16 +748,28 @@ static int map_device(struct domain *d, struct
> dt_device_node *dev)
> irq = res;
>
> DPRINT("irq %u = %u\n", i, irq);
> - res = route_irq_to_guest(d, irq, dt_node_name(dev));
> +
> + res = irq_permit_access(d, irq);
> if ( res )
> {
> - printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
> - irq, d->domain_id);
> + printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> + d->domain_id, irq);
> return res;
> }
> +
> + if ( map )
> + {
> + res = route_irq_to_guest(d, irq, dt_node_name(dev));
> + if ( res )
> + {
> + printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
> + irq, d->domain_id);
> + return res;
> + }
> + }
> }
>
> - /* Map the address ranges */
> + /* Give permission and map MMIOs */
> for ( i = 0; i < naddr; i++ )
> {
> res = dt_device_get_address(dev, i, &addr, &size);
> @@ -774,17 +793,21 @@ static int map_device(struct domain *d, struct
> dt_device_node *dev)
> addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
> return res;
> }
> - res = map_mmio_regions(d,
> - paddr_to_pfn(addr & PAGE_MASK),
> - DIV_ROUND_UP(size, PAGE_SIZE),
> - paddr_to_pfn(addr & PAGE_MASK));
> - if ( res )
> +
> + if ( map )
> {
> - printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> - " - 0x%"PRIx64" in domain %d\n",
> - addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1,
> - d->domain_id);
> - return res;
> + res = map_mmio_regions(d,
> + paddr_to_pfn(addr & PAGE_MASK),
> + DIV_ROUND_UP(size, PAGE_SIZE),
> + paddr_to_pfn(addr & PAGE_MASK));
> + if ( res )
> + {
> + printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> + " - 0x%"PRIx64" in domain %d\n",
> + addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1,
> + d->domain_id);
> + return res;
> + }
> }
> }
>
> @@ -865,10 +888,9 @@ static int handle_node(struct domain *d, struct
> kernel_info *kinfo,
> * property. Therefore these device doesn't need to be mapped. This
> * solution can be use later for pass through.
> */
> - if ( !dt_device_type_is_equal(node, "memory") &&
> - dt_device_is_available(node) )
> + if ( !dt_device_type_is_equal(node, "memory") )
> {
> - res = map_device(d, node);
> + res = handle_device(d, node, dt_device_is_available(node));
>
> if ( res )
> return res;
We need a comment here
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |