Skip to content

Commit 82612d6

Browse files
pippy360willdeacon
authored andcommitted
iommu: Allow the dma-iommu api to use bounce buffers
Allow the dma-iommu api to use bounce buffers for untrusted devices. This is a copy of the intel bounce buffer code. Co-developed-by: Lu Baolu <[email protected]> Signed-off-by: Tom Murphy <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Tested-by: Logan Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 230309d commit 82612d6

File tree

1 file changed

+149
-13
lines changed

1 file changed

+149
-13
lines changed

drivers/iommu/dma-iommu.c

Lines changed: 149 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
#include <linux/mm.h>
2121
#include <linux/mutex.h>
2222
#include <linux/pci.h>
23+
#include <linux/swiotlb.h>
2324
#include <linux/scatterlist.h>
2425
#include <linux/vmalloc.h>
2526
#include <linux/crash_dump.h>
27+
#include <linux/dma-direct.h>
2628

2729
struct iommu_dma_msi_page {
2830
struct list_head list;
@@ -499,6 +501,31 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
499501
iommu_dma_free_iova(cookie, dma_addr, size, iotlb_gather.freelist);
500502
}
501503

504+
static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
505+
size_t size, enum dma_data_direction dir,
506+
unsigned long attrs)
507+
{
508+
struct iommu_domain *domain = iommu_get_dma_domain(dev);
509+
struct iommu_dma_cookie *cookie = domain->iova_cookie;
510+
struct iova_domain *iovad = &cookie->iovad;
511+
phys_addr_t phys;
512+
513+
phys = iommu_iova_to_phys(domain, dma_addr);
514+
if (WARN_ON(!phys))
515+
return;
516+
517+
__iommu_dma_unmap(dev, dma_addr, size);
518+
519+
if (unlikely(is_swiotlb_buffer(phys)))
520+
swiotlb_tbl_unmap_single(dev, phys, size,
521+
iova_align(iovad, size), dir, attrs);
522+
}
523+
524+
static bool dev_is_untrusted(struct device *dev)
525+
{
526+
return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
527+
}
528+
502529
static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
503530
size_t size, int prot, u64 dma_mask)
504531
{
@@ -524,6 +551,54 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
524551
return iova + iova_off;
525552
}
526553

554+
static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys,
555+
size_t org_size, dma_addr_t dma_mask, bool coherent,
556+
enum dma_data_direction dir, unsigned long attrs)
557+
{
558+
int prot = dma_info_to_prot(dir, coherent, attrs);
559+
struct iommu_domain *domain = iommu_get_dma_domain(dev);
560+
struct iommu_dma_cookie *cookie = domain->iova_cookie;
561+
struct iova_domain *iovad = &cookie->iovad;
562+
size_t aligned_size = org_size;
563+
void *padding_start;
564+
size_t padding_size;
565+
dma_addr_t iova;
566+
567+
/*
568+
* If both the physical buffer start address and size are
569+
* page aligned, we don't need to use a bounce page.
570+
*/
571+
if (IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev) &&
572+
iova_offset(iovad, phys | org_size)) {
573+
aligned_size = iova_align(iovad, org_size);
574+
phys = swiotlb_tbl_map_single(dev, phys, org_size,
575+
aligned_size, dir, attrs);
576+
577+
if (phys == DMA_MAPPING_ERROR)
578+
return DMA_MAPPING_ERROR;
579+
580+
/* Cleanup the padding area. */
581+
padding_start = phys_to_virt(phys);
582+
padding_size = aligned_size;
583+
584+
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
585+
(dir == DMA_TO_DEVICE ||
586+
dir == DMA_BIDIRECTIONAL)) {
587+
padding_start += org_size;
588+
padding_size -= org_size;
589+
}
590+
591+
memset(padding_start, 0, padding_size);
592+
}
593+
594+
iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask);
595+
if ((iova == DMA_MAPPING_ERROR) && is_swiotlb_buffer(phys))
596+
swiotlb_tbl_unmap_single(dev, phys, org_size,
597+
aligned_size, dir, attrs);
598+
599+
return iova;
600+
}
601+
527602
static void __iommu_dma_free_pages(struct page **pages, int count)
528603
{
529604
while (count--)
@@ -697,23 +772,31 @@ static void iommu_dma_sync_single_for_cpu(struct device *dev,
697772
{
698773
phys_addr_t phys;
699774

700-
if (dev_is_dma_coherent(dev))
775+
if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
701776
return;
702777

703778
phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
704-
arch_sync_dma_for_cpu(phys, size, dir);
779+
if (!dev_is_dma_coherent(dev))
780+
arch_sync_dma_for_cpu(phys, size, dir);
781+
782+
if (is_swiotlb_buffer(phys))
783+
swiotlb_tbl_sync_single(dev, phys, size, dir, SYNC_FOR_CPU);
705784
}
706785

707786
static void iommu_dma_sync_single_for_device(struct device *dev,
708787
dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
709788
{
710789
phys_addr_t phys;
711790

712-
if (dev_is_dma_coherent(dev))
791+
if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
713792
return;
714793

715794
phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
716-
arch_sync_dma_for_device(phys, size, dir);
795+
if (is_swiotlb_buffer(phys))
796+
swiotlb_tbl_sync_single(dev, phys, size, dir, SYNC_FOR_DEVICE);
797+
798+
if (!dev_is_dma_coherent(dev))
799+
arch_sync_dma_for_device(phys, size, dir);
717800
}
718801

719802
static void iommu_dma_sync_sg_for_cpu(struct device *dev,
@@ -723,11 +806,17 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev,
723806
struct scatterlist *sg;
724807
int i;
725808

726-
if (dev_is_dma_coherent(dev))
809+
if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
727810
return;
728811

729-
for_each_sg(sgl, sg, nelems, i)
730-
arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
812+
for_each_sg(sgl, sg, nelems, i) {
813+
if (!dev_is_dma_coherent(dev))
814+
arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
815+
816+
if (is_swiotlb_buffer(sg_phys(sg)))
817+
swiotlb_tbl_sync_single(dev, sg_phys(sg), sg->length,
818+
dir, SYNC_FOR_CPU);
819+
}
731820
}
732821

733822
static void iommu_dma_sync_sg_for_device(struct device *dev,
@@ -737,11 +826,17 @@ static void iommu_dma_sync_sg_for_device(struct device *dev,
737826
struct scatterlist *sg;
738827
int i;
739828

740-
if (dev_is_dma_coherent(dev))
829+
if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
741830
return;
742831

743-
for_each_sg(sgl, sg, nelems, i)
744-
arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
832+
for_each_sg(sgl, sg, nelems, i) {
833+
if (is_swiotlb_buffer(sg_phys(sg)))
834+
swiotlb_tbl_sync_single(dev, sg_phys(sg), sg->length,
835+
dir, SYNC_FOR_DEVICE);
836+
837+
if (!dev_is_dma_coherent(dev))
838+
arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
839+
}
745840
}
746841

747842
static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
@@ -750,10 +845,10 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
750845
{
751846
phys_addr_t phys = page_to_phys(page) + offset;
752847
bool coherent = dev_is_dma_coherent(dev);
753-
int prot = dma_info_to_prot(dir, coherent, attrs);
754848
dma_addr_t dma_handle;
755849

756-
dma_handle = __iommu_dma_map(dev, phys, size, prot, dma_get_mask(dev));
850+
dma_handle = __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev),
851+
coherent, dir, attrs);
757852
if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
758853
dma_handle != DMA_MAPPING_ERROR)
759854
arch_sync_dma_for_device(phys, size, dir);
@@ -765,7 +860,7 @@ static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
765860
{
766861
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
767862
iommu_dma_sync_single_for_cpu(dev, dma_handle, size, dir);
768-
__iommu_dma_unmap(dev, dma_handle, size);
863+
__iommu_dma_unmap_swiotlb(dev, dma_handle, size, dir, attrs);
769864
}
770865

771866
/*
@@ -843,6 +938,39 @@ static void __invalidate_sg(struct scatterlist *sg, int nents)
843938
}
844939
}
845940

941+
static void iommu_dma_unmap_sg_swiotlb(struct device *dev, struct scatterlist *sg,
942+
int nents, enum dma_data_direction dir, unsigned long attrs)
943+
{
944+
struct scatterlist *s;
945+
int i;
946+
947+
for_each_sg(sg, s, nents, i)
948+
__iommu_dma_unmap_swiotlb(dev, sg_dma_address(s),
949+
sg_dma_len(s), dir, attrs);
950+
}
951+
952+
static int iommu_dma_map_sg_swiotlb(struct device *dev, struct scatterlist *sg,
953+
int nents, enum dma_data_direction dir, unsigned long attrs)
954+
{
955+
struct scatterlist *s;
956+
int i;
957+
958+
for_each_sg(sg, s, nents, i) {
959+
sg_dma_address(s) = __iommu_dma_map_swiotlb(dev, sg_phys(s),
960+
s->length, dma_get_mask(dev),
961+
dev_is_dma_coherent(dev), dir, attrs);
962+
if (sg_dma_address(s) == DMA_MAPPING_ERROR)
963+
goto out_unmap;
964+
sg_dma_len(s) = s->length;
965+
}
966+
967+
return nents;
968+
969+
out_unmap:
970+
iommu_dma_unmap_sg_swiotlb(dev, sg, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
971+
return 0;
972+
}
973+
846974
/*
847975
* The DMA API client is passing in a scatterlist which could describe
848976
* any old buffer layout, but the IOMMU API requires everything to be
@@ -869,6 +997,9 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
869997
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
870998
iommu_dma_sync_sg_for_device(dev, sg, nents, dir);
871999

1000+
if (dev_is_untrusted(dev))
1001+
return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs);
1002+
8721003
/*
8731004
* Work out how much IOVA space we need, and align the segments to
8741005
* IOVA granules for the IOMMU driver to handle. With some clever
@@ -938,6 +1069,11 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
9381069
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
9391070
iommu_dma_sync_sg_for_cpu(dev, sg, nents, dir);
9401071

1072+
if (dev_is_untrusted(dev)) {
1073+
iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs);
1074+
return;
1075+
}
1076+
9411077
/*
9421078
* The scatterlist segments are mapped into a single
9431079
* contiguous IOVA allocation, so this is incredibly easy.

0 commit comments

Comments
 (0)