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:
parent
b213203e47
commit
c7ab48d2ac
|
@ -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,
|
||||||
"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,
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iommu_prepare_gfx_mapping();
|
|
||||||
|
|
||||||
iommu_prepare_isa();
|
iommu_prepare_isa();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue