diff mbox series

[XEN,RFC,v3,01/14] xen/arm/device: Remove __init from function type

Message ID 20220308194704.14061-2-fnu.vikram@xilinx.com (mailing list archive)
State New, archived
Headers show
Series dynamic node programming using overlay dtbo | expand

Commit Message

Vikram Garhwal March 8, 2022, 7:46 p.m. UTC
Change function type of following function to access during runtime:
    1. map_irq_to_domain()
    2. handle_device_interrupt()
    3. map_range_to_domain()
    4. unflatten_dt_node()
    5. unflatten_device_tree()

Move map_irq_to_domain(), handle_device_interrupt() and map_range_to_domain() to
device.c.

These changes are done to support the dynamic programming of a nodes where an
overlay node will be added to fdt and unflattened node will be added to dt_host.
Furthermore, IRQ and mmio mapping will be done for the added node.

Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
---
 xen/arch/arm/device.c            | 136 +++++++++++++++++++++++++++++
 xen/arch/arm/domain_build.c      | 142 -------------------------------
 xen/arch/arm/include/asm/setup.h |   3 +
 xen/common/device_tree.c         |  20 ++---
 xen/include/xen/device_tree.h    |   5 ++
 5 files changed, 154 insertions(+), 152 deletions(-)

Comments

Luca Fancellu March 14, 2022, 12:31 p.m. UTC | #1
> On 8 Mar 2022, at 19:46, Vikram Garhwal <fnu.vikram@xilinx.com> wrote:
> 
> Change function type of following function to access during runtime:
>    1. map_irq_to_domain()
>    2. handle_device_interrupt()
>    3. map_range_to_domain()
>    4. unflatten_dt_node()
>    5. unflatten_device_tree()
> 
> Move map_irq_to_domain(), handle_device_interrupt() and map_range_to_domain() to
> device.c.
> 
> These changes are done to support the dynamic programming of a nodes where an
> overlay node will be added to fdt and unflattened node will be added to dt_host.
> Furthermore, IRQ and mmio mapping will be done for the added node.
> 
> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> ---
> xen/arch/arm/device.c            | 136 +++++++++++++++++++++++++++++
> xen/arch/arm/domain_build.c      | 142 -------------------------------
> xen/arch/arm/include/asm/setup.h |   3 +
> xen/common/device_tree.c         |  20 ++---
> xen/include/xen/device_tree.h    |   5 ++
> 5 files changed, 154 insertions(+), 152 deletions(-)
> 
> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> index 70cd6c1a19..0dfd33b33e 100644
> --- a/xen/arch/arm/device.c
> +++ b/xen/arch/arm/device.c
> @@ -21,6 +21,9 @@
> #include <xen/errno.h>
> #include <xen/init.h>
> #include <xen/lib.h>
> +#include <xen/iocap.h>
> +#include <asm/domain_build.h>
> +#include <asm/setup.h>
> 
> extern const struct device_desc _sdevice[], _edevice[];
> extern const struct acpi_device_desc _asdevice[], _aedevice[];
> @@ -84,6 +87,139 @@ enum device_class device_get_class(const struct dt_device_node *dev)
>     return DEVICE_UNKNOWN;
> }
> 
> +int map_irq_to_domain(struct domain *d, unsigned int irq,
> +                      bool need_mapping, const char *devname)
> +{
> +    int res;
> +
> +    res = irq_permit_access(d, irq);
> +    if ( res )
> +    {
> +        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> +               d->domain_id, irq);
> +        return res;
> +    }
> +
> +    if ( need_mapping )
> +    {
> +        /*
> +         * Checking the return of vgic_reserve_virq is not
> +         * necessary. It should not fail except when we try to map
> +         * the IRQ twice. This can legitimately happen if the IRQ is shared
> +         */
> +        vgic_reserve_virq(d, irq);
> +
> +        res = route_irq_to_guest(d, irq, irq, devname);
> +        if ( res < 0 )
> +        {
> +            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> +                   irq, d->domain_id);
> +            return res;
> +        }
> +    }
> +
> +    dt_dprintk("  - IRQ: %u\n", irq);
> +    return 0;
> +}
> +
> +int map_range_to_domain(const struct dt_device_node *dev,
> +                        u64 addr, u64 len, void *data)
> +{
> +    struct map_range_data *mr_data = data;
> +    struct domain *d = mr_data->d;
> +    int res;
> +
> +    res = iomem_permit_access(d, paddr_to_pfn(addr),
> +            paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));

Hi Vikram,

Why the if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
strlen("/reserved-memory/")) != 0 ) was dropped?


