Commit c7ab48d2 authored by David Woodhouse's avatar David Woodhouse

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: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent b213203e
...@@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON ...@@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON
recommended you say N here while the DMAR code remains recommended you say N here while the DMAR code remains
experimental. experimental.
config DMAR_GFX_WA
def_bool y
prompt "Support for Graphics workaround"
depends on DMAR
---help---
Current Graphics drivers tend to use physical address
for DMA and avoid using DMA APIs. Setting this config
option permits the IOMMU driver to set a unity map for
all the OS-visible memory. Hence the driver can continue
to use physical addresses for DMA.
config DMAR_FLOPPY_WA config DMAR_FLOPPY_WA
def_bool y def_bool y
depends on DMAR depends on DMAR
---help--- ---help---
Floppy disk drivers are know to bypass DMA API calls Floppy disk drivers are known to bypass DMA API calls
thereby failing to work when IOMMU is enabled. This thereby failing to work when IOMMU is enabled. This
workaround will setup a 1:1 mapping for the first workaround will setup a 1:1 mapping for the first
16M to make floppy (an ISA device) work. 16MiB to make floppy (an ISA device) work.
config INTR_REMAP config INTR_REMAP
bool "Support for Interrupt Remapping (EXPERIMENTAL)" bool "Support for Interrupt Remapping (EXPERIMENTAL)"
......
...@@ -1889,11 +1889,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, ...@@ -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", "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
pci_name(pdev), start, end); pci_name(pdev), start, end);
if (iommu_identity_mapping) domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
domain = si_domain;
else
/* page table init */
domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
if (!domain) if (!domain)
return -ENOMEM; return -ENOMEM;
...@@ -1922,64 +1918,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, ...@@ -1922,64 +1918,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
rmrr->end_address + 1); 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 #ifdef CONFIG_DMAR_FLOPPY_WA
static inline void iommu_prepare_isa(void) static inline void iommu_prepare_isa(void)
{ {
...@@ -1990,12 +1928,12 @@ static inline void iommu_prepare_isa(void) ...@@ -1990,12 +1928,12 @@ static inline void iommu_prepare_isa(void)
if (!pdev) if (!pdev)
return; 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); ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024);
if (ret) if (ret)
printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
"floppy might not work\n"); "floppy might not work\n");
} }
#else #else
...@@ -2023,16 +1961,30 @@ static int __init init_context_pass_through(void) ...@@ -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 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) static int si_domain_init(void)
{ {
struct dmar_drhd_unit *drhd; struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu; struct intel_iommu *iommu;
int ret = 0; int nid, ret = 0;
si_domain = alloc_domain(); si_domain = alloc_domain();
if (!si_domain) if (!si_domain)
return -EFAULT; return -EFAULT;
pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
for_each_active_iommu(iommu, drhd) { for_each_active_iommu(iommu, drhd) {
ret = iommu_attach_domain(si_domain, iommu); ret = iommu_attach_domain(si_domain, iommu);
...@@ -2049,6 +2001,12 @@ static int si_domain_init(void) ...@@ -2049,6 +2001,12 @@ static int si_domain_init(void)
si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; 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; return 0;
} }
...@@ -2102,13 +2060,14 @@ static int iommu_prepare_static_identity_mapping(void) ...@@ -2102,13 +2060,14 @@ static int iommu_prepare_static_identity_mapping(void)
if (ret) if (ret)
return -EFAULT; return -EFAULT;
printk(KERN_INFO "IOMMU: Setting identity map:\n");
for_each_pci_dev(pdev) { for_each_pci_dev(pdev) {
ret = iommu_prepare_with_active_regions(pdev); printk(KERN_INFO "IOMMU: identity mapping for device %s\n",
if (ret) { pci_name(pdev));
printk(KERN_INFO "1:1 mapping to one domain failed.\n");
return -EFAULT; ret = domain_context_mapping(si_domain, pdev,
} CONTEXT_TT_MULTI_LEVEL);
if (ret)
return ret;
ret = domain_add_dev_info(si_domain, pdev); ret = domain_add_dev_info(si_domain, pdev);
if (ret) if (ret)
return ret; return ret;
...@@ -2299,8 +2258,6 @@ int __init init_dmars(void) ...@@ -2299,8 +2258,6 @@ int __init init_dmars(void)
} }
} }
iommu_prepare_gfx_mapping();
iommu_prepare_isa(); iommu_prepare_isa();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment