intel-iommu: Clean up identity mapping code, remove CONFIG_DMAR_GFX_WA

There's no need for the GFX workaround now we have 'iommu=pt' for the
cases where people really care about performance. There's no need to
have a special case for just one type of device.

This also speeds up the iommu=pt path and reduces memory usage by
setting up the si_domain _once_ and then using it for all devices,
rather than giving each device its own private page tables.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
David Woodhouse
2009-06-26 19:10:36 +01:00
parent b213203e47
commit c7ab48d2ac
2 changed files with 34 additions and 88 deletions

View File

@@ -1889,11 +1889,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
"IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
pci_name(pdev), start, end);
if (iommu_identity_mapping)
domain = si_domain;
else
/* page table init */
domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
if (!domain)
return -ENOMEM;
@@ -1922,64 +1918,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
rmrr->end_address + 1);
}
struct iommu_prepare_data {
struct pci_dev *pdev;
int ret;
};
static int __init iommu_prepare_work_fn(unsigned long start_pfn,
unsigned long end_pfn, void *datax)
{
struct iommu_prepare_data *data;
data = (struct iommu_prepare_data *)datax;
data->ret = iommu_prepare_identity_map(data->pdev,
start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
return data->ret;
}
static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev)
{
int nid;
struct iommu_prepare_data data;
data.pdev = pdev;
data.ret = 0;
for_each_online_node(nid) {
work_with_active_regions(nid, iommu_prepare_work_fn, &data);
if (data.ret)
return data.ret;
}
return data.ret;
}
#ifdef CONFIG_DMAR_GFX_WA
static void __init iommu_prepare_gfx_mapping(void)
{
struct pci_dev *pdev = NULL;
int ret;
for_each_pci_dev(pdev) {
if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO ||
!IS_GFX_DEVICE(pdev))
continue;
printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
pci_name(pdev));
ret = iommu_prepare_with_active_regions(pdev);
if (ret)
printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
}
}
#else /* !CONFIG_DMAR_GFX_WA */
static inline void iommu_prepare_gfx_mapping(void)
{
return;
}
#endif
#ifdef CONFIG_DMAR_FLOPPY_WA
static inline void iommu_prepare_isa(void)
{
@@ -1990,12 +1928,12 @@ static inline void iommu_prepare_isa(void)
if (!pdev)
return;
printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n");
printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024);
if (ret)
printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, "
"floppy might not work\n");
printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
"floppy might not work\n");
}
#else
@@ -2023,16 +1961,30 @@ static int __init init_context_pass_through(void)
}
static int md_domain_init(struct dmar_domain *domain, int guest_width);
static int __init si_domain_work_fn(unsigned long start_pfn,
unsigned long end_pfn, void *datax)
{
int *ret = datax;
*ret = iommu_domain_identity_map(si_domain,
(uint64_t)start_pfn << PAGE_SHIFT,
(uint64_t)end_pfn << PAGE_SHIFT);
return *ret;
}
static int si_domain_init(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu;
int ret = 0;
int nid, ret = 0;
si_domain = alloc_domain();
if (!si_domain)
return -EFAULT;
pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
for_each_active_iommu(iommu, drhd) {
ret = iommu_attach_domain(si_domain, iommu);
@@ -2049,6 +2001,12 @@ static int si_domain_init(void)
si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
for_each_online_node(nid) {
work_with_active_regions(nid, si_domain_work_fn, &ret);
if (ret)
return ret;
}
return 0;
}
@@ -2102,13 +2060,14 @@ static int iommu_prepare_static_identity_mapping(void)
if (ret)
return -EFAULT;
printk(KERN_INFO "IOMMU: Setting identity map:\n");
for_each_pci_dev(pdev) {
ret = iommu_prepare_with_active_regions(pdev);
if (ret) {
printk(KERN_INFO "1:1 mapping to one domain failed.\n");
return -EFAULT;
}
printk(KERN_INFO "IOMMU: identity mapping for device %s\n",
pci_name(pdev));
ret = domain_context_mapping(si_domain, pdev,
CONTEXT_TT_MULTI_LEVEL);
if (ret)
return ret;
ret = domain_add_dev_info(si_domain, pdev);
if (ret)
return ret;
@@ -2299,8 +2258,6 @@ int __init init_dmars(void)
}
}
iommu_prepare_gfx_mapping();
iommu_prepare_isa();
}