> +    if ( res )
> +    {
> +        printk(XENLOG_ERR "Unable to permit to dom%d access to"
> +                " 0x%"PRIx64" - 0x%"PRIx64"\n",
> +                d->domain_id,
> +                addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> +        return res;
> +    }
> +
> +    if ( !mr_data->skip_mapping )
> +    {
> +        res = map_regions_p2mt(d,
> +                               gaddr_to_gfn(addr),
> +                               PFN_UP(len),
> +                               maddr_to_mfn(addr),
> +                               mr_data->p2mt);
> +
> +        if ( res < 0 )
> +        {
> +            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> +                   " - 0x%"PRIx64" in domain %d\n",
> +                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> +                   d->domain_id);
> +            return res;
> +        }
> +    }
> +
> +    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> +               addr, addr + len, mr_data->p2mt);
> +
> +    return 0;
> +}
> +
> +/*
> + * handle_device_interrupts retrieves the interrupts configuration from
> + * a device tree node and maps those interrupts to the target domain.
> + *
> + * Returns:
> + *   < 0 error
> + *   0   success
> + */
> +int handle_device_interrupts(struct domain *d,
> +                             struct dt_device_node *dev,
> +                             bool need_mapping)
> +{
> +    unsigned int i, nirq;
> +    int res;
> +    struct dt_raw_irq rirq;
> +
> +    nirq = dt_number_of_irq(dev);
> +
> +    /* Give permission and map IRQs */
> +    for ( i = 0; i < nirq; i++ )
> +    {
> +        res = dt_device_get_raw_irq(dev, i, &rirq);
> +        if ( res )
> +        {
> +            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> +                   i, dt_node_full_name(dev));
> +            return res;
> +        }
> +
> +        /*
> +         * Don't map IRQ that have no physical meaning
> +         * ie: IRQ whose controller is not the GIC
> +         */
> +        if ( rirq.controller != dt_interrupt_controller )
> +        {
> +            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> +                      i, dt_node_full_name(rirq.controller));
> +            continue;
> +        }
> +
> +        res = platform_get_irq(dev, i);
> +        if ( res < 0 )
> +        {
> +            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> +                   i, dt_node_full_name(dev));
> +            return res;
> +        }
> +
> +        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> +        if ( res )
> +            return res;
> +    }
> +
> +    return 0;
> +}
> +
> /*
>  * Local variables:
>  * mode: C
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 8be01678de..b06770a2af 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1794,41 +1794,6 @@ int __init make_chosen_node(const struct kernel_info *kinfo)
>     return res;
> }
> 
> -int __init map_irq_to_domain(struct domain *d, unsigned int irq,
> -                             bool need_mapping, const char *devname)
> -{
> -    int res;
> -
> -    res = irq_permit_access(d, irq);
> -    if ( res )
> -    {
> -        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> -               d->domain_id, irq);
> -        return res;
> -    }
> -
> -    if ( need_mapping )
> -    {
> -        /*
> -         * Checking the return of vgic_reserve_virq is not
> -         * necessary. It should not fail except when we try to map
> -         * the IRQ twice. This can legitimately happen if the IRQ is shared
> -         */
> -        vgic_reserve_virq(d, irq);
> -
> -        res = route_irq_to_guest(d, irq, irq, devname);
> -        if ( res < 0 )
> -        {
> -            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> -                   irq, d->domain_id);
> -            return res;
> -        }
> -    }
> -
> -    dt_dprintk("  - IRQ: %u\n", irq);
> -    return 0;
> -}
> -
> static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
>                                        const struct dt_irq *dt_irq,
>                                        void *data)
> @@ -1860,57 +1825,6 @@ static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
>     return 0;
> }
> 
> -int __init map_range_to_domain(const struct dt_device_node *dev,
> -                               u64 addr, u64 len, void *data)
> -{
> -    struct map_range_data *mr_data = data;
> -    struct domain *d = mr_data->d;
> -    int res;
> -
> -    /*
> -     * reserved-memory regions are RAM carved out for a special purpose.
> -     * They are not MMIO and therefore a domain should not be able to
> -     * manage them via the IOMEM interface.
> -     */
> -    if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
> -                     strlen("/reserved-memory/")) != 0 )
> -    {
> -        res = iomem_permit_access(d, paddr_to_pfn(addr),
> -                paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
> -        if ( res )
> -        {
> -            printk(XENLOG_ERR "Unable to permit to dom%d access to"
> -                    " 0x%"PRIx64" - 0x%"PRIx64"\n",
> -                    d->domain_id,
> -                    addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> -            return res;
> -        }
> -    }
> -
> -    if ( !mr_data->skip_mapping )
> -    {
> -        res = map_regions_p2mt(d,
> -                               gaddr_to_gfn(addr),
> -                               PFN_UP(len),
> -                               maddr_to_mfn(addr),
> -                               mr_data->p2mt);
> -
> -        if ( res < 0 )
> -        {
> -            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> -                   " - 0x%"PRIx64" in domain %d\n",
> -                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> -                   d->domain_id);
> -            return res;
> -        }
> -    }
> -
> -    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> -               addr, addr + len, mr_data->p2mt);
> -
> -    return 0;
> -}
> -
> /*
>  * For a node which describes a discoverable bus (such as a PCI bus)
>  * then we may need to perform additional mappings in order to make
> @@ -1938,62 +1852,6 @@ static int __init map_device_children(const struct dt_device_node *dev,
>     return 0;
> }
> 
> -/*
> - * handle_device_interrupts retrieves the interrupts configuration from
> - * a device tree node and maps those interrupts to the target domain.
> - *
> - * Returns:
> - *   < 0 error
> - *   0   success
> - */
> -static int __init handle_device_interrupts(struct domain *d,
> -                                           struct dt_device_node *dev,
> -                                           bool need_mapping)
> -{
> -    unsigned int i, nirq;
> -    int res;
> -    struct dt_raw_irq rirq;
> -
> -    nirq = dt_number_of_irq(dev);
> -
> -    /* Give permission and map IRQs */
> -    for ( i = 0; i < nirq; i++ )
> -    {
> -        res = dt_device_get_raw_irq(dev, i, &rirq);
> -        if ( res )
> -        {
> -            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> -                   i, dt_node_full_name(dev));
> -            return res;
> -        }
> -
> -        /*
> -         * Don't map IRQ that have no physical meaning
> -         * ie: IRQ whose controller is not the GIC
> -         */
> -        if ( rirq.controller != dt_interrupt_controller )
> -        {
> -            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> -                      i, dt_node_full_name(rirq.controller));
> -            continue;
> -        }
> -
> -        res = platform_get_irq(dev, i);
> -        if ( res < 0 )
> -        {
> -            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> -                   i, dt_node_full_name(dev));
> -            return res;
> -        }
> -
> -        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> -        if ( res )
> -            return res;
> -    }
> -
> -    return 0;
> -}
> -
> /*
>  * For a given device node:
>  *  - Give permission to the guest to manage IRQ and MMIO range
> diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
> index 7a1e1d6798..8a26f1845c 100644
> --- a/xen/arch/arm/include/asm/setup.h
> +++ b/xen/arch/arm/include/asm/setup.h
> @@ -134,6 +134,9 @@ void device_tree_get_reg(const __be32 **cell, u32 address_cells,
> u32 device_tree_get_u32(const void *fdt, int node,
>                         const char *prop_name, u32 dflt);
> 
> +int handle_device_interrupts(struct domain *d, struct dt_device_node *dev,
> +                             bool need_mapping);
> +
> int map_range_to_domain(const struct dt_device_node *dev,
>                         u64 addr, u64 len, void *data);
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 4aae281e89..f43d66a501 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -1811,12 +1811,12 @@ int dt_count_phandle_with_args(const struct dt_device_node *np,
>  * @allnextpp: pointer to ->allnext from last allocated device_node
>  * @fpsize: Size of the node path up at the current depth.
>  */
> -static unsigned long __init unflatten_dt_node(const void *fdt,
> -                                              unsigned long mem,
> -                                              unsigned long *p,
> -                                              struct dt_device_node *dad,
> -                                              struct dt_device_node ***allnextpp,
> -                                              unsigned long fpsize)
> +static unsigned long unflatten_dt_node(const void *fdt,
> +                                       unsigned long mem,
> +                                       unsigned long *p,
> +                                       struct dt_device_node *dad,
> +                                       struct dt_device_node ***allnextpp,
> +                                       unsigned long fpsize)
> {
>     struct dt_device_node *np;
>     struct dt_property *pp, **prev_pp = NULL;
> @@ -2047,7 +2047,7 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
> }
> 
> /**
> - * __unflatten_device_tree - create tree of device_nodes from flat blob
> + * unflatten_device_tree - create tree of device_nodes from flat blob
>  *
>  * unflattens a device-tree, creating the
>  * tree of struct device_node. It also fills the "name" and "type"
> @@ -2056,8 +2056,8 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
>  * @fdt: The fdt to expand
>  * @mynodes: The device_node tree created by the call
>  */
> -static void __init __unflatten_device_tree(const void *fdt,
> -                                           struct dt_device_node **mynodes)
> +void unflatten_device_tree(const void *fdt,
> +                           struct dt_device_node **mynodes)
> {
>     unsigned long start, mem, size;
>     struct dt_device_node **allnextp = mynodes;
> @@ -2179,7 +2179,7 @@ dt_find_interrupt_controller(const struct dt_device_match *matches)
> 
> void __init dt_unflatten_host_device_tree(void)
> {
> -    __unflatten_device_tree(device_tree_flattened, &dt_host);
> +    unflatten_device_tree(device_tree_flattened, &dt_host);
>     dt_alias_scan();
> }
> 
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index fd6cd00b43..06d7866c10 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -177,6 +177,11 @@ int device_tree_for_each_node(const void *fdt, int node,
>  */
> void dt_unflatten_host_device_tree(void);
> 
> +/*
> + * unflatten any device tree.
> + */
> +void unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes);
> +
> /**
>  * IRQ translation callback
>  * TODO: For the moment we assume that we only have ONE

NIT: there are some minor code style issues, like indentation that could be fixed

Cheers,
Luca
Vikram Garhwal March 15, 2022, 10:29 p.m. UTC | #2
On Mon, Mar 14, 2022 at 12:31:06PM +0000, Luca Fancellu wrote:
> 
> 
> > On 8 Mar 2022, at 19:46, Vikram Garhwal <fnu.vikram@xilinx.com> wrote:
> > 
> > Change function type of following function to access during runtime:
> >    1. map_irq_to_domain()
> >    2. handle_device_interrupt()
> >    3. map_range_to_domain()
> >    4. unflatten_dt_node()
> >    5. unflatten_device_tree()
> > 
> > Move map_irq_to_domain(), handle_device_interrupt() and map_range_to_domain() to
> > device.c.
> > 
> > These changes are done to support the dynamic programming of a nodes where an
> > overlay node will be added to fdt and unflattened node will be added to dt_host.
> > Furthermore, IRQ and mmio mapping will be done for the added node.
> > 
> > Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> > ---
> > xen/arch/arm/device.c            | 136 +++++++++++++++++++++++++++++
> > xen/arch/arm/domain_build.c      | 142 -------------------------------
> > xen/arch/arm/include/asm/setup.h |   3 +
> > xen/common/device_tree.c         |  20 ++---
> > xen/include/xen/device_tree.h    |   5 ++
> > 5 files changed, 154 insertions(+), 152 deletions(-)
> > 
> > diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> > index 70cd6c1a19..0dfd33b33e 100644
> > --- a/xen/arch/arm/device.c
> > +++ b/xen/arch/arm/device.c
> > @@ -21,6 +21,9 @@
> > #include <xen/errno.h>
> > #include <xen/init.h>
> > #include <xen/lib.h>
> > +#include <xen/iocap.h>
> > +#include <asm/domain_build.h>
> > +#include <asm/setup.h>
> > 
> > extern const struct device_desc _sdevice[], _edevice[];
> > extern const struct acpi_device_desc _asdevice[], _aedevice[];
> > @@ -84,6 +87,139 @@ enum device_class device_get_class(const struct dt_device_node *dev)
> >     return DEVICE_UNKNOWN;
> > }
> > 
> > +int map_irq_to_domain(struct domain *d, unsigned int irq,
> > +                      bool need_mapping, const char *devname)
> > +{
> > +    int res;
> > +
> > +    res = irq_permit_access(d, irq);
> > +    if ( res )
> > +    {
> > +        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> > +               d->domain_id, irq);
> > +        return res;
> > +    }
> > +
> > +    if ( need_mapping )
> > +    {
> > +        /*
> > +         * Checking the return of vgic_reserve_virq is not
> > +         * necessary. It should not fail except when we try to map
> > +         * the IRQ twice. This can legitimately happen if the IRQ is shared
> > +         */
> > +        vgic_reserve_virq(d, irq);
> > +
> > +        res = route_irq_to_guest(d, irq, irq, devname);
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> > +                   irq, d->domain_id);
> > +            return res;
> > +        }
> > +    }
> > +
> > +    dt_dprintk("  - IRQ: %u\n", irq);
> > +    return 0;
> > +}
> > +
> > +int map_range_to_domain(const struct dt_device_node *dev,
> > +                        u64 addr, u64 len, void *data)
> > +{
> > +    struct map_range_data *mr_data = data;
> > +    struct domain *d = mr_data->d;
> > +    int res;
> > +
> > +    res = iomem_permit_access(d, paddr_to_pfn(addr),
> > +            paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
> 
> Hi Vikram,
> 
> Why the if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
> strlen("/reserved-memory/")) != 0 ) was dropped?
> 
Hi Luca,
Thanks for spotting this. Yeah, I messed this while porting the patches from 
internal to upstream Xen.
Will address this in v4!

