of_iommu: add support for "iommu-ranges"
Subsystems (7)
v6 cover of_iommu: add support for "iommu-ranges"
The series adds support for recently introduced property "iommu-ranges". It adds the required checks to error out for cases which are not following the schema definition.
Iommu-ranges was defined in schema with this PR
https://github.com/devicetree-org/dt-schema/pull/207
The patch series is being posted as revision v6, since the patches were initially part of the media series [1]. The patches are moved out to get review comments from iommu reviewers, which was otherwise looking as a media seris. Happy to move this back to media series if anyone have any concerns.
[1]
https://lore.kernel.org/linux-media/20260926-vpu_iommu_iova_handling-v5-0-0322ca5dc10c@oss.qualcomm.com/
---
Changes in v6:
- Addressed sashiko comments.
- Addressed comment from Bryan.
- Link to v5: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-4-0322ca5dc10c@oss.qualcomm.com/
---
Vikash Garodia (2):
iommu: use resource_size_t for reserved region length
of: Add support for "iommu-ranges" on a device node
drivers/iommu/amd/iommu.c | 2 +- drivers/iommu/intel/iommu.c | 2 +- drivers/iommu/iommu.c | 2 +- drivers/iommu/of_iommu.c | 138 +++++++++++++++++++++++++++++++++++++++---- drivers/iommu/virtio-iommu.c | 2 +- drivers/of/address.c | 2 +- include/linux/iommu.h | 4 +- include/linux/of_address.h | 2 +- 8 files changed, 135 insertions(+), 19 deletions(-)
---
base-commit: 2637bdec0535a2044cd830eba9a79363651d9043
change-id: 20261103-add_iommu_ranges-549cf3fb0867
Best regards,
Signature · 1 line
Vikash Garodia <[email protected]>
PATCH v6 1/2 iommu: use resource_size_t for reserved region length
On 32-bit systems with LPAE, physical addresses are 64-bit. A reserved region can be larger than 4GiB, but its length is stored as size_t, which is only 32-bit there. The length gets truncated.
Use resource_size_t for the length so it matches the width of phys_addr_t and holds the full size of the region.
--- drivers/iommu/amd/iommu.c | 2 +- drivers/iommu/intel/iommu.c | 2 +- drivers/iommu/iommu.c | 2 +- drivers/iommu/of_iommu.c | 4 ++-- drivers/iommu/virtio-iommu.c | 2 +- drivers/of/address.c | 2 +- include/linux/iommu.h | 4 ++-- include/linux/of_address.h | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-)
drivers/iommu/amd/iommu.c +1 -1
@@ -3327,7 +3327,7 @@ static void amd_iommu_get_resv_regions(struct device *dev,list_for_each_entry (entry, &pci_seg->unity_map, list) {int type, prot =0 ; -size_t length; +resource_size_t length;if (devid < entry->devid_start || devid > entry->devid_end)continue ;
drivers/iommu/intel/iommu.c +1 -1
@@ -3535,7 +3535,7 @@ static void intel_iommu_get_resv_regions(struct device *device, i, i_dev) {struct iommu_resv_region *resv;enum iommu_resv_type type; -size_t length; +resource_size_t length;if (i_dev != device && !is_downstream_to_pci_bridge (device, i_dev))
drivers/iommu/iommu.c +1 -1
@@ -3010,7 +3010,7 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)EXPORT_SYMBOL (iommu_put_resv_regions);struct iommu_resv_region *iommu_alloc_resv_region (phys_addr_t start, -size_t length,int prot, +resource_size_t length,int prot,enum iommu_resv_type type,gfp_t gfp) {
drivers/iommu/of_iommu.c +2 -2
@@ -170,7 +170,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,static enum iommu_resv_type __maybe_unused iommu_resv_region_get_type (struct device *dev,struct resource *phys, -phys_addr_t start,size_t length) +phys_addr_t start,resource_size_t length) {phys_addr_t end = start + length -1 ;
@@ -246,7 +246,7 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list)struct iommu_resv_region *region;enum iommu_resv_type type;phys_addr_t iova; -size_t length; +resource_size_t length;if (of_dma_is_coherent (dev->of_node)) prot |=IOMMU_CACHE ;
drivers/iommu/virtio-iommu.c +1 -1
@@ -483,7 +483,7 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev, struct virtio_iommu_probe_resv_mem *mem, size_t len) { - size_t size; +resource_size_t size;u64 start64, end64;phys_addr_t start, end;struct iommu_resv_region *region =NULL , *next;
drivers/of/address.c +1 -1
@@ -655,7 +655,7 @@ EXPORT_SYMBOL(of_translate_dma_address);* Returns a pointer to the cell immediately following the translated DMA region. */ const __be32 *of_translate_dma_region (struct device_node *dev,const __be32 *prop, -phys_addr_t *start,size_t *length) +phys_addr_t *start,resource_size_t *length) { struct device_node *parent __free(device_node) = __of_get_dma_parent(dev);u64 address, size;
include/linux/iommu.h +2 -2
@@ -306,7 +306,7 @@ enum iommu_resv_type {struct iommu_resv_region {struct list_head list;phys_addr_t start; -size_t length; +resource_size_t length;int prot;enum iommu_resv_type type;void (*free)(struct device *dev,struct iommu_resv_region *region);
@@ -968,7 +968,7 @@ extern void iommu_set_default_passthrough(bool cmd_line);extern void iommu_set_default_translated (bool cmd_line);extern bool iommu_default_passthrough (void );extern struct iommu_resv_region * -iommu_alloc_resv_region (phys_addr_t start,size_t length,int prot, +iommu_alloc_resv_region (phys_addr_t start,resource_size_t length,int prot,enum iommu_resv_type type,gfp_t gfp);extern int iommu_get_group_resv_regions (struct iommu_group *group,struct list_head *head);
include/linux/of_address.h +1 -1
@@ -56,7 +56,7 @@ static inline int of_range_count(const struct of_range_parser *parser)extern u64 of_translate_dma_address (struct device_node *dev,const __be32 *in_addr);extern const __be32 *of_translate_dma_region (struct device_node *dev,const __be32 *addr, -phys_addr_t *start,size_t *length); +phys_addr_t *start,resource_size_t *length);#ifdef CONFIG_OF_ADDRESS extern u64 of_translate_address (struct device_node *np,const __be32 *addr);
Signature · 1 line
2.34.1
[email protected]
AI reviewRe: [PATCH v6 1/2] iommu: use resource_size_t for reserved region length
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] vfio/type1: truncation of region->length in vfio_find_dma() on 32-bit LPAE --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] vfio/type1: truncation of region->length in vfio_find_dma() on 32-bit LPAE --
commit 0e9e6ab1dd5582c6a157191dbe1e262f13c108a9
Author: Vikash Garodia <[email protected]>
iommu: use resource_size_t for reserved region length
This commit widens struct iommu_resv_region.length and related helper parameters from size_t to resource_size_t so that reserved regions of 4GiB or larger are not truncated on 32-bit systems with LPAE.
[ ... ]
include/linux/iommu.h enum iommu_resv_type { · line 309
Quoted 10 lines
include/linux/iommu.h +1
-1@@ -306,7 +306,7 @@ enum iommu_resv_type {struct iommu_resv_region {struct list_head list;phys_addr_t start; -size_t length; +resource_size_t length;
[Severity: Medium]
Now that region->length can hold values of 4GiB or larger on 32-bit LPAE systems, could it still get truncated when passed to vfio_find_dma() via vfio_iommu_type1_attach_group() -> vfio_iommu_resv_conflict()?
In drivers/vfio/vfio_iommu_type1.c, vfio_iommu_resv_conflict() passes region->length directly to vfio_find_dma():
drivers/vfio/vfio_iommu_type1.c:vfio_iommu_resv_conflict() {
list_for_each_entry(region, resv_regions, list) {
if (region->type == IOMMU_RESV_DIRECT_RELAXABLE)
continue;
if (vfio_find_dma(iommu, region->start, region->length))
return true;
}
}However, vfio_find_dma() still takes size as a 32-bit size_t on 32-bit LPAE systems:
drivers/vfio/vfio_iommu_type1.c:vfio_find_dma() {
static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
dma_addr_t start, size_t size)
{
struct rb_node *node = iommu->dma_list.rb_node;
WARN_ON(!size);
while (node) {
struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
if (start + size - 1 < dma->iova)...
}
If an IOMMU group with a reserved region of 4GiB or larger is attached to a VFIO container on a 32-bit LPAE system, region->length will be truncated to 32 bits. When region->length is a multiple of 4GiB, size becomes 0, triggering WARN_ON(!size) and miscomputing start + size - 1; for other sizes >= 4GiB, the upper portion of the reserved region will not be checked for conflicting DMA mappings.
Should the size parameter of vfio_find_dma() (or a dedicated range helper) also be widened to resource_size_t or dma_addr_t?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
PATCH v6 2/2 of: Add support for "iommu-ranges" on a device node
In reply to Vikash GarodiaReserving an IOVA address using "iommu-addresses" requires it to be placed in the reserved-memory node. But when "iommu-addresses" is the only property being described and there is no backing "reg" (i.e. no actual reserved system memory), it does not really belong under /reserved-memory. A device IOVA range is specific to its own address space, and does not describe the system physical memory to make it qualify under reserved-memory. Given this, place "iommu-addresses" inside reserved-memory only when it is paired with a "reg", otherwise, define it within the device own node. It was discussed here:
https://lore.kernel.org/all/[email protected]
Existing "iommu-addresses" property expects a phandle, which does not make sense when the property is defined within the device node. "iommu-ranges" was introduced to specify the device specific IOVA ranges when there is no backing "reg".
--- drivers/iommu/of_iommu.c | 134 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 9 deletions(-)
drivers/iommu/of_iommu.c +125 -9
@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,if (start == phys->start && end == phys->end)return IOMMU_RESV_DIRECT ; -dev_warn (dev,"treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n" , phys, - &start, &end); +dev_err (dev,"non-direct mapping [%pr] -> [%pap-%pap] is not supported\n" , phys, + &start, &end);return IOMMU_RESV_RESERVED ; } +/** +* of_iommu_derive_resv_regions - derive reserved regions which +* are outside of iommu-ranges +* @dev: device for which to get reserved regions +* @list: reserved region list +* +* A device can describe its own usable IOVA ranges directly on its node +* via "iommu-ranges". Everything not under those ranges is derived +* as a reserved region so the IOMMU allocator won't use it. Entries may +* appear in any order in the property. +*/ +#if IS_ENABLED (CONFIG_OF_ADDRESS ) +static void of_iommu_derive_resv_regions (struct device *dev,struct list_head *list) +{ +struct of_iommu_range { +struct list_head node; +phys_addr_t start; +phys_addr_t end; + } *pos, *new, *next_range; +int size, prot =IOMMU_READ |IOMMU_WRITE ; +struct iommu_resv_region *region; +const __be32 *maps, *end; +struct list_head *prev; +phys_addr_t next =0 ; +LIST_HEAD (ranges); + + maps =of_get_property (dev->of_node,"iommu-ranges" , &size); +if (!maps) +return ; + + end = maps + size /sizeof (__be32); + +while (maps < end) { +phys_addr_t iova, iova_end; +resource_size_t length; + + maps =of_translate_dma_region (dev->of_node, maps, &iova, &length); +if (!maps) { +dev_err (dev,"%pOF: failed to parse iommu-ranges\n" , + dev->of_node); +break ; + } + +if (!length) +continue ; + + iova_end = iova + length -1 ; + +if (iova_end < iova) { +dev_err (dev,"%pOF: iommu-ranges overflows address space\n" , + dev->of_node); +continue ; + } + + prev = &ranges; +list_for_each_entry (pos, &ranges, node) { +if (pos->start > iova) +break ; + prev = &pos->node; + } + + new =kmalloc_obj (*new); +if (!new) +continue ; + + new->start = iova; + new->end = iova_end; +list_add (&new->node, prev); + } + +if (list_empty (&ranges)) +return ; + +if (of_dma_is_coherent (dev->of_node)) + prot |=IOMMU_CACHE ; + +list_for_each_entry_safe (pos, next_range, &ranges, node) { +if (pos->start > next) { + region =iommu_alloc_resv_region (next, pos->start - next, prot, +IOMMU_RESV_RESERVED ,GFP_KERNEL ); +if (region) +list_add_tail (®ion->list, list); + } + +if (pos->end ==PHYS_ADDR_MAX ) + goto exit; + +if (pos->end >= next) + next = pos->end +1 ; + +list_del (&pos->node); +kfree (pos); + } + + region =iommu_alloc_resv_region (next,PHYS_ADDR_MAX - next +1 , + prot,IOMMU_RESV_RESERVED ,GFP_KERNEL ); +if (region) +list_add_tail (®ion->list, list); + +exit: +list_for_each_entry_safe (pos, next_range, &ranges, node) { +list_del (&pos->node); +kfree (pos); + } +} +#endif +/** * of_iommu_get_resv_regions - reserved region driver helper for device tree * @dev: device for which to get reserved regions
@@ -214,10 +321,14 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list)memset (&phys,0 ,sizeof (phys)); + maps =of_get_property (it.node,"iommu-addresses" , &size); +if (!maps) +continue ; +/* -* The "reg" property is optional and can be omitted by reserved-memory regions -* that represent reservations in the IOVA space, which are regions that should -* not be mapped. +* "iommu-addresses" must be used in combination with a "reg" that provides +* the physical address and size of this memory region, for an identity 1:1 +* IOVA mapping to that physical memory. */ if (of_property_present (it.node,"reg" )) { err =of_address_to_resource (it.node,0 , &phys);
@@ -226,11 +337,11 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) it.node, err);continue ; } - } - - maps =of_get_property (it.node,"iommu-addresses" , &size); -if (!maps) + }else { +dev_err (dev,"%pOF: iommu-addresses requires a reg property\n" , + it.node);continue ; + } end = maps + size /sizeof (__be32);
@@ -258,6 +369,9 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) } type =iommu_resv_region_get_type (dev, &phys, iova, length); +if (type !=IOMMU_RESV_DIRECT ) +continue ; + region =iommu_alloc_resv_region (iova, length, prot, type,GFP_KERNEL );if (region)
@@ -265,6 +379,8 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) } } } + +of_iommu_derive_resv_regions (dev, list);#endif }EXPORT_SYMBOL (of_iommu_get_resv_regions);
Signature · 1 line
2.34.1
[email protected]
AI reviewRe: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Critical] iommu: of_iommu_derive_resv_regions() corrupts iovad->anchor on 32-bit LPAE - [High] iommu…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] iommu: of_iommu_derive_resv_regions() corrupts iovad->anchor on 32-bit LPAE
- [High] iommu: of_iommu_derive_resv_regions() PHYS_ADDR_MAX end overflows merge --
commit 138d9a14b5fdb2f77facac6b1fa8a670c0862071
Author: Vikash Garodia <[email protected]>
of: Add support for "iommu-ranges" on a device node
This commit adds support for parsing the "iommu-ranges" device tree property on a device node to derive reserved IOVA regions outside the usable ranges, and restricts "iommu-addresses" on reserved-memory nodes to identity mappings backed by a "reg" property.
Quoted 5 lines
drivers/iommu/of_iommu.c +0
-0@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,
[ ... ]
Quoted 2 lines
drivers/iommu/of_iommu.c +2
-0+static void of_iommu_derive_resv_regions (struct device *dev,struct list_head *list) +{
[ ... ]
Quoted 12 lines
drivers/iommu/of_iommu.c +12
-0+list_for_each_entry_safe (pos, next_range, &ranges, node) { +if (pos->start > next) { + region =iommu_alloc_resv_region (next, pos->start - next, prot, +IOMMU_RESV_RESERVED ,GFP_KERNEL ); +if (region) +list_add_tail (®ion->list, list); + } + +if (pos->end ==PHYS_ADDR_MAX ) + goto exit; + +if (pos->end >= next)
drivers/iommu/of_iommu.c iommu_resv_region_get_type(struct device *dev, · line 290
Quoted 10 lines
drivers/iommu/of_iommu.c +10
-0+ next = pos->end +1 ; + +list_del (&pos->node); +kfree (pos); + } + + region =iommu_alloc_resv_region (next,PHYS_ADDR_MAX - next +1 , + prot,IOMMU_RESV_RESERVED ,GFP_KERNEL ); +if (region) +list_add_tail (®ion->list, list);
[Severity: Critical]
On 32-bit systems with 64-bit phys_addr_t and dma_addr_t (such as ARM LPAE with CONFIG_PHYS_ADDR_T_64BIT=y), can reserving this trailing region up to PHYS_ADDR_MAX corrupt iovad->anchor and lead to slab corruption when the IOVA domain is freed?
In of_iommu_derive_resv_regions(), the trailing reserved region is allocated with start = next and length = PHYS_ADDR_MAX - next + 1, giving it an inclusive end address of 0xffffffffffffffffULL.
When a device attaches to a DMA domain, iova_reserve_iommu_regions() in drivers/iommu/dma-iommu.c reserves each region:
lo = iova_pfn(iovad, region->start);
hi = iova_pfn(iovad, region->start + region->length - 1);
reserve_iova(iovad, lo, hi);Because iova_pfn() returns an unsigned long (32-bit on 32-bit architectures), shifting 0xffffffffffffffffULL right by iova_shift(iovad) and truncating to unsigned long yields hi = 0xffffffffUL, which is IOVA_ANCHOR (~0UL).
In drivers/iommu/iova.c:reserve_iova(), the upper-bound check compares 32-bit unsigned long values against (ULLONG_MAX >> iova_shift(iovad)), which does not trigger on 32-bit LPAE. The rbtree walk then finds &iovad->anchor (where pfn_lo = pfn_hi = IOVA_ANCHOR):
for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
iova = to_iova(node);
__adjust_overlap_range(iova, &pfn_lo, &pfn_hi);__adjust_overlap_range() overwrites iovad->anchor.pfn_lo with lo. Later, when put_iova_domain() tears down the domain and calls free_iova_mem(&iovad->anchor), iova->pfn_lo != IOVA_ANCHOR is true and kmem_cache_free(iova_cache, &iovad->anchor) is called on the anchor embedded inside struct iommu_dma_cookie.
[Severity: High]
Does setting the trailing reserved region's end to PHYS_ADDR_MAX also cause unsigned integer wraparound in iommu_insert_resv_region() when merging group reserved regions?
When iommu_get_group_resv_regions() merges device reserved regions through iommu_insert_device_resv_regions() -> iommu_insert_resv_region() in drivers/iommu/iommu.c:
top_end = top->start + top->length - 1;
if (iter->start > top_end + 1) {
list_move_tail(&iter->list, &stack);
} else {
top->length = max(top_end, iter_end) - top->start + 1;First, when top is a reserved region ending at top_end == PHYS_ADDR_MAX, top_end + 1 wraps around to 0 in phys_addr_t arithmetic. Any subsequent overlapping IOMMU_RESV_RESERVED region with iter->start > 0 satisfies iter->start > 0 and fails to merge.
Second, if a reserved region starting at top->start == 0 is merged with an overlapping or adjacent region ending at iter_end == PHYS_ADDR_MAX (for instance, when two devices in the same IOMMU group have disjoint usable iommu-ranges), max(top_end, iter_end) - top->start + 1 evaluates PHYS_ADDR_MAX - 0 + 1, wrapping top->length around to 0.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Rob Herring
maintainerRe: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
In reply to Vikash GarodiaQuoted 42 lines · Vikash Garodia
Reserving an IOVA address using "iommu-addresses" requires it to be placed in the reserved-memory node. But when "iommu-addresses" is the only property being described and there is no backing "reg" (i.e. no actual reserved system memory), it does not really belong under /reserved-memory. A device IOVA range is specific to its own address space, and does not describe the system physical memory to make it qualify under reserved-memory. Given this, place "iommu-addresses" inside reserved-memory only when it is paired with a "reg", otherwise, define it within the device own node. It was discussed here:
https://lore.kernel.org/all/[email protected]Existing "iommu-addresses" property expects a phandle, which does not make sense when the property is defined within the device node. "iommu-ranges" was introduced to specify the device specific IOVA ranges when there is no backing "reg".
Suggested-by Rob Herring <[email protected]>Reviewed-by Dmitry Baryshkov <[email protected]>Co-developed-by Vishnu Reddy <[email protected]>Signed-off-by Vishnu Reddy <[email protected]>Signed-off-by Vikash Garodia <[email protected]>--- drivers/iommu/of_iommu.c | 134 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 9 deletions(-)drivers/iommu/of_iommu.c +4
-2@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,if (start == phys->start && end == phys->end)return IOMMU_RESV_DIRECT ; -dev_warn (dev,"treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n" , phys, - &start, &end); +dev_err (dev,"non-direct mapping [%pr] -> [%pap-%pap] is not supported\n" , phys, + &start, &end);return IOMMU_RESV_RESERVED ; } +/** +* of_iommu_derive_resv_regions - derive reserved regions which
drivers/iommu/of_iommu.c iommu_resv_region_get_type(struct device *dev, · line 204
Quoted 10 lines
drivers/iommu/of_iommu.c +10
-0+* are outside of iommu-ranges +* @dev: device for which to get reserved regions +* @list: reserved region list +* +* A device can describe its own usable IOVA ranges directly on its node +* via "iommu-ranges". Everything not under those ranges is derived +* as a reserved region so the IOMMU allocator won't use it. Entries may +* appear in any order in the property. +*/ +#if IS_ENABLED (CONFIG_OF_ADDRESS )
Is this really needed? Assuming CONFIG_OF is enabled, this is only false on Sparc. I don't think Sparc needs anything in this file. There aren't any IOMMU drivers for Sparc unless COMPILE_TEST is enabled. So maybe building of_iommu.c as a whole should depend on CONFIG_OF_ADDRESS?
Rob
Re: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
Hi Rob,
Appreciate your reviews/suggestions on this patch.
Quoted 50 lines · Rob Herring
Quoted 49 lines · Vikash Garodia
Reserving an IOVA address using "iommu-addresses" requires it to be placed in the reserved-memory node. But when "iommu-addresses" is the only property being described and there is no backing "reg" (i.e. no actual reserved system memory), it does not really belong under /reserved-memory. A device IOVA range is specific to its own address space, and does not describe the system physical memory to make it qualify under reserved-memory. Given this, place "iommu-addresses" inside reserved-memory only when it is paired with a "reg", otherwise, define it within the device own node. It was discussed here:
https://lore.kernel.org/all/[email protected]Existing "iommu-addresses" property expects a phandle, which does not make sense when the property is defined within the device node. "iommu-ranges" was introduced to specify the device specific IOVA ranges when there is no backing "reg".
Suggested-by Rob Herring <[email protected]>Reviewed-by Dmitry Baryshkov <[email protected]>Co-developed-by Vishnu Reddy <[email protected]>Signed-off-by Vishnu Reddy <[email protected]>Signed-off-by Vikash Garodia <[email protected]>--- drivers/iommu/of_iommu.c | 134 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 9 deletions(-)drivers/iommu/of_iommu.c +11
-2@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,if (start == phys->start && end == phys->end)return IOMMU_RESV_DIRECT ; -dev_warn (dev,"treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n" , phys, - &start, &end); +dev_err (dev,"non-direct mapping [%pr] -> [%pap-%pap] is not supported\n" , phys, + &start, &end);return IOMMU_RESV_RESERVED ; } +/** +* of_iommu_derive_resv_regions - derive reserved regions which +* are outside of iommu-ranges +* @dev: device for which to get reserved regions +* @list: reserved region list +* +* A device can describe its own usable IOVA ranges directly on its node +* via "iommu-ranges". Everything not under those ranges is derived +* as a reserved region so the IOMMU allocator won't use it. Entries may
Quoted 8 lines
drivers/iommu/of_iommu.c iommu_resv_region_get_type(struct device *dev, · line 204
Quoted 3 lines
drivers/iommu/of_iommu.c +3
-0+* appear in any order in the property. +*/ +#if IS_ENABLED (CONFIG_OF_ADDRESS )Is this really needed? Assuming
CONFIG_OFis enabled, this is only false on Sparc. I don't think Sparc needs anything in this file. There aren't any IOMMU drivers for Sparc unlessCOMPILE_TESTis enabled. So maybe buildingof_iommu.cas a whole should depend onCONFIG_OF_ADDRESS?
Agree, that's much better than adding the check, will drop from other places too and make it conditional compilation.
Regards,
Vikash
Quoted 2 lines
Rob
Re: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
In reply to Vikash GarodiaQuoted 5 lines · Vikash Garodia
drivers/iommu/of_iommu.c +0
-0
drivers/iommu/of_iommu.c iommu_resv_region_get_type(struct device *dev, · line 192
Quoted 10 lines
drivers/iommu/of_iommu.c +2
-2@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,if (start == phys->start && end == phys->end)return IOMMU_RESV_DIRECT ; -dev_warn (dev,"treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n" , phys, - &start, &end); +dev_err (dev,"non-direct mapping [%pr] -> [%pap-%pap] is not supported\n" , phys, + &start, &end);return IOMMU_RESV_RESERVED ; }
Same feedback as @ the last version of this.
I still think this behaviour change should have its own patch that preceds this patch so that the logical change is clearly explained and understood as a standalone change.
Supporting iommu-ranges != not mapping misaligned ranges.
Otherwise this change goes under the radar of the new functionality addition.
---
bod
Re: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
Hi Bryan,
Quoted 19 lines · Bryan O'Donoghue
Quoted 5 lines · Vikash Garodia
drivers/iommu/of_iommu.c +0
-0drivers/iommu/of_iommu.c iommu_resv_region_get_type(struct device *dev, · line 192
Quoted 10 lines
drivers/iommu/of_iommu.c +2
-2@@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev, if (start == phys->start && end == phys->end) return IOMMU_RESV_DIRECT; - dev_warn(dev, "treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n", phys, - &start, &end); + dev_err(dev, "non-direct mapping [%pr] -> [%pap-%pap] is not supported\n", phys, + &start, &end); return IOMMU_RESV_RESERVED; }Same feedback as @ the last version of this.
Quoted 5 lines
I still think this behaviour change should have its own patch that preceds this patch so that the logical change is clearly explained and understood as a standalone change.
Supporting iommu-ranges != not mapping misaligned ranges.
Otherwise this change goes under the radar of the new functionality addition.
Ack. Will push this out as a separate patch.
Regards,
Vikash
Quoted 3 lines
---
bod