mirror of https://gitee.com/openkylin/linux.git
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
|
||||
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)"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue