Skip to content

Commit

Permalink
iommu/amd: Create a list of reserved iova addresses
Browse files Browse the repository at this point in the history
Put the MSI-range, the HT-range and the MMIO ranges of PCI
devices into that range, so that these addresses are not
allocated for DMA.

Copy this address list into every created dma_ops_domain.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Joerg Roedel committed Jul 13, 2016
1 parent 307d585 commit 81cd07b
Showing 1 changed file with 69 additions and 0 deletions.
69 changes: 69 additions & 0 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))

/* Reserved IOVA ranges */
#define MSI_RANGE_START (0xfee00000)
#define MSI_RANGE_END (0xfeefffff)
#define HT_RANGE_START (0xfd00000000ULL)
#define HT_RANGE_END (0xffffffffffULL)

/*
* This bitmap is used to advertise the page sizes our hardware support
* to the IOMMU core, which will then use this information to split
Expand Down Expand Up @@ -169,6 +175,9 @@ struct dma_ops_domain {
struct iova_domain iovad;
};

static struct iova_domain reserved_iova_ranges;
static struct lock_class_key reserved_rbtree_key;

/****************************************************************************
*
* Helper functions
Expand Down Expand Up @@ -2058,6 +2067,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void)
init_iova_domain(&dma_dom->iovad, PAGE_SIZE,
IOVA_START_PFN, DMA_32BIT_PFN);

/* Initialize reserved ranges */
copy_reserved_iova(&reserved_iova_ranges, &dma_dom->iovad);

return dma_dom;

free_dma_dom:
Expand Down Expand Up @@ -2963,6 +2975,59 @@ static struct dma_map_ops amd_iommu_dma_ops = {
.set_dma_mask = set_dma_mask,
};

static int init_reserved_iova_ranges(void)
{
struct pci_dev *pdev = NULL;
struct iova *val;

init_iova_domain(&reserved_iova_ranges, PAGE_SIZE,
IOVA_START_PFN, DMA_32BIT_PFN);

lockdep_set_class(&reserved_iova_ranges.iova_rbtree_lock,
&reserved_rbtree_key);

/* MSI memory range */
val = reserve_iova(&reserved_iova_ranges,
IOVA_PFN(MSI_RANGE_START), IOVA_PFN(MSI_RANGE_END));
if (!val) {
pr_err("Reserving MSI range failed\n");
return -ENOMEM;
}

/* HT memory range */
val = reserve_iova(&reserved_iova_ranges,
IOVA_PFN(HT_RANGE_START), IOVA_PFN(HT_RANGE_END));
if (!val) {
pr_err("Reserving HT range failed\n");
return -ENOMEM;
}

/*
* Memory used for PCI resources
* FIXME: Check whether we can reserve the PCI-hole completly
*/
for_each_pci_dev(pdev) {
int i;

for (i = 0; i < PCI_NUM_RESOURCES; ++i) {
struct resource *r = &pdev->resource[i];

if (!(r->flags & IORESOURCE_MEM))
continue;

val = reserve_iova(&reserved_iova_ranges,
IOVA_PFN(r->start),
IOVA_PFN(r->end));
if (!val) {
pr_err("Reserve pci-resource range failed\n");
return -ENOMEM;
}
}
}

return 0;
}

int __init amd_iommu_init_api(void)
{
int ret, err = 0;
Expand All @@ -2971,6 +3036,10 @@ int __init amd_iommu_init_api(void)
if (ret)
return ret;

ret = init_reserved_iova_ranges();
if (ret)
return ret;

err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
if (err)
return err;
Expand Down

0 comments on commit 81cd07b

Please sign in to comment.