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

@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON
recommended you say N here while the DMAR code remains
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
def_bool y
depends on DMAR
---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
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
bool "Support for Interrupt Remapping (EXPERIMENTAL)"

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();
}