aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-09-04 09:04:26 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-19 06:59:03 -0400
commitdbcc112e3b5367e81a845b082933506b0ff1d1e2 (patch)
treeb5537684c5ea8d354d5e94b358741f4db3e05d7c /arch/x86/kernel/amd_iommu.c
parent07a2c01a0c2a0cb4581a67d50d4f17cb4d2457c4 (diff)
AMD IOMMU: check for invalid device pointers
Currently AMD IOMMU code triggers a BUG_ON if NULL is passed as the device. This is inconsistent with other IOMMU implementations. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/amd_iommu.c')
-rw-r--r--arch/x86/kernel/amd_iommu.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 01c68c38840d..695e0fc41b10 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -646,6 +646,18 @@ static void set_device_domain(struct amd_iommu *iommu,
646 *****************************************************************************/ 646 *****************************************************************************/
647 647
648/* 648/*
649 * This function checks if the driver got a valid device from the caller to
650 * avoid dereferencing invalid pointers.
651 */
652static bool check_device(struct device *dev)
653{
654 if (!dev || !dev->dma_mask)
655 return false;
656
657 return true;
658}
659
660/*
649 * In the dma_ops path we only have the struct device. This function 661 * In the dma_ops path we only have the struct device. This function
650 * finds the corresponding IOMMU, the protection domain and the 662 * finds the corresponding IOMMU, the protection domain and the
651 * requestor id for a given device. 663 * requestor id for a given device.
@@ -661,18 +673,19 @@ static int get_device_resources(struct device *dev,
661 struct pci_dev *pcidev; 673 struct pci_dev *pcidev;
662 u16 _bdf; 674 u16 _bdf;
663 675
664 BUG_ON(!dev || dev->bus != &pci_bus_type || !dev->dma_mask); 676 *iommu = NULL;
677 *domain = NULL;
678 *bdf = 0xffff;
679
680 if (dev->bus != &pci_bus_type)
681 return 0;
665 682
666 pcidev = to_pci_dev(dev); 683 pcidev = to_pci_dev(dev);
667 _bdf = calc_devid(pcidev->bus->number, pcidev->devfn); 684 _bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
668 685
669 /* device not translated by any IOMMU in the system? */ 686 /* device not translated by any IOMMU in the system? */
670 if (_bdf > amd_iommu_last_bdf) { 687 if (_bdf > amd_iommu_last_bdf)
671 *iommu = NULL;
672 *domain = NULL;
673 *bdf = 0xffff;
674 return 0; 688 return 0;
675 }
676 689
677 *bdf = amd_iommu_alias_table[_bdf]; 690 *bdf = amd_iommu_alias_table[_bdf];
678 691
@@ -826,6 +839,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
826 u16 devid; 839 u16 devid;
827 dma_addr_t addr; 840 dma_addr_t addr;
828 841
842 if (!check_device(dev))
843 return bad_dma_address;
844
829 get_device_resources(dev, &iommu, &domain, &devid); 845 get_device_resources(dev, &iommu, &domain, &devid);
830 846
831 if (iommu == NULL || domain == NULL) 847 if (iommu == NULL || domain == NULL)
@@ -860,7 +876,8 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
860 struct protection_domain *domain; 876 struct protection_domain *domain;
861 u16 devid; 877 u16 devid;
862 878
863 if (!get_device_resources(dev, &iommu, &domain, &devid)) 879 if (!check_device(dev) ||
880 !get_device_resources(dev, &iommu, &domain, &devid))
864 /* device not handled by any AMD IOMMU */ 881 /* device not handled by any AMD IOMMU */
865 return; 882 return;
866 883
@@ -910,6 +927,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
910 phys_addr_t paddr; 927 phys_addr_t paddr;
911 int mapped_elems = 0; 928 int mapped_elems = 0;
912 929
930 if (!check_device(dev))
931 return 0;
932
913 get_device_resources(dev, &iommu, &domain, &devid); 933 get_device_resources(dev, &iommu, &domain, &devid);
914 934
915 if (!iommu || !domain) 935 if (!iommu || !domain)
@@ -967,7 +987,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
967 u16 devid; 987 u16 devid;
968 int i; 988 int i;
969 989
970 if (!get_device_resources(dev, &iommu, &domain, &devid)) 990 if (!check_device(dev) ||
991 !get_device_resources(dev, &iommu, &domain, &devid))
971 return; 992 return;
972 993
973 spin_lock_irqsave(&domain->lock, flags); 994 spin_lock_irqsave(&domain->lock, flags);
@@ -999,6 +1020,9 @@ static void *alloc_coherent(struct device *dev, size_t size,
999 u16 devid; 1020 u16 devid;
1000 phys_addr_t paddr; 1021 phys_addr_t paddr;
1001 1022
1023 if (!check_device(dev))
1024 return NULL;
1025
1002 virt_addr = (void *)__get_free_pages(flag, get_order(size)); 1026 virt_addr = (void *)__get_free_pages(flag, get_order(size));
1003 if (!virt_addr) 1027 if (!virt_addr)
1004 return 0; 1028 return 0;
@@ -1047,6 +1071,9 @@ static void free_coherent(struct device *dev, size_t size,
1047 struct protection_domain *domain; 1071 struct protection_domain *domain;
1048 u16 devid; 1072 u16 devid;
1049 1073
1074 if (!check_device(dev))
1075 return;
1076
1050 get_device_resources(dev, &iommu, &domain, &devid); 1077 get_device_resources(dev, &iommu, &domain, &devid);
1051 1078
1052 if (!iommu || !domain) 1079 if (!iommu || !domain)