summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2019-06-03 02:53:31 -0400
committerJoerg Roedel <jroedel@suse.de>2019-06-12 04:32:59 -0400
commit5f64ce5411b467f1cfea6c63e2494c22b773582b (patch)
tree9837f8989e06c2f76cf720346842341c5e80b3da /drivers/iommu/intel-iommu.c
parentad0834dedaa15c3a176f783c0373f836e44b4700 (diff)
iommu/vt-d: Duplicate iommu_resv_region objects per device list
intel_iommu_get_resv_regions() aims to return the list of reserved regions accessible by a given @device. However several devices can access the same reserved memory region and when building the list it is not safe to use a single iommu_resv_region object, whose container is the RMRR. This iommu_resv_region must be duplicated per device reserved region list. Let's remove the struct iommu_resv_region from the RMRR unit and allocate the iommu_resv_region directly in intel_iommu_get_resv_regions(). We hold the dmar_global_lock instead of the rcu-lock to allow sleeping. Fixes: 0659b8dc45a6 ("iommu/vt-d: Implement reserved region get/put callbacks") Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c34
1 files changed, 17 insertions, 17 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 876096c1f91b..082fbb1bdeaf 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -324,7 +324,6 @@ struct dmar_rmrr_unit {
324 u64 end_address; /* reserved end address */ 324 u64 end_address; /* reserved end address */
325 struct dmar_dev_scope *devices; /* target devices */ 325 struct dmar_dev_scope *devices; /* target devices */
326 int devices_cnt; /* target device count */ 326 int devices_cnt; /* target device count */
327 struct iommu_resv_region *resv; /* reserved region handle */
328}; 327};
329 328
330struct dmar_atsr_unit { 329struct dmar_atsr_unit {
@@ -4050,7 +4049,6 @@ static inline void init_iommu_pm_ops(void) {}
4050int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg) 4049int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
4051{ 4050{
4052 struct acpi_dmar_reserved_memory *rmrr; 4051 struct acpi_dmar_reserved_memory *rmrr;
4053 int prot = DMA_PTE_READ|DMA_PTE_WRITE;
4054 struct dmar_rmrr_unit *rmrru; 4052 struct dmar_rmrr_unit *rmrru;
4055 size_t length; 4053 size_t length;
4056 4054
@@ -4064,22 +4062,16 @@ int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
4064 rmrru->end_address = rmrr->end_address; 4062 rmrru->end_address = rmrr->end_address;
4065 4063
4066 length = rmrr->end_address - rmrr->base_address + 1; 4064 length = rmrr->end_address - rmrr->base_address + 1;
4067 rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
4068 IOMMU_RESV_DIRECT);
4069 if (!rmrru->resv)
4070 goto free_rmrru;
4071 4065
4072 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1), 4066 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4073 ((void *)rmrr) + rmrr->header.length, 4067 ((void *)rmrr) + rmrr->header.length,
4074 &rmrru->devices_cnt); 4068 &rmrru->devices_cnt);
4075 if (rmrru->devices_cnt && rmrru->devices == NULL) 4069 if (rmrru->devices_cnt && rmrru->devices == NULL)
4076 goto free_all; 4070 goto free_rmrru;
4077 4071
4078 list_add(&rmrru->list, &dmar_rmrr_units); 4072 list_add(&rmrru->list, &dmar_rmrr_units);
4079 4073
4080 return 0; 4074 return 0;
4081free_all:
4082 kfree(rmrru->resv);
4083free_rmrru: 4075free_rmrru:
4084 kfree(rmrru); 4076 kfree(rmrru);
4085out: 4077out:
@@ -4297,7 +4289,6 @@ static void intel_iommu_free_dmars(void)
4297 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) { 4289 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4298 list_del(&rmrru->list); 4290 list_del(&rmrru->list);
4299 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt); 4291 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
4300 kfree(rmrru->resv);
4301 kfree(rmrru); 4292 kfree(rmrru);
4302 } 4293 }
4303 4294
@@ -5400,22 +5391,33 @@ static void intel_iommu_remove_device(struct device *dev)
5400static void intel_iommu_get_resv_regions(struct device *device, 5391static void intel_iommu_get_resv_regions(struct device *device,
5401 struct list_head *head) 5392 struct list_head *head)
5402{ 5393{
5394 int prot = DMA_PTE_READ | DMA_PTE_WRITE;
5403 struct iommu_resv_region *reg; 5395 struct iommu_resv_region *reg;
5404 struct dmar_rmrr_unit *rmrr; 5396 struct dmar_rmrr_unit *rmrr;
5405 struct device *i_dev; 5397 struct device *i_dev;
5406 int i; 5398 int i;
5407 5399
5408 rcu_read_lock(); 5400 down_read(&dmar_global_lock);
5409 for_each_rmrr_units(rmrr) { 5401 for_each_rmrr_units(rmrr) {
5410 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt, 5402 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5411 i, i_dev) { 5403 i, i_dev) {
5404 struct iommu_resv_region *resv;
5405 size_t length;
5406
5412 if (i_dev != device) 5407 if (i_dev != device)
5413 continue; 5408 continue;
5414 5409
5415 list_add_tail(&rmrr->resv->list, head); 5410 length = rmrr->end_address - rmrr->base_address + 1;
5411 resv = iommu_alloc_resv_region(rmrr->base_address,
5412 length, prot,
5413 IOMMU_RESV_DIRECT);
5414 if (!resv)
5415 break;
5416
5417 list_add_tail(&resv->list, head);
5416 } 5418 }
5417 } 5419 }
5418 rcu_read_unlock(); 5420 up_read(&dmar_global_lock);
5419 5421
5420#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA 5422#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
5421 if (dev_is_pci(device)) { 5423 if (dev_is_pci(device)) {
@@ -5443,10 +5445,8 @@ static void intel_iommu_put_resv_regions(struct device *dev,
5443{ 5445{
5444 struct iommu_resv_region *entry, *next; 5446 struct iommu_resv_region *entry, *next;
5445 5447
5446 list_for_each_entry_safe(entry, next, head, list) { 5448 list_for_each_entry_safe(entry, next, head, list)
5447 if (entry->type == IOMMU_RESV_MSI) 5449 kfree(entry);
5448 kfree(entry);
5449 }
5450} 5450}
5451 5451
5452int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev) 5452int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)