> 
> > +    if ( res )
> > +    {
> > +        printk(XENLOG_ERR "Unable to permit to dom%d access to"
> > +                " 0x%"PRIx64" - 0x%"PRIx64"\n",
> > +                d->domain_id,
> > +                addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> > +        return res;
> > +    }
> > +
> > +    if ( !mr_data->skip_mapping )
> > +    {
> > +        res = map_regions_p2mt(d,
> > +                               gaddr_to_gfn(addr),
> > +                               PFN_UP(len),
> > +                               maddr_to_mfn(addr),
> > +                               mr_data->p2mt);
> > +
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> > +                   " - 0x%"PRIx64" in domain %d\n",
> > +                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> > +                   d->domain_id);
> > +            return res;
> > +        }
> > +    }
> > +
> > +    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> > +               addr, addr + len, mr_data->p2mt);
> > +
> > +    return 0;
> > +}
> > +
> > +/*
> > + * handle_device_interrupts retrieves the interrupts configuration from
> > + * a device tree node and maps those interrupts to the target domain.
> > + *
> > + * Returns:
> > + *   < 0 error
> > + *   0   success
> > + */
> > +int handle_device_interrupts(struct domain *d,
> > +                             struct dt_device_node *dev,
> > +                             bool need_mapping)
> > +{
> > +    unsigned int i, nirq;
> > +    int res;
> > +    struct dt_raw_irq rirq;
> > +
> > +    nirq = dt_number_of_irq(dev);
> > +
> > +    /* Give permission and map IRQs */
> > +    for ( i = 0; i < nirq; i++ )
> > +    {
> > +        res = dt_device_get_raw_irq(dev, i, &rirq);
> > +        if ( res )
> > +        {
> > +            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> > +                   i, dt_node_full_name(dev));
> > +            return res;
> > +        }
> > +
> > +        /*
> > +         * Don't map IRQ that have no physical meaning
> > +         * ie: IRQ whose controller is not the GIC
> > +         */
> > +        if ( rirq.controller != dt_interrupt_controller )
> > +        {
> > +            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> > +                      i, dt_node_full_name(rirq.controller));
> > +            continue;
> > +        }
> > +
> > +        res = platform_get_irq(dev, i);
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> > +                   i, dt_node_full_name(dev));
> > +            return res;
> > +        }
> > +
> > +        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> > +        if ( res )
> > +            return res;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > /*
> >  * Local variables:
> >  * mode: C
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 8be01678de..b06770a2af 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -1794,41 +1794,6 @@ int __init make_chosen_node(const struct kernel_info *kinfo)
> >     return res;
> > }
> > 
> > -int __init map_irq_to_domain(struct domain *d, unsigned int irq,
> > -                             bool need_mapping, const char *devname)
> > -{
> > -    int res;
> > -
> > -    res = irq_permit_access(d, irq);
> > -    if ( res )
> > -    {
> > -        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> > -               d->domain_id, irq);
> > -        return res;
> > -    }
> > -
> > -    if ( need_mapping )
> > -    {
> > -        /*
> > -         * Checking the return of vgic_reserve_virq is not
> > -         * necessary. It should not fail except when we try to map
> > -         * the IRQ twice. This can legitimately happen if the IRQ is shared
> > -         */
> > -        vgic_reserve_virq(d, irq);
> > -
> > -        res = route_irq_to_guest(d, irq, irq, devname);
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> > -                   irq, d->domain_id);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    dt_dprintk("  - IRQ: %u\n", irq);
> > -    return 0;
> > -}
> > -
> > static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
> >                                        const struct dt_irq *dt_irq,
> >                                        void *data)
> > @@ -1860,57 +1825,6 @@ static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
> >     return 0;
> > }
> > 
> > -int __init map_range_to_domain(const struct dt_device_node *dev,
> > -                               u64 addr, u64 len, void *data)
> > -{
> > -    struct map_range_data *mr_data = data;
> > -    struct domain *d = mr_data->d;
> > -    int res;
> > -
> > -    /*
> > -     * reserved-memory regions are RAM carved out for a special purpose.
> > -     * They are not MMIO and therefore a domain should not be able to
> > -     * manage them via the IOMEM interface.
> > -     */
> > -    if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
> > -                     strlen("/reserved-memory/")) != 0 )
> > -    {
> > -        res = iomem_permit_access(d, paddr_to_pfn(addr),
> > -                paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
> > -        if ( res )
> > -        {
> > -            printk(XENLOG_ERR "Unable to permit to dom%d access to"
> > -                    " 0x%"PRIx64" - 0x%"PRIx64"\n",
> > -                    d->domain_id,
> > -                    addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    if ( !mr_data->skip_mapping )
> > -    {
> > -        res = map_regions_p2mt(d,
> > -                               gaddr_to_gfn(addr),
> > -                               PFN_UP(len),
> > -                               maddr_to_mfn(addr),
> > -                               mr_data->p2mt);
> > -
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> > -                   " - 0x%"PRIx64" in domain %d\n",
> > -                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> > -                   d->domain_id);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> > -               addr, addr + len, mr_data->p2mt);
> > -
> > -    return 0;
> > -}
> > -
> > /*
> >  * For a node which describes a discoverable bus (such as a PCI bus)
> >  * then we may need to perform additional mappings in order to make
> > @@ -1938,62 +1852,6 @@ static int __init map_device_children(const struct dt_device_node *dev,
> >     return 0;
> > }
> > 
> > -/*
> > - * handle_device_interrupts retrieves the interrupts configuration from
> > - * a device tree node and maps those interrupts to the target domain.
> > - *
> > - * Returns:
> > - *   < 0 error
> > - *   0   success
> > - */
> > -static int __init handle_device_interrupts(struct domain *d,
> > -                                           struct dt_device_node *dev,
> > -                                           bool need_mapping)
> > -{
> > -    unsigned int i, nirq;
> > -    int res;
> > -    struct dt_raw_irq rirq;
> > -
> > -    nirq = dt_number_of_irq(dev);
> > -
> > -    /* Give permission and map IRQs */
> > -    for ( i = 0; i < nirq; i++ )
> > -    {
> > -        res = dt_device_get_raw_irq(dev, i, &rirq);
> > -        if ( res )
> > -        {
> > -            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> > -                   i, dt_node_full_name(dev));
> > -            return res;
> > -        }
> > -
> > -        /*
> > -         * Don't map IRQ that have no physical meaning
> > -         * ie: IRQ whose controller is not the GIC
> > -         */
> > -        if ( rirq.controller != dt_interrupt_controller )
> > -        {
> > -            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> > -                      i, dt_node_full_name(rirq.controller));
> > -            continue;
> > -        }
> > -
> > -        res = platform_get_irq(dev, i);
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> > -                   i, dt_node_full_name(dev));
> > -            return res;
> > -        }
> > -
> > -        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> > -        if ( res )
> > -            return res;
> > -    }
> > -
> > -    return 0;
> > -}
> > -
> > /*
> >  * For a given device node:
> >  *  - Give permission to the guest to manage IRQ and MMIO range
> > diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
> > index 7a1e1d6798..8a26f1845c 100644
> > --- a/xen/arch/arm/include/asm/setup.h
> > +++ b/xen/arch/arm/include/asm/setup.h
> > @@ -134,6 +134,9 @@ void device_tree_get_reg(const __be32 **cell, u32 address_cells,
> > u32 device_tree_get_u32(const void *fdt, int node,
> >                         const char *prop_name, u32 dflt);
> > 
> > +int handle_device_interrupts(struct domain *d, struct dt_device_node *dev,
> > +                             bool need_mapping);
> > +
> > int map_range_to_domain(const struct dt_device_node *dev,
> >                         u64 addr, u64 len, void *data);
> > 
> > diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> > index 4aae281e89..f43d66a501 100644
> > --- a/xen/common/device_tree.c
> > +++ b/xen/common/device_tree.c
> > @@ -1811,12 +1811,12 @@ int dt_count_phandle_with_args(const struct dt_device_node *np,
> >  * @allnextpp: pointer to ->allnext from last allocated device_node
> >  * @fpsize: Size of the node path up at the current depth.
> >  */
> > -static unsigned long __init unflatten_dt_node(const void *fdt,
> > -                                              unsigned long mem,
> > -                                              unsigned long *p,
> > -                                              struct dt_device_node *dad,
> > -                                              struct dt_device_node ***allnextpp,
> > -                                              unsigned long fpsize)
> > +static unsigned long unflatten_dt_node(const void *fdt,
> > +                                       unsigned long mem,
> > +                                       unsigned long *p,
> > +                                       struct dt_device_node *dad,
> > +                                       struct dt_device_node ***allnextpp,
> > +                                       unsigned long fpsize)
> > {
> >     struct dt_device_node *np;
> >     struct dt_property *pp, **prev_pp = NULL;
> > @@ -2047,7 +2047,7 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
> > }
> > 
> > /**
> > - * __unflatten_device_tree - create tree of device_nodes from flat blob
> > + * unflatten_device_tree - create tree of device_nodes from flat blob
> >  *
> >  * unflattens a device-tree, creating the
> >  * tree of struct device_node. It also fills the "name" and "type"
> > @@ -2056,8 +2056,8 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
> >  * @fdt: The fdt to expand
> >  * @mynodes: The device_node tree created by the call
> >  */
> > -static void __init __unflatten_device_tree(const void *fdt,
> > -                                           struct dt_device_node **mynodes)
> > +void unflatten_device_tree(const void *fdt,
> > +                           struct dt_device_node **mynodes)
> > {
> >     unsigned long start, mem, size;
> >     struct dt_device_node **allnextp = mynodes;
> > @@ -2179,7 +2179,7 @@ dt_find_interrupt_controller(const struct dt_device_match *matches)
> > 
> > void __init dt_unflatten_host_device_tree(void)
> > {
> > -    __unflatten_device_tree(device_tree_flattened, &dt_host);
> > +    unflatten_device_tree(device_tree_flattened, &dt_host);
> >     dt_alias_scan();
> > }
> > 
> > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> > index fd6cd00b43..06d7866c10 100644
> > --- a/xen/include/xen/device_tree.h
> > +++ b/xen/include/xen/device_tree.h
> > @@ -177,6 +177,11 @@ int device_tree_for_each_node(const void *fdt, int node,
> >  */
> > void dt_unflatten_host_device_tree(void);
> > 
> > +/*
> > + * unflatten any device tree.
> > + */
> > +void unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes);
> > +
> > /**
> >  * IRQ translation callback
> >  * TODO: For the moment we assume that we only have ONE
> 
> NIT: there are some minor code style issues, like indentation that could be fixed
> 
> Cheers,
> Luca
>
Vikram Garhwal March 15, 2022, 10:42 p.m. UTC | #3
On Mon, Mar 14, 2022 at 12:31:06PM +0000, Luca Fancellu wrote:
> 
> 
> > On 8 Mar 2022, at 19:46, Vikram Garhwal <fnu.vikram@xilinx.com> wrote:
> > 
> > Change function type of following function to access during runtime:
> >    1. map_irq_to_domain()
> >    2. handle_device_interrupt()
> >    3. map_range_to_domain()
> >    4. unflatten_dt_node()
> >    5. unflatten_device_tree()
> > 
> > Move map_irq_to_domain(), handle_device_interrupt() and map_range_to_domain() to
> > device.c.
> > 
> > These changes are done to support the dynamic programming of a nodes where an
> > overlay node will be added to fdt and unflattened node will be added to dt_host.
> > Furthermore, IRQ and mmio mapping will be done for the added node.
> > 
> > Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> > ---
> > xen/arch/arm/device.c            | 136 +++++++++++++++++++++++++++++
> > xen/arch/arm/domain_build.c      | 142 -------------------------------
> > xen/arch/arm/include/asm/setup.h |   3 +
> > xen/common/device_tree.c         |  20 ++---
> > xen/include/xen/device_tree.h    |   5 ++
> > 5 files changed, 154 insertions(+), 152 deletions(-)
> > 
> > diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> > index 70cd6c1a19..0dfd33b33e 100644
> > --- a/xen/arch/arm/device.c
> > +++ b/xen/arch/arm/device.c
> > @@ -21,6 +21,9 @@
> > #include <xen/errno.h>
> > #include <xen/init.h>
> > #include <xen/lib.h>
> > +#include <xen/iocap.h>
> > +#include <asm/domain_build.h>
> > +#include <asm/setup.h>
> > 
> > extern const struct device_desc _sdevice[], _edevice[];
> > extern const struct acpi_device_desc _asdevice[], _aedevice[];
> > @@ -84,6 +87,139 @@ enum device_class device_get_class(const struct dt_device_node *dev)
> >     return DEVICE_UNKNOWN;
> > }
> > 
> > +int map_irq_to_domain(struct domain *d, unsigned int irq,
> > +                      bool need_mapping, const char *devname)
> > +{
> > +    int res;
> > +
> > +    res = irq_permit_access(d, irq);
> > +    if ( res )
> > +    {
> > +        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> > +               d->domain_id, irq);
> > +        return res;
> > +    }
> > +
> > +    if ( need_mapping )
> > +    {
> > +        /*
> > +         * Checking the return of vgic_reserve_virq is not
> > +         * necessary. It should not fail except when we try to map
> > +         * the IRQ twice. This can legitimately happen if the IRQ is shared
> > +         */
> > +        vgic_reserve_virq(d, irq);
> > +
> > +        res = route_irq_to_guest(d, irq, irq, devname);
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> > +                   irq, d->domain_id);
> > +            return res;
> > +        }
> > +    }
> > +
> > +    dt_dprintk("  - IRQ: %u\n", irq);
> > +    return 0;
> > +}
> > +
> > +int map_range_to_domain(const struct dt_device_node *dev,
> > +                        u64 addr, u64 len, void *data)
> > +{
> > +    struct map_range_data *mr_data = data;
> > +    struct domain *d = mr_data->d;
> > +    int res;
> > +
> > +    res = iomem_permit_access(d, paddr_to_pfn(addr),
> > +            paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
> 
> Hi Vikram,
> 
> Why the if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
> strlen("/reserved-memory/")) != 0 ) was dropped?
> 
> 
Hi Luca,
Thanks for spotting this. Yeah, I messed this while porting the patches from
internal to upstream Xen.
Will address this in v4!

