Commit c7ab48d2acaf959e4d59c3f55d12fdb7ca9afd7c
1 parent
b213203e47
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 34 additions and 88 deletions Side-by-side Diff
arch/x86/Kconfig
... | ... | @@ -1913,25 +1913,14 @@ |
1913 | 1913 | recommended you say N here while the DMAR code remains |
1914 | 1914 | experimental. |
1915 | 1915 | |
1916 | -config DMAR_GFX_WA | |
1917 | - def_bool y | |
1918 | - prompt "Support for Graphics workaround" | |
1919 | - depends on DMAR | |
1920 | - ---help--- | |
1921 | - Current Graphics drivers tend to use physical address | |
1922 | - for DMA and avoid using DMA APIs. Setting this config | |
1923 | - option permits the IOMMU driver to set a unity map for | |
1924 | - all the OS-visible memory. Hence the driver can continue | |
1925 | - to use physical addresses for DMA. | |
1926 | - | |
1927 | 1916 | config DMAR_FLOPPY_WA |
1928 | 1917 | def_bool y |
1929 | 1918 | depends on DMAR |
1930 | 1919 | ---help--- |
1931 | - Floppy disk drivers are know to bypass DMA API calls | |
1920 | + Floppy disk drivers are known to bypass DMA API calls | |
1932 | 1921 | thereby failing to work when IOMMU is enabled. This |
1933 | 1922 | workaround will setup a 1:1 mapping for the first |
1934 | - 16M to make floppy (an ISA device) work. | |
1923 | + 16MiB to make floppy (an ISA device) work. | |
1935 | 1924 | |
1936 | 1925 | config INTR_REMAP |
1937 | 1926 | bool "Support for Interrupt Remapping (EXPERIMENTAL)" |
drivers/pci/intel-iommu.c
... | ... | @@ -1889,11 +1889,7 @@ |
1889 | 1889 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
1890 | 1890 | pci_name(pdev), start, end); |
1891 | 1891 | |
1892 | - if (iommu_identity_mapping) | |
1893 | - domain = si_domain; | |
1894 | - else | |
1895 | - /* page table init */ | |
1896 | - domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | |
1892 | + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | |
1897 | 1893 | if (!domain) |
1898 | 1894 | return -ENOMEM; |
1899 | 1895 | |
... | ... | @@ -1922,64 +1918,6 @@ |
1922 | 1918 | rmrr->end_address + 1); |
1923 | 1919 | } |
1924 | 1920 | |
1925 | -struct iommu_prepare_data { | |
1926 | - struct pci_dev *pdev; | |
1927 | - int ret; | |
1928 | -}; | |
1929 | - | |
1930 | -static int __init iommu_prepare_work_fn(unsigned long start_pfn, | |
1931 | - unsigned long end_pfn, void *datax) | |
1932 | -{ | |
1933 | - struct iommu_prepare_data *data; | |
1934 | - | |
1935 | - data = (struct iommu_prepare_data *)datax; | |
1936 | - | |
1937 | - data->ret = iommu_prepare_identity_map(data->pdev, | |
1938 | - start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | |
1939 | - return data->ret; | |
1940 | - | |
1941 | -} | |
1942 | - | |
1943 | -static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | |
1944 | -{ | |
1945 | - int nid; | |
1946 | - struct iommu_prepare_data data; | |
1947 | - | |
1948 | - data.pdev = pdev; | |
1949 | - data.ret = 0; | |
1950 | - | |
1951 | - for_each_online_node(nid) { | |
1952 | - work_with_active_regions(nid, iommu_prepare_work_fn, &data); | |
1953 | - if (data.ret) | |
1954 | - return data.ret; | |
1955 | - } | |
1956 | - return data.ret; | |
1957 | -} | |
1958 | - | |
1959 | -#ifdef CONFIG_DMAR_GFX_WA | |
1960 | -static void __init iommu_prepare_gfx_mapping(void) | |
1961 | -{ | |
1962 | - struct pci_dev *pdev = NULL; | |
1963 | - int ret; | |
1964 | - | |
1965 | - for_each_pci_dev(pdev) { | |
1966 | - if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | |
1967 | - !IS_GFX_DEVICE(pdev)) | |
1968 | - continue; | |
1969 | - printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | |
1970 | - pci_name(pdev)); | |
1971 | - ret = iommu_prepare_with_active_regions(pdev); | |
1972 | - if (ret) | |
1973 | - printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | |
1974 | - } | |
1975 | -} | |
1976 | -#else /* !CONFIG_DMAR_GFX_WA */ | |
1977 | -static inline void iommu_prepare_gfx_mapping(void) | |
1978 | -{ | |
1979 | - return; | |
1980 | -} | |
1981 | -#endif | |
1982 | - | |
1983 | 1921 | #ifdef CONFIG_DMAR_FLOPPY_WA |
1984 | 1922 | static inline void iommu_prepare_isa(void) |
1985 | 1923 | { |
1986 | 1924 | |
... | ... | @@ -1990,12 +1928,12 @@ |
1990 | 1928 | if (!pdev) |
1991 | 1929 | return; |
1992 | 1930 | |
1993 | - printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | |
1931 | + printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); | |
1994 | 1932 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
1995 | 1933 | |
1996 | 1934 | if (ret) |
1997 | - printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | |
1998 | - "floppy might not work\n"); | |
1935 | + printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " | |
1936 | + "floppy might not work\n"); | |
1999 | 1937 | |
2000 | 1938 | } |
2001 | 1939 | #else |
2002 | 1940 | |
2003 | 1941 | |
... | ... | @@ -2023,16 +1961,30 @@ |
2023 | 1961 | } |
2024 | 1962 | |
2025 | 1963 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
1964 | + | |
1965 | +static int __init si_domain_work_fn(unsigned long start_pfn, | |
1966 | + unsigned long end_pfn, void *datax) | |
1967 | +{ | |
1968 | + int *ret = datax; | |
1969 | + | |
1970 | + *ret = iommu_domain_identity_map(si_domain, | |
1971 | + (uint64_t)start_pfn << PAGE_SHIFT, | |
1972 | + (uint64_t)end_pfn << PAGE_SHIFT); | |
1973 | + return *ret; | |
1974 | + | |
1975 | +} | |
1976 | + | |
2026 | 1977 | static int si_domain_init(void) |
2027 | 1978 | { |
2028 | 1979 | struct dmar_drhd_unit *drhd; |
2029 | 1980 | struct intel_iommu *iommu; |
2030 | - int ret = 0; | |
1981 | + int nid, ret = 0; | |
2031 | 1982 | |
2032 | 1983 | si_domain = alloc_domain(); |
2033 | 1984 | if (!si_domain) |
2034 | 1985 | return -EFAULT; |
2035 | 1986 | |
1987 | + pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | |
2036 | 1988 | |
2037 | 1989 | for_each_active_iommu(iommu, drhd) { |
2038 | 1990 | ret = iommu_attach_domain(si_domain, iommu); |
... | ... | @@ -2049,6 +2001,12 @@ |
2049 | 2001 | |
2050 | 2002 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
2051 | 2003 | |
2004 | + for_each_online_node(nid) { | |
2005 | + work_with_active_regions(nid, si_domain_work_fn, &ret); | |
2006 | + if (ret) | |
2007 | + return ret; | |
2008 | + } | |
2009 | + | |
2052 | 2010 | return 0; |
2053 | 2011 | } |
2054 | 2012 | |
2055 | 2013 | |
... | ... | @@ -2102,13 +2060,14 @@ |
2102 | 2060 | if (ret) |
2103 | 2061 | return -EFAULT; |
2104 | 2062 | |
2105 | - printk(KERN_INFO "IOMMU: Setting identity map:\n"); | |
2106 | 2063 | for_each_pci_dev(pdev) { |
2107 | - ret = iommu_prepare_with_active_regions(pdev); | |
2108 | - if (ret) { | |
2109 | - printk(KERN_INFO "1:1 mapping to one domain failed.\n"); | |
2110 | - return -EFAULT; | |
2111 | - } | |
2064 | + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", | |
2065 | + pci_name(pdev)); | |
2066 | + | |
2067 | + ret = domain_context_mapping(si_domain, pdev, | |
2068 | + CONTEXT_TT_MULTI_LEVEL); | |
2069 | + if (ret) | |
2070 | + return ret; | |
2112 | 2071 | ret = domain_add_dev_info(si_domain, pdev); |
2113 | 2072 | if (ret) |
2114 | 2073 | return ret; |
... | ... | @@ -2298,8 +2257,6 @@ |
2298 | 2257 | "IOMMU: mapping reserved region failed\n"); |
2299 | 2258 | } |
2300 | 2259 | } |
2301 | - | |
2302 | - iommu_prepare_gfx_mapping(); | |
2303 | 2260 | |
2304 | 2261 | iommu_prepare_isa(); |
2305 | 2262 | } |