Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu: Implement reserved_regions iommu-group sysfs file

A new iommu-group sysfs attribute file is introduced. It contains
the list of reserved regions for the iommu-group. Each reserved
region is described on a separate line:
- first field is the start IOVA address,
- second is the end IOVA address,
- third is the type.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Tomasz Nowicki <tomasz.nowicki@caviumnetworks.com>
Tested-by: Bharat Bhushan <bharat.bhushan@nxp.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

authored by

Eric Auger and committed by
Will Deacon
bc7d12b9 6c65fb31

+48
+12
Documentation/ABI/testing/sysfs-kernel-iommu_groups
··· 12 12 file if the IOMMU driver has chosen to register a more 13 13 common name for the group. 14 14 Users: 15 + 16 + What: /sys/kernel/iommu_groups/reserved_regions 17 + Date: January 2017 18 + KernelVersion: v4.11 19 + Contact: Eric Auger <eric.auger@redhat.com> 20 + Description: /sys/kernel/iommu_groups/reserved_regions list IOVA 21 + regions that are reserved. Not necessarily all 22 + reserved regions are listed. This is typically used to 23 + output direct-mapped, MSI, non mappable regions. Each 24 + region is described on a single line: the 1st field is 25 + the base IOVA, the second is the end IOVA and the third 26 + field describes the type of the region.
+36
drivers/iommu/iommu.c
··· 68 68 const char *buf, size_t count); 69 69 }; 70 70 71 + static const char * const iommu_group_resv_type_string[] = { 72 + [IOMMU_RESV_DIRECT] = "direct", 73 + [IOMMU_RESV_RESERVED] = "reserved", 74 + [IOMMU_RESV_MSI] = "msi", 75 + }; 76 + 71 77 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ 72 78 struct iommu_group_attribute iommu_group_attr_##_name = \ 73 79 __ATTR(_name, _mode, _show, _store) ··· 237 231 } 238 232 EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); 239 233 234 + static ssize_t iommu_group_show_resv_regions(struct iommu_group *group, 235 + char *buf) 236 + { 237 + struct iommu_resv_region *region, *next; 238 + struct list_head group_resv_regions; 239 + char *str = buf; 240 + 241 + INIT_LIST_HEAD(&group_resv_regions); 242 + iommu_get_group_resv_regions(group, &group_resv_regions); 243 + 244 + list_for_each_entry_safe(region, next, &group_resv_regions, list) { 245 + str += sprintf(str, "0x%016llx 0x%016llx %s\n", 246 + (long long int)region->start, 247 + (long long int)(region->start + 248 + region->length - 1), 249 + iommu_group_resv_type_string[region->type]); 250 + kfree(region); 251 + } 252 + 253 + return (str - buf); 254 + } 255 + 240 256 static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); 257 + 258 + static IOMMU_GROUP_ATTR(reserved_regions, 0444, 259 + iommu_group_show_resv_regions, NULL); 241 260 242 261 static void iommu_group_release(struct kobject *kobj) 243 262 { ··· 340 309 * use the devices_kobj for reference counting. 341 310 */ 342 311 kobject_put(&group->kobj); 312 + 313 + ret = iommu_group_create_file(group, 314 + &iommu_group_attr_reserved_regions); 315 + if (ret) 316 + return ERR_PTR(ret); 343 317 344 318 pr_debug("Allocated group %d\n", group->id); 345 319