@everyone, apologies for resending the same email. Previous one didn't make to
xen-devel due to change in my email ID.

Regards,
Vikram
> > +    if ( res )
> > +    {
> > +        printk(XENLOG_ERR "Unable to permit to dom%d access to"
> > +                " 0x%"PRIx64" - 0x%"PRIx64"\n",
> > +                d->domain_id,
> > +                addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> > +        return res;
> > +    }
> > +
> > +    if ( !mr_data->skip_mapping )
> > +    {
> > +        res = map_regions_p2mt(d,
> > +                               gaddr_to_gfn(addr),
> > +                               PFN_UP(len),
> > +                               maddr_to_mfn(addr),
> > +                               mr_data->p2mt);
> > +
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> > +                   " - 0x%"PRIx64" in domain %d\n",
> > +                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> > +                   d->domain_id);
> > +            return res;
> > +        }
> > +    }
> > +
> > +    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> > +               addr, addr + len, mr_data->p2mt);
> > +
> > +    return 0;
> > +}
> > +
> > +/*
> > + * handle_device_interrupts retrieves the interrupts configuration from
> > + * a device tree node and maps those interrupts to the target domain.
> > + *
> > + * Returns:
> > + *   < 0 error
> > + *   0   success
> > + */
> > +int handle_device_interrupts(struct domain *d,
> > +                             struct dt_device_node *dev,
> > +                             bool need_mapping)
> > +{
> > +    unsigned int i, nirq;
> > +    int res;
> > +    struct dt_raw_irq rirq;
> > +
> > +    nirq = dt_number_of_irq(dev);
> > +
> > +    /* Give permission and map IRQs */
> > +    for ( i = 0; i < nirq; i++ )
> > +    {
> > +        res = dt_device_get_raw_irq(dev, i, &rirq);
> > +        if ( res )
> > +        {
> > +            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> > +                   i, dt_node_full_name(dev));
> > +            return res;
> > +        }
> > +
> > +        /*
> > +         * Don't map IRQ that have no physical meaning
> > +         * ie: IRQ whose controller is not the GIC
> > +         */
> > +        if ( rirq.controller != dt_interrupt_controller )
> > +        {
> > +            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> > +                      i, dt_node_full_name(rirq.controller));
> > +            continue;
> > +        }
> > +
> > +        res = platform_get_irq(dev, i);
> > +        if ( res < 0 )
> > +        {
> > +            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> > +                   i, dt_node_full_name(dev));
> > +            return res;
> > +        }
> > +
> > +        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> > +        if ( res )
> > +            return res;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > /*
> >  * Local variables:
> >  * mode: C
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 8be01678de..b06770a2af 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -1794,41 +1794,6 @@ int __init make_chosen_node(const struct kernel_info *kinfo)
> >     return res;
> > }
> > 
> > -int __init map_irq_to_domain(struct domain *d, unsigned int irq,
> > -                             bool need_mapping, const char *devname)
> > -{
> > -    int res;
> > -
> > -    res = irq_permit_access(d, irq);
> > -    if ( res )
> > -    {
> > -        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
> > -               d->domain_id, irq);
> > -        return res;
> > -    }
> > -
> > -    if ( need_mapping )
> > -    {
> > -        /*
> > -         * Checking the return of vgic_reserve_virq is not
> > -         * necessary. It should not fail except when we try to map
> > -         * the IRQ twice. This can legitimately happen if the IRQ is shared
> > -         */
> > -        vgic_reserve_virq(d, irq);
> > -
> > -        res = route_irq_to_guest(d, irq, irq, devname);
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
> > -                   irq, d->domain_id);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    dt_dprintk("  - IRQ: %u\n", irq);
> > -    return 0;
> > -}
> > -
> > static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
> >                                        const struct dt_irq *dt_irq,
> >                                        void *data)
> > @@ -1860,57 +1825,6 @@ static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
> >     return 0;
> > }
> > 
> > -int __init map_range_to_domain(const struct dt_device_node *dev,
> > -                               u64 addr, u64 len, void *data)
> > -{
> > -    struct map_range_data *mr_data = data;
> > -    struct domain *d = mr_data->d;
> > -    int res;
> > -
> > -    /*
> > -     * reserved-memory regions are RAM carved out for a special purpose.
> > -     * They are not MMIO and therefore a domain should not be able to
> > -     * manage them via the IOMEM interface.
> > -     */
> > -    if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
> > -                     strlen("/reserved-memory/")) != 0 )
> > -    {
> > -        res = iomem_permit_access(d, paddr_to_pfn(addr),
> > -                paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
> > -        if ( res )
> > -        {
> > -            printk(XENLOG_ERR "Unable to permit to dom%d access to"
> > -                    " 0x%"PRIx64" - 0x%"PRIx64"\n",
> > -                    d->domain_id,
> > -                    addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    if ( !mr_data->skip_mapping )
> > -    {
> > -        res = map_regions_p2mt(d,
> > -                               gaddr_to_gfn(addr),
> > -                               PFN_UP(len),
> > -                               maddr_to_mfn(addr),
> > -                               mr_data->p2mt);
> > -
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
> > -                   " - 0x%"PRIx64" in domain %d\n",
> > -                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
> > -                   d->domain_id);
> > -            return res;
> > -        }
> > -    }
> > -
> > -    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
> > -               addr, addr + len, mr_data->p2mt);
> > -
> > -    return 0;
> > -}
> > -
> > /*
> >  * For a node which describes a discoverable bus (such as a PCI bus)
> >  * then we may need to perform additional mappings in order to make
> > @@ -1938,62 +1852,6 @@ static int __init map_device_children(const struct dt_device_node *dev,
> >     return 0;
> > }
> > 
> > -/*
> > - * handle_device_interrupts retrieves the interrupts configuration from
> > - * a device tree node and maps those interrupts to the target domain.
> > - *
> > - * Returns:
> > - *   < 0 error
> > - *   0   success
> > - */
> > -static int __init handle_device_interrupts(struct domain *d,
> > -                                           struct dt_device_node *dev,
> > -                                           bool need_mapping)
> > -{
> > -    unsigned int i, nirq;
> > -    int res;
> > -    struct dt_raw_irq rirq;
> > -
> > -    nirq = dt_number_of_irq(dev);
> > -
> > -    /* Give permission and map IRQs */
> > -    for ( i = 0; i < nirq; i++ )
> > -    {
> > -        res = dt_device_get_raw_irq(dev, i, &rirq);
> > -        if ( res )
> > -        {
> > -            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
> > -                   i, dt_node_full_name(dev));
> > -            return res;
> > -        }
> > -
> > -        /*
> > -         * Don't map IRQ that have no physical meaning
> > -         * ie: IRQ whose controller is not the GIC
> > -         */
> > -        if ( rirq.controller != dt_interrupt_controller )
> > -        {
> > -            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
> > -                      i, dt_node_full_name(rirq.controller));
> > -            continue;
> > -        }
> > -
> > -        res = platform_get_irq(dev, i);
> > -        if ( res < 0 )
> > -        {
> > -            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
> > -                   i, dt_node_full_name(dev));
> > -            return res;
> > -        }
> > -
> > -        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
> > -        if ( res )
> > -            return res;
> > -    }
> > -
> > -    return 0;
> > -}
> > -
> > /*
> >  * For a given device node:
> >  *  - Give permission to the guest to manage IRQ and MMIO range
> > diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
> > index 7a1e1d6798..8a26f1845c 100644
> > --- a/xen/arch/arm/include/asm/setup.h
> > +++ b/xen/arch/arm/include/asm/setup.h
> > @@ -134,6 +134,9 @@ void device_tree_get_reg(const __be32 **cell, u32 address_cells,
> > u32 device_tree_get_u32(const void *fdt, int node,
> >                         const char *prop_name, u32 dflt);
> > 
> > +int handle_device_interrupts(struct domain *d, struct dt_device_node *dev,
> > +                             bool need_mapping);
> > +
> > int map_range_to_domain(const struct dt_device_node *dev,
> >                         u64 addr, u64 len, void *data);
> > 
> > diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> > index 4aae281e89..f43d66a501 100644
> > --- a/xen/common/device_tree.c
> > +++ b/xen/common/device_tree.c
> > @@ -1811,12 +1811,12 @@ int dt_count_phandle_with_args(const struct dt_device_node *np,
> >  * @allnextpp: pointer to ->allnext from last allocated device_node
> >  * @fpsize: Size of the node path up at the current depth.
> >  */
> > -static unsigned long __init unflatten_dt_node(const void *fdt,
> > -                                              unsigned long mem,
> > -                                              unsigned long *p,
> > -                                              struct dt_device_node *dad,
> > -                                              struct dt_device_node ***allnextpp,
> > -                                              unsigned long fpsize)
> > +static unsigned long unflatten_dt_node(const void *fdt,
> > +                                       unsigned long mem,
> > +                                       unsigned long *p,
> > +                                       struct dt_device_node *dad,
> > +                                       struct dt_device_node ***allnextpp,
> > +                                       unsigned long fpsize)
> > {
> >     struct dt_device_node *np;
> >     struct dt_property *pp, **prev_pp = NULL;
> > @@ -2047,7 +2047,7 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
> > }
> > 
> > /**
> > - * __unflatten_device_tree - create tree of device_nodes from flat blob
> > + * unflatten_device_tree - create tree of device_nodes from flat blob
> >  *
> >  * unflattens a device-tree, creating the
> >  * tree of struct device_node. It also fills the "name" and "type"
> > @@ -2056,8 +2056,8 @@ static unsigned long __init unflatten_dt_node(const void *fdt,
> >  * @fdt: The fdt to expand
> >  * @mynodes: The device_node tree created by the call
> >  */
> > -static void __init __unflatten_device_tree(const void *fdt,
> > -                                           struct dt_device_node **mynodes)
> > +void unflatten_device_tree(const void *fdt,
> > +                           struct dt_device_node **mynodes)
> > {
> >     unsigned long start, mem, size;
> >     struct dt_device_node **allnextp = mynodes;
> > @@ -2179,7 +2179,7 @@ dt_find_interrupt_controller(const struct dt_device_match *matches)
> > 
> > void __init dt_unflatten_host_device_tree(void)
> > {
> > -    __unflatten_device_tree(device_tree_flattened, &dt_host);
> > +    unflatten_device_tree(device_tree_flattened, &dt_host);
> >     dt_alias_scan();
> > }
> > 
> > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> > index fd6cd00b43..06d7866c10 100644
> > --- a/xen/include/xen/device_tree.h
> > +++ b/xen/include/xen/device_tree.h
> > @@ -177,6 +177,11 @@ int device_tree_for_each_node(const void *fdt, int node,
> >  */
> > void dt_unflatten_host_device_tree(void);
> > 
> > +/*
> > + * unflatten any device tree.
> > + */
> > +void unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes);
> > +
> > /**
> >  * IRQ translation callback
> >  * TODO: For the moment we assume that we only have ONE
> 
> NIT: there are some minor code style issues, like indentation that could be fixed
> 
> Cheers,
> Luca
>
diff mbox series

Patch

diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 70cd6c1a19..0dfd33b33e 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -21,6 +21,9 @@ 
 #include <xen/errno.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/iocap.h>
+#include <asm/domain_build.h>
+#include <asm/setup.h>
 
 extern const struct device_desc _sdevice[], _edevice[];
 extern const struct acpi_device_desc _asdevice[], _aedevice[];
@@ -84,6 +87,139 @@  enum device_class device_get_class(const struct dt_device_node *dev)
     return DEVICE_UNKNOWN;
 }
 
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname)
+{
+    int res;
+
+    res = irq_permit_access(d, irq);
+    if ( res )
+    {
+        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
+               d->domain_id, irq);
+        return res;
+    }
+
+    if ( need_mapping )
+    {
+        /*
+         * Checking the return of vgic_reserve_virq is not
+         * necessary. It should not fail except when we try to map
+         * the IRQ twice. This can legitimately happen if the IRQ is shared
+         */
+        vgic_reserve_virq(d, irq);
+
+        res = route_irq_to_guest(d, irq, irq, devname);
+        if ( res < 0 )
+        {
+            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
+                   irq, d->domain_id);
+            return res;
+        }
+    }
+
+    dt_dprintk("  - IRQ: %u\n", irq);
+    return 0;
+}
+
+int map_range_to_domain(const struct dt_device_node *dev,
+                        u64 addr, u64 len, void *data)
+{
+    struct map_range_data *mr_data = data;
+    struct domain *d = mr_data->d;
+    int res;
+
+    res = iomem_permit_access(d, paddr_to_pfn(addr),
+            paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
+    if ( res )
+    {
+        printk(XENLOG_ERR "Unable to permit to dom%d access to"
+                " 0x%"PRIx64" - 0x%"PRIx64"\n",
+                d->domain_id,
+                addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
+        return res;
+    }
+
+    if ( !mr_data->skip_mapping )
+    {
+        res = map_regions_p2mt(d,
+                               gaddr_to_gfn(addr),
+                               PFN_UP(len),
+                               maddr_to_mfn(addr),
+                               mr_data->p2mt);
+
+        if ( res < 0 )
+        {
+            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
+                   " - 0x%"PRIx64" in domain %d\n",
+                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
+                   d->domain_id);
+            return res;
+        }
+    }
+
+    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
+               addr, addr + len, mr_data->p2mt);
+
+    return 0;
+}
+
+/*
+ * handle_device_interrupts retrieves the interrupts configuration from
+ * a device tree node and maps those interrupts to the target domain.
+ *
+ * Returns:
+ *   < 0 error
+ *   0   success
+ */
+int handle_device_interrupts(struct domain *d,
+                             struct dt_device_node *dev,
+                             bool need_mapping)
+{
+    unsigned int i, nirq;
+    int res;
+    struct dt_raw_irq rirq;
+
+    nirq = dt_number_of_irq(dev);
+
+    /* Give permission and map IRQs */
+    for ( i = 0; i < nirq; i++ )
+    {
+        res = dt_device_get_raw_irq(dev, i, &rirq);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
+                   i, dt_node_full_name(dev));
+            return res;
+        }
+
+        /*
+         * Don't map IRQ that have no physical meaning
+         * ie: IRQ whose controller is not the GIC
+         */
+        if ( rirq.controller != dt_interrupt_controller )
+        {
+            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
+                      i, dt_node_full_name(rirq.controller));
+            continue;
+        }
+
+        res = platform_get_irq(dev, i);
+        if ( res < 0 )
+        {
+            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
+                   i, dt_node_full_name(dev));
+            return res;
+        }
+
+        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
+        if ( res )
+            return res;
+    }
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8be01678de..b06770a2af 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1794,41 +1794,6 @@  int __init make_chosen_node(const struct kernel_info *kinfo)
     return res;
 }
 
