Message ID | 20190930233032.2120-5-sstabellini@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v7b,1/8] xen/arm: introduce handle_device_interrupts | expand |
Hi Stefano, On 10/1/19 12:30 AM, Stefano Stabellini wrote: > Scan the user provided dtb fragment at boot. For each device node, map > memory to guests, and route interrupts and setup the iommu. > > The memory region to remap is specified by the "xen,reg" property. > > The iommu is setup by passing the node of the device to assign on the > host device tree. The path is specified in the device tree fragment as > the "xen,path" string property. > > The interrupts are remapped based on the information from the > corresponding node on the host device tree. Call > handle_device_interrupts to remap interrupts. Interrupts related device > tree properties are copied from the device tree fragment, same as all > the other properties. > > Require both xen,reg and xen,path to be present, unless > xen,force-assign-without-iommu is also set. In that case, tolerate a > missing xen,path, also tolerate iommu setup failure for the passthrough > device. > > Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU > can use the IOMMU if a partial dtb is specified. The patch looks good a few comments below. [...] > xen/arch/arm/domain_build.c | 133 ++++++++++++++++++++++++++++++++++-- > 1 file changed, 129 insertions(+), 4 deletions(-) > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > index 84b65b8f25..47f9bb31df 100644 > --- a/xen/arch/arm/domain_build.c > +++ b/xen/arch/arm/domain_build.c > @@ -1714,6 +1714,88 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo) > } > #endif > > +/* > + * Scan device tree properties for passthrough specific information. > + * Returns < 0 on error > + * 0 on success > + */ > +static int __init handle_passthrough_prop(struct kernel_info *kinfo, > + const struct fdt_property *xen_reg, > + const struct fdt_property *xen_path, > + bool xen_force, > + uint32_t address_cells, uint32_t size_cells) > +{ > + const __be32 *cell; > + unsigned int i, len; > + struct dt_device_node *node; > + int res; > + paddr_t mstart, size, gstart; > + > + /* xen,reg specifies where to map the MMIO region */ > + cell = (const __be32 *)xen_reg->data; > + len = fdt32_to_cpu(xen_reg->len) / > + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); Coding style again. I was kind of expecting you configured your editor properly after the last discussion... [...] > static int __init handle_prop_pfdt(struct kernel_info *kinfo, > const void *pfdt, int nodeoff, > uint32_t address_cells, uint32_t size_cells, > @@ -1721,7 +1803,9 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, > { > void *fdt = kinfo->fdt; > int propoff, nameoff, res; > - const struct fdt_property *prop; > + const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL; > + const char *name; > + bool found, xen_force = false; > > for ( propoff = fdt_first_property_offset(pfdt, nodeoff); > propoff >= 0; > @@ -1730,10 +1814,48 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, > if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) > return -FDT_ERR_INTERNAL; > > + found = false; > nameoff = fdt32_to_cpu(prop->nameoff); > - res = fdt_property(fdt, fdt_string(pfdt, nameoff), > - prop->data, fdt32_to_cpu(prop->len)); > - if ( res ) > + name = fdt_string(pfdt, nameoff); > + > + if ( scan_passthrough_prop ) > + { > + if ( dt_prop_cmp("xen,reg", name) == 0 ) > + { > + xen_reg = prop; > + found = true; > + } > + else if ( dt_prop_cmp("xen,path", name) == 0 ) > + { > + xen_path = prop; > + found = true; > + } > + else if ( dt_prop_cmp("xen,force-assign-without-iommu", > + name) == 0 ) Coding style. > + { > + xen_force = true; > + found = true; > + } > + } > + > + /* Copy all other properties */ It is not entirely clear what you mean by "other" here. > + if ( !found ) > + { > + res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len)); > + if ( res ) > + return res; > + } > + } > + > + /* > + * Only handle passthrough properties if both xen,reg and xen,path > + * are present, or if xen,force-assign-without-iommu is specified. > + */ > + if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) > + { > + res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, > + address_cells, size_cells); > + if ( res < 0 ) > return res; > } I would print an error so the user knows what happen here. > > @@ -2291,6 +2413,9 @@ void __init create_domUs(void) > panic("Missing property 'cpus' for domain %s\n", > dt_node_name(node)); > > + if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") ) > + d_cfg.flags |= XEN_DOMCTL_CDF_iommu; > + > d = domain_create(++max_init_domid, &d_cfg, false); > if ( IS_ERR(d) ) > panic("Error creating domain %s\n", dt_node_name(node)); > Cheers,
On Wed, 2 Oct 2019, Julien Grall wrote: > Hi Stefano, > > On 10/1/19 12:30 AM, Stefano Stabellini wrote: > > Scan the user provided dtb fragment at boot. For each device node, map > > memory to guests, and route interrupts and setup the iommu. > > > > The memory region to remap is specified by the "xen,reg" property. > > > > The iommu is setup by passing the node of the device to assign on the > > host device tree. The path is specified in the device tree fragment as > > the "xen,path" string property. > > > > The interrupts are remapped based on the information from the > > corresponding node on the host device tree. Call > > handle_device_interrupts to remap interrupts. Interrupts related device > > tree properties are copied from the device tree fragment, same as all > > the other properties. > > > > Require both xen,reg and xen,path to be present, unless > > xen,force-assign-without-iommu is also set. In that case, tolerate a > > missing xen,path, also tolerate iommu setup failure for the passthrough > > device. > > > > Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU > > can use the IOMMU if a partial dtb is specified. > > The patch looks good a few comments below. Thanks > [...] > > > xen/arch/arm/domain_build.c | 133 ++++++++++++++++++++++++++++++++++-- > > 1 file changed, 129 insertions(+), 4 deletions(-) > > > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > > index 84b65b8f25..47f9bb31df 100644 > > --- a/xen/arch/arm/domain_build.c > > +++ b/xen/arch/arm/domain_build.c > > @@ -1714,6 +1714,88 @@ static int __init make_vpl011_uart_node(struct > > kernel_info *kinfo) > > } > > #endif > > +/* > > + * Scan device tree properties for passthrough specific information. > > + * Returns < 0 on error > > + * 0 on success > > + */ > > +static int __init handle_passthrough_prop(struct kernel_info *kinfo, > > + const struct fdt_property > > *xen_reg, > > + const struct fdt_property > > *xen_path, > > + bool xen_force, > > + uint32_t address_cells, uint32_t > > size_cells) > > +{ > > + const __be32 *cell; > > + unsigned int i, len; > > + struct dt_device_node *node; > > + int res; > > + paddr_t mstart, size, gstart; > > + > > + /* xen,reg specifies where to map the MMIO region */ > > + cell = (const __be32 *)xen_reg->data; > > + len = fdt32_to_cpu(xen_reg->len) / > > + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); > > Coding style again. I was kind of expecting you configured your editor > properly after the last discussion... Actually I fail to see the coding style issue on this one. Is it still an alignment issue you are talking about? > > > static int __init handle_prop_pfdt(struct kernel_info *kinfo, > > const void *pfdt, int nodeoff, > > uint32_t address_cells, uint32_t > > size_cells, > > @@ -1721,7 +1803,9 @@ static int __init handle_prop_pfdt(struct kernel_info > > *kinfo, > > { > > void *fdt = kinfo->fdt; > > int propoff, nameoff, res; > > - const struct fdt_property *prop; > > + const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL; > > + const char *name; > > + bool found, xen_force = false; > > for ( propoff = fdt_first_property_offset(pfdt, nodeoff); > > propoff >= 0; > > @@ -1730,10 +1814,48 @@ static int __init handle_prop_pfdt(struct > > kernel_info *kinfo, > > if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) > > return -FDT_ERR_INTERNAL; > > + found = false; > > nameoff = fdt32_to_cpu(prop->nameoff); > > - res = fdt_property(fdt, fdt_string(pfdt, nameoff), > > - prop->data, fdt32_to_cpu(prop->len)); > > - if ( res ) > > + name = fdt_string(pfdt, nameoff); > > + > > + if ( scan_passthrough_prop ) > > + { > > + if ( dt_prop_cmp("xen,reg", name) == 0 ) > > + { > > + xen_reg = prop; > > + found = true; > > + } > > + else if ( dt_prop_cmp("xen,path", name) == 0 ) > > + { > > + xen_path = prop; > > + found = true; > > + } > > + else if ( dt_prop_cmp("xen,force-assign-without-iommu", > > + name) == 0 ) > > Coding style. Ah, this one I can see, it should be: else if ( dt_prop_cmp("xen,force-assign-without-iommu", name) == 0 ) > > + { > > + xen_force = true; > > + found = true; > > + } > > + } > > + > > + /* Copy all other properties */ > > It is not entirely clear what you mean by "other" here. I can spell it out. It meant other than the one above: xen,reg xen,path and xen,force-assign-without-iommu. I'll reword it to: Copy properties other than the one above. > > + if ( !found ) > > + { > > + res = fdt_property(fdt, name, prop->data, > > fdt32_to_cpu(prop->len)); > > + if ( res ) > > + return res; > > + } > > + } > > + > > + /* > > + * Only handle passthrough properties if both xen,reg and xen,path > > + * are present, or if xen,force-assign-without-iommu is specified. > > + */ > > + if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) > > + { > > + res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, > > + address_cells, size_cells); > > + if ( res < 0 ) > > return res; > > } > > I would print an error so the user knows what happen here. All right, I'll add: printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d); More specific information about the type of failure is already printed by handle_passthrough_prop. > > @@ -2291,6 +2413,9 @@ void __init create_domUs(void) > > panic("Missing property 'cpus' for domain %s\n", > > dt_node_name(node)); > > + if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") > > ) > > + d_cfg.flags |= XEN_DOMCTL_CDF_iommu; > > + > > d = domain_create(++max_init_domid, &d_cfg, false); > > if ( IS_ERR(d) ) > > panic("Error creating domain %s\n", dt_node_name(node)); > > > > Cheers, > > -- > Julien Grall >
On Wed, 2 Oct 2019, Stefano Stabellini wrote: > On Wed, 2 Oct 2019, Julien Grall wrote: > > Hi Stefano, > > > > On 10/1/19 12:30 AM, Stefano Stabellini wrote: > > > Scan the user provided dtb fragment at boot. For each device node, map > > > memory to guests, and route interrupts and setup the iommu. > > > > > > The memory region to remap is specified by the "xen,reg" property. > > > > > > The iommu is setup by passing the node of the device to assign on the > > > host device tree. The path is specified in the device tree fragment as > > > the "xen,path" string property. > > > > > > The interrupts are remapped based on the information from the > > > corresponding node on the host device tree. Call > > > handle_device_interrupts to remap interrupts. Interrupts related device > > > tree properties are copied from the device tree fragment, same as all > > > the other properties. > > > > > > Require both xen,reg and xen,path to be present, unless > > > xen,force-assign-without-iommu is also set. In that case, tolerate a > > > missing xen,path, also tolerate iommu setup failure for the passthrough > > > device. > > > > > > Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU > > > can use the IOMMU if a partial dtb is specified. > > > > The patch looks good a few comments below. > > Thanks > > > > [...] > > > > > xen/arch/arm/domain_build.c | 133 ++++++++++++++++++++++++++++++++++-- > > > 1 file changed, 129 insertions(+), 4 deletions(-) > > > > > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > > > index 84b65b8f25..47f9bb31df 100644 > > > --- a/xen/arch/arm/domain_build.c > > > +++ b/xen/arch/arm/domain_build.c > > > @@ -1714,6 +1714,88 @@ static int __init make_vpl011_uart_node(struct > > > kernel_info *kinfo) > > > } > > > #endif > > > +/* > > > + * Scan device tree properties for passthrough specific information. > > > + * Returns < 0 on error > > > + * 0 on success > > > + */ > > > +static int __init handle_passthrough_prop(struct kernel_info *kinfo, > > > + const struct fdt_property > > > *xen_reg, > > > + const struct fdt_property > > > *xen_path, > > > + bool xen_force, > > > + uint32_t address_cells, uint32_t > > > size_cells) > > > +{ > > > + const __be32 *cell; > > > + unsigned int i, len; > > > + struct dt_device_node *node; > > > + int res; > > > + paddr_t mstart, size, gstart; > > > + > > > + /* xen,reg specifies where to map the MMIO region */ > > > + cell = (const __be32 *)xen_reg->data; > > > + len = fdt32_to_cpu(xen_reg->len) / > > > + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); > > > > Coding style again. I was kind of expecting you configured your editor > > properly after the last discussion... > > Actually I fail to see the coding style issue on this one. Is it still > an alignment issue you are talking about? Is it because you would like it to look like this? len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) * sizeof(uint32_t));
On Wed, 2 Oct 2019, Stefano Stabellini wrote: > > > Coding style again. I was kind of expecting you configured your editor > > > properly after the last discussion... > > > > Actually I fail to see the coding style issue on this one. Is it still > > an alignment issue you are talking about? > > Is it because you would like it to look like this? > > len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) * > sizeof(uint32_t)); I went with this, although I wasn't sure it is what you meant. Sorry about inflating the version number of the series, but I thought it would be good to get it out if the way, especially due to our timezone difference. If this is the only issue left and I didn't get it right, maybe you could also fix it on commit...
Hi Stefano, On 02/10/2019 23:48, Stefano Stabellini wrote: > On Wed, 2 Oct 2019, Stefano Stabellini wrote: >> On Wed, 2 Oct 2019, Julien Grall wrote: >>> Hi Stefano, >>> >>> On 10/1/19 12:30 AM, Stefano Stabellini wrote: >>>> Scan the user provided dtb fragment at boot. For each device node, map >>>> memory to guests, and route interrupts and setup the iommu. >>>> >>>> The memory region to remap is specified by the "xen,reg" property. >>>> >>>> The iommu is setup by passing the node of the device to assign on the >>>> host device tree. The path is specified in the device tree fragment as >>>> the "xen,path" string property. >>>> >>>> The interrupts are remapped based on the information from the >>>> corresponding node on the host device tree. Call >>>> handle_device_interrupts to remap interrupts. Interrupts related device >>>> tree properties are copied from the device tree fragment, same as all >>>> the other properties. >>>> >>>> Require both xen,reg and xen,path to be present, unless >>>> xen,force-assign-without-iommu is also set. In that case, tolerate a >>>> missing xen,path, also tolerate iommu setup failure for the passthrough >>>> device. >>>> >>>> Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU >>>> can use the IOMMU if a partial dtb is specified. >>> >>> The patch looks good a few comments below. >> >> Thanks >> >> >>> [...] >>> >>>> xen/arch/arm/domain_build.c | 133 ++++++++++++++++++++++++++++++++++-- >>>> 1 file changed, 129 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c >>>> index 84b65b8f25..47f9bb31df 100644 >>>> --- a/xen/arch/arm/domain_build.c >>>> +++ b/xen/arch/arm/domain_build.c >>>> @@ -1714,6 +1714,88 @@ static int __init make_vpl011_uart_node(struct >>>> kernel_info *kinfo) >>>> } >>>> #endif >>>> +/* >>>> + * Scan device tree properties for passthrough specific information. >>>> + * Returns < 0 on error >>>> + * 0 on success >>>> + */ >>>> +static int __init handle_passthrough_prop(struct kernel_info *kinfo, >>>> + const struct fdt_property >>>> *xen_reg, >>>> + const struct fdt_property >>>> *xen_path, >>>> + bool xen_force, >>>> + uint32_t address_cells, uint32_t >>>> size_cells) >>>> +{ >>>> + const __be32 *cell; >>>> + unsigned int i, len; >>>> + struct dt_device_node *node; >>>> + int res; >>>> + paddr_t mstart, size, gstart; >>>> + >>>> + /* xen,reg specifies where to map the MMIO region */ >>>> + cell = (const __be32 *)xen_reg->data; >>>> + len = fdt32_to_cpu(xen_reg->len) / >>>> + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); >>> >>> Coding style again. I was kind of expecting you configured your editor >>> properly after the last discussion... >> >> Actually I fail to see the coding style issue on this one. Is it still >> an alignment issue you are talking about? > > Is it because you would like it to look like this? > > len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) * > sizeof(uint32_t)); No, I completely misread the line and thought the division was part of the fdt32_to_cpu argument. Apologies for the noise :(. This is fixable on commit. Cheers,
Hi Stefano, On 02/10/2019 23:43, Stefano Stabellini wrote: > On Wed, 2 Oct 2019, Julien Grall wrote: >>> + if ( !found ) >>> + { >>> + res = fdt_property(fdt, name, prop->data, >>> fdt32_to_cpu(prop->len)); >>> + if ( res ) >>> + return res; >>> + } >>> + } >>> + >>> + /* >>> + * Only handle passthrough properties if both xen,reg and xen,path >>> + * are present, or if xen,force-assign-without-iommu is specified. >>> + */ >>> + if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) >>> + { >>> + res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, >>> + address_cells, size_cells); >>> + if ( res < 0 ) >>> return res; >>> } >> >> I would print an error so the user knows what happen here. > > All right, I'll add: > > printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d); > > More specific information about the type of failure is already printed > by handle_passthrough_prop. I am less concerned about the error when handle_passthrough_prop. What I am concerned about if the fact you will ignore xen,path if xen,reg is not present. We should at least warn the user if not returning an error. Cheers,
On 01.10.19 02:30, Stefano Stabellini wrote: Hi Stefano > + > + /* If xen_force, we ignore IOMMU failures. */ > + res = iommu_add_dt_device(node); > + if ( res < 0 ) > + return xen_force ? 0 : -EINVAL; Any specific reason to return -EINVAL if not forcing (why don't return res)? > + > + res = iommu_assign_dt_device(kinfo->d, node); > + return res; could be optimized: return iommu_assign_dt_device(kinfo->d, node);
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 84b65b8f25..47f9bb31df 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -1714,6 +1714,88 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo) } #endif +/* + * Scan device tree properties for passthrough specific information. + * Returns < 0 on error + * 0 on success + */ +static int __init handle_passthrough_prop(struct kernel_info *kinfo, + const struct fdt_property *xen_reg, + const struct fdt_property *xen_path, + bool xen_force, + uint32_t address_cells, uint32_t size_cells) +{ + const __be32 *cell; + unsigned int i, len; + struct dt_device_node *node; + int res; + paddr_t mstart, size, gstart; + + /* xen,reg specifies where to map the MMIO region */ + cell = (const __be32 *)xen_reg->data; + len = fdt32_to_cpu(xen_reg->len) / + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); + + for ( i = 0; i < len; i++ ) + { + device_tree_get_reg(&cell, address_cells, size_cells, + &mstart, &size); + gstart = dt_next_cell(address_cells, &cell); + + if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK ) + { + printk(XENLOG_ERR + "DomU passthrough config has not page aligned addresses/sizes\n"); + return -EINVAL; + } + + res = map_regions_p2mt(kinfo->d, + gaddr_to_gfn(gstart), + PFN_DOWN(size), + maddr_to_mfn(mstart), + p2m_mmio_direct_dev); + if ( res < 0 ) + { + printk(XENLOG_ERR + "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n", + mstart, gstart); + return -EFAULT; + } + } + + /* + * If xen_force, we let the user assign a MMIO region with no + * associated path. + */ + if ( xen_path == NULL ) + return xen_force ? 0 : -EINVAL; + + /* + * xen,path specifies the corresponding node in the host DT. + * Both interrupt mappings and IOMMU settings are based on it, + * as they are done based on the corresponding host DT node. + */ + node = dt_find_node_by_path(xen_path->data); + if ( node == NULL ) + { + printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n", + (char *)xen_path->data); + return -EINVAL; + } + + res = handle_device_interrupts(kinfo->d, node, true); + if ( res < 0 ) + return res; + + /* If xen_force, we ignore IOMMU failures. */ + res = iommu_add_dt_device(node); + if ( res < 0 ) + return xen_force ? 0 : -EINVAL; + + res = iommu_assign_dt_device(kinfo->d, node); + return res; +} + static int __init handle_prop_pfdt(struct kernel_info *kinfo, const void *pfdt, int nodeoff, uint32_t address_cells, uint32_t size_cells, @@ -1721,7 +1803,9 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, { void *fdt = kinfo->fdt; int propoff, nameoff, res; - const struct fdt_property *prop; + const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL; + const char *name; + bool found, xen_force = false; for ( propoff = fdt_first_property_offset(pfdt, nodeoff); propoff >= 0; @@ -1730,10 +1814,48 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) return -FDT_ERR_INTERNAL; + found = false; nameoff = fdt32_to_cpu(prop->nameoff); - res = fdt_property(fdt, fdt_string(pfdt, nameoff), - prop->data, fdt32_to_cpu(prop->len)); - if ( res ) + name = fdt_string(pfdt, nameoff); + + if ( scan_passthrough_prop ) + { + if ( dt_prop_cmp("xen,reg", name) == 0 ) + { + xen_reg = prop; + found = true; + } + else if ( dt_prop_cmp("xen,path", name) == 0 ) + { + xen_path = prop; + found = true; + } + else if ( dt_prop_cmp("xen,force-assign-without-iommu", + name) == 0 ) + { + xen_force = true; + found = true; + } + } + + /* Copy all other properties */ + if ( !found ) + { + res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len)); + if ( res ) + return res; + } + } + + /* + * Only handle passthrough properties if both xen,reg and xen,path + * are present, or if xen,force-assign-without-iommu is specified. + */ + if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) + { + res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, + address_cells, size_cells); + if ( res < 0 ) return res; } @@ -2291,6 +2413,9 @@ void __init create_domUs(void) panic("Missing property 'cpus' for domain %s\n", dt_node_name(node)); + if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") ) + d_cfg.flags |= XEN_DOMCTL_CDF_iommu; + d = domain_create(++max_init_domid, &d_cfg, false); if ( IS_ERR(d) ) panic("Error creating domain %s\n", dt_node_name(node));
Scan the user provided dtb fragment at boot. For each device node, map memory to guests, and route interrupts and setup the iommu. The memory region to remap is specified by the "xen,reg" property. The iommu is setup by passing the node of the device to assign on the host device tree. The path is specified in the device tree fragment as the "xen,path" string property. The interrupts are remapped based on the information from the corresponding node on the host device tree. Call handle_device_interrupts to remap interrupts. Interrupts related device tree properties are copied from the device tree fragment, same as all the other properties. Require both xen,reg and xen,path to be present, unless xen,force-assign-without-iommu is also set. In that case, tolerate a missing xen,path, also tolerate iommu setup failure for the passthrough device. Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU can use the IOMMU if a partial dtb is specified. Signed-off-by: Stefano Stabellini <stefanos@xilinx.com> --- Changes in v7: - improve in-code comment - code style - return 1 instead of ENOENT - introduce "xen,force-assign-without-iommu" - require both "xen,reg" and "xen,path" unless "xen,force-assign-without-iommu" Changes in v6: - turn dprintks into printks - return error on page alignment check failure - set XEN_DOMCTL_CDF_iommu if partial dtb is specified Changes in v5: - use local variable for name - use map_regions_p2mt - add warning for not page aligned addresses/sizes - introduce handle_passthrough_prop Changes in v4: - use unsigned - improve commit message - code style - use dt_prop_cmp - use device_tree_get_reg - don't copy over xen,reg and xen,path - don't create special interrupt properties for domU: copy them from the fragment - in-code comment Changes in v3: - improve commit message - remove superfluous cast - merge code with the copy code - add interrup-parent - demove depth > 2 check - reuse code from handle_device_interrupts - copy interrupts from host dt Changes in v2: - rename "path" to "xen,path" - grammar fix - use gaddr_to_gfn and maddr_to_mfn - remove depth <= 2 limitation in scanning the dtb fragment - introduce and parse xen,reg - code style - support more than one interrupt per device - specify only the GIC is supported --- xen/arch/arm/domain_build.c | 133 ++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 4 deletions(-)