-int __init map_irq_to_domain(struct domain *d, unsigned int irq,
-                             bool need_mapping, const char *devname)
-{
-    int res;
-
-    res = irq_permit_access(d, irq);
-    if ( res )
-    {
-        printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
-               d->domain_id, irq);
-        return res;
-    }
-
-    if ( need_mapping )
-    {
-        /*
-         * Checking the return of vgic_reserve_virq is not
-         * necessary. It should not fail except when we try to map
-         * the IRQ twice. This can legitimately happen if the IRQ is shared
-         */
-        vgic_reserve_virq(d, irq);
-
-        res = route_irq_to_guest(d, irq, irq, devname);
-        if ( res < 0 )
-        {
-            printk(XENLOG_ERR "Unable to map IRQ%"PRId32" to dom%d\n",
-                   irq, d->domain_id);
-            return res;
-        }
-    }
-
-    dt_dprintk("  - IRQ: %u\n", irq);
-    return 0;
-}
-
 static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
                                        const struct dt_irq *dt_irq,
                                        void *data)
@@ -1860,57 +1825,6 @@  static int __init map_dt_irq_to_domain(const struct dt_device_node *dev,
     return 0;
 }
 
-int __init map_range_to_domain(const struct dt_device_node *dev,
-                               u64 addr, u64 len, void *data)
-{
-    struct map_range_data *mr_data = data;
-    struct domain *d = mr_data->d;
-    int res;
-
-    /*
-     * reserved-memory regions are RAM carved out for a special purpose.
-     * They are not MMIO and therefore a domain should not be able to
-     * manage them via the IOMEM interface.
-     */
-    if ( strncasecmp(dt_node_full_name(dev), "/reserved-memory/",
-                     strlen("/reserved-memory/")) != 0 )
-    {
-        res = iomem_permit_access(d, paddr_to_pfn(addr),
-                paddr_to_pfn(PAGE_ALIGN(addr + len - 1)));
-        if ( res )
-        {
-            printk(XENLOG_ERR "Unable to permit to dom%d access to"
-                    " 0x%"PRIx64" - 0x%"PRIx64"\n",
-                    d->domain_id,
-                    addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1);
-            return res;
-        }
-    }
-
-    if ( !mr_data->skip_mapping )
-    {
-        res = map_regions_p2mt(d,
-                               gaddr_to_gfn(addr),
-                               PFN_UP(len),
-                               maddr_to_mfn(addr),
-                               mr_data->p2mt);
-
-        if ( res < 0 )
-        {
-            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
-                   " - 0x%"PRIx64" in domain %d\n",
-                   addr & PAGE_MASK, PAGE_ALIGN(addr + len) - 1,
-                   d->domain_id);
-            return res;
-        }
-    }
-
-    dt_dprintk("  - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
-               addr, addr + len, mr_data->p2mt);
-
-    return 0;
-}
-
 /*
  * For a node which describes a discoverable bus (such as a PCI bus)
  * then we may need to perform additional mappings in order to make
@@ -1938,62 +1852,6 @@  static int __init map_device_children(const struct dt_device_node *dev,
     return 0;
 }
 
-/*
- * handle_device_interrupts retrieves the interrupts configuration from
- * a device tree node and maps those interrupts to the target domain.
- *
- * Returns:
- *   < 0 error
- *   0   success
- */
-static int __init handle_device_interrupts(struct domain *d,
-                                           struct dt_device_node *dev,
-                                           bool need_mapping)
-{
-    unsigned int i, nirq;
-    int res;
-    struct dt_raw_irq rirq;
-
-    nirq = dt_number_of_irq(dev);
-
-    /* Give permission and map IRQs */
-    for ( i = 0; i < nirq; i++ )
-    {
-        res = dt_device_get_raw_irq(dev, i, &rirq);
-        if ( res )
-        {
-            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
-                   i, dt_node_full_name(dev));
-            return res;
-        }
-
-        /*
-         * Don't map IRQ that have no physical meaning
-         * ie: IRQ whose controller is not the GIC
-         */
-        if ( rirq.controller != dt_interrupt_controller )
-        {
-            dt_dprintk("irq %u not connected to primary controller. Connected to %s\n",
-                      i, dt_node_full_name(rirq.controller));
-            continue;
-        }
-
-        res = platform_get_irq(dev, i);
-        if ( res < 0 )
-        {
-            printk(XENLOG_ERR "Unable to get irq %u for %s\n",
-                   i, dt_node_full_name(dev));
-            return res;
-        }
-
-        res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
-        if ( res )
-            return res;
-    }
-
-    return 0;
-}
-
 /*
  * For a given device node:
  *  - Give permission to the guest to manage IRQ and MMIO range
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 7a1e1d6798..8a26f1845c 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -134,6 +134,9 @@  void device_tree_get_reg(const __be32 **cell, u32 address_cells,
 u32 device_tree_get_u32(const void *fdt, int node,
                         const char *prop_name, u32 dflt);
 
+int handle_device_interrupts(struct domain *d, struct dt_device_node *dev,
+                             bool need_mapping);
+
 int map_range_to_domain(const struct dt_device_node *dev,
                         u64 addr, u64 len, void *data);
 
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 4aae281e89..f43d66a501 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -1811,12 +1811,12 @@  int dt_count_phandle_with_args(const struct dt_device_node *np,
  * @allnextpp: pointer to ->allnext from last allocated device_node
  * @fpsize: Size of the node path up at the current depth.
  */
-static unsigned long __init unflatten_dt_node(const void *fdt,
-                                              unsigned long mem,
-                                              unsigned long *p,
-                                              struct dt_device_node *dad,
-                                              struct dt_device_node ***allnextpp,
-                                              unsigned long fpsize)
+static unsigned long unflatten_dt_node(const void *fdt,
+                                       unsigned long mem,
+                                       unsigned long *p,
+                                       struct dt_device_node *dad,
+                                       struct dt_device_node ***allnextpp,
+                                       unsigned long fpsize)
 {
     struct dt_device_node *np;
     struct dt_property *pp, **prev_pp = NULL;
@@ -2047,7 +2047,7 @@  static unsigned long __init unflatten_dt_node(const void *fdt,
 }
 
 /**
- * __unflatten_device_tree - create tree of device_nodes from flat blob
+ * unflatten_device_tree - create tree of device_nodes from flat blob
  *
  * unflattens a device-tree, creating the
  * tree of struct device_node. It also fills the "name" and "type"
@@ -2056,8 +2056,8 @@  static unsigned long __init unflatten_dt_node(const void *fdt,
  * @fdt: The fdt to expand
  * @mynodes: The device_node tree created by the call
  */
-static void __init __unflatten_device_tree(const void *fdt,
-                                           struct dt_device_node **mynodes)
+void unflatten_device_tree(const void *fdt,
+                           struct dt_device_node **mynodes)
 {
     unsigned long start, mem, size;
     struct dt_device_node **allnextp = mynodes;
@@ -2179,7 +2179,7 @@  dt_find_interrupt_controller(const struct dt_device_match *matches)
 
 void __init dt_unflatten_host_device_tree(void)
 {
-    __unflatten_device_tree(device_tree_flattened, &dt_host);
+    unflatten_device_tree(device_tree_flattened, &dt_host);
     dt_alias_scan();
 }
 
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index fd6cd00b43..06d7866c10 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -177,6 +177,11 @@  int device_tree_for_each_node(const void *fdt, int node,
  */
 void dt_unflatten_host_device_tree(void);
 
+/*
+ * unflatten any device tree.
+ */
+void unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes);
+
 /**
  * IRQ translation callback
  * TODO: For the moment we assume that we only have ONE