diff options
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 218 |
1 files changed, 100 insertions, 118 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 2314ad7ee5fe..3f256b8d83c1 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -251,7 +251,8 @@ static inline int first_pte_in_page(struct dma_pte *pte) | |||
251 | * 2. It maps to each iommu if successful. | 251 | * 2. It maps to each iommu if successful. |
252 | * 3. Each iommu mapps to this domain if successful. | 252 | * 3. Each iommu mapps to this domain if successful. |
253 | */ | 253 | */ |
254 | struct dmar_domain *si_domain; | 254 | static struct dmar_domain *si_domain; |
255 | static int hw_pass_through = 1; | ||
255 | 256 | ||
256 | /* devices under the same p2p bridge are owned in one domain */ | 257 | /* devices under the same p2p bridge are owned in one domain */ |
257 | #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) | 258 | #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) |
@@ -1309,7 +1310,6 @@ static void iommu_detach_domain(struct dmar_domain *domain, | |||
1309 | } | 1310 | } |
1310 | 1311 | ||
1311 | static struct iova_domain reserved_iova_list; | 1312 | static struct iova_domain reserved_iova_list; |
1312 | static struct lock_class_key reserved_alloc_key; | ||
1313 | static struct lock_class_key reserved_rbtree_key; | 1313 | static struct lock_class_key reserved_rbtree_key; |
1314 | 1314 | ||
1315 | static void dmar_init_reserved_ranges(void) | 1315 | static void dmar_init_reserved_ranges(void) |
@@ -1320,8 +1320,6 @@ static void dmar_init_reserved_ranges(void) | |||
1320 | 1320 | ||
1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); | 1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
1322 | 1322 | ||
1323 | lockdep_set_class(&reserved_iova_list.iova_alloc_lock, | ||
1324 | &reserved_alloc_key); | ||
1325 | lockdep_set_class(&reserved_iova_list.iova_rbtree_lock, | 1323 | lockdep_set_class(&reserved_iova_list.iova_rbtree_lock, |
1326 | &reserved_rbtree_key); | 1324 | &reserved_rbtree_key); |
1327 | 1325 | ||
@@ -1958,14 +1956,24 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, | |||
1958 | struct dmar_domain *domain; | 1956 | struct dmar_domain *domain; |
1959 | int ret; | 1957 | int ret; |
1960 | 1958 | ||
1961 | printk(KERN_INFO | ||
1962 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | ||
1963 | pci_name(pdev), start, end); | ||
1964 | |||
1965 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | 1959 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
1966 | if (!domain) | 1960 | if (!domain) |
1967 | return -ENOMEM; | 1961 | return -ENOMEM; |
1968 | 1962 | ||
1963 | /* For _hardware_ passthrough, don't bother. But for software | ||
1964 | passthrough, we do it anyway -- it may indicate a memory | ||
1965 | range which is reserved in E820, so which didn't get set | ||
1966 | up to start with in si_domain */ | ||
1967 | if (domain == si_domain && hw_pass_through) { | ||
1968 | printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n", | ||
1969 | pci_name(pdev), start, end); | ||
1970 | return 0; | ||
1971 | } | ||
1972 | |||
1973 | printk(KERN_INFO | ||
1974 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | ||
1975 | pci_name(pdev), start, end); | ||
1976 | |||
1969 | ret = iommu_domain_identity_map(domain, start, end); | 1977 | ret = iommu_domain_identity_map(domain, start, end); |
1970 | if (ret) | 1978 | if (ret) |
1971 | goto error; | 1979 | goto error; |
@@ -2016,23 +2024,6 @@ static inline void iommu_prepare_isa(void) | |||
2016 | } | 2024 | } |
2017 | #endif /* !CONFIG_DMAR_FLPY_WA */ | 2025 | #endif /* !CONFIG_DMAR_FLPY_WA */ |
2018 | 2026 | ||
2019 | /* Initialize each context entry as pass through.*/ | ||
2020 | static int __init init_context_pass_through(void) | ||
2021 | { | ||
2022 | struct pci_dev *pdev = NULL; | ||
2023 | struct dmar_domain *domain; | ||
2024 | int ret; | ||
2025 | |||
2026 | for_each_pci_dev(pdev) { | ||
2027 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
2028 | ret = domain_context_mapping(domain, pdev, | ||
2029 | CONTEXT_TT_PASS_THROUGH); | ||
2030 | if (ret) | ||
2031 | return ret; | ||
2032 | } | ||
2033 | return 0; | ||
2034 | } | ||
2035 | |||
2036 | static int md_domain_init(struct dmar_domain *domain, int guest_width); | 2027 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
2037 | 2028 | ||
2038 | static int __init si_domain_work_fn(unsigned long start_pfn, | 2029 | static int __init si_domain_work_fn(unsigned long start_pfn, |
@@ -2047,7 +2038,7 @@ static int __init si_domain_work_fn(unsigned long start_pfn, | |||
2047 | 2038 | ||
2048 | } | 2039 | } |
2049 | 2040 | ||
2050 | static int si_domain_init(void) | 2041 | static int si_domain_init(int hw) |
2051 | { | 2042 | { |
2052 | struct dmar_drhd_unit *drhd; | 2043 | struct dmar_drhd_unit *drhd; |
2053 | struct intel_iommu *iommu; | 2044 | struct intel_iommu *iommu; |
@@ -2074,6 +2065,9 @@ static int si_domain_init(void) | |||
2074 | 2065 | ||
2075 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | 2066 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
2076 | 2067 | ||
2068 | if (hw) | ||
2069 | return 0; | ||
2070 | |||
2077 | for_each_online_node(nid) { | 2071 | for_each_online_node(nid) { |
2078 | work_with_active_regions(nid, si_domain_work_fn, &ret); | 2072 | work_with_active_regions(nid, si_domain_work_fn, &ret); |
2079 | if (ret) | 2073 | if (ret) |
@@ -2165,24 +2159,26 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | |||
2165 | return 1; | 2159 | return 1; |
2166 | } | 2160 | } |
2167 | 2161 | ||
2168 | static int iommu_prepare_static_identity_mapping(void) | 2162 | static int iommu_prepare_static_identity_mapping(int hw) |
2169 | { | 2163 | { |
2170 | struct pci_dev *pdev = NULL; | 2164 | struct pci_dev *pdev = NULL; |
2171 | int ret; | 2165 | int ret; |
2172 | 2166 | ||
2173 | ret = si_domain_init(); | 2167 | ret = si_domain_init(hw); |
2174 | if (ret) | 2168 | if (ret) |
2175 | return -EFAULT; | 2169 | return -EFAULT; |
2176 | 2170 | ||
2177 | for_each_pci_dev(pdev) { | 2171 | for_each_pci_dev(pdev) { |
2178 | if (iommu_should_identity_map(pdev, 1)) { | 2172 | if (iommu_should_identity_map(pdev, 1)) { |
2179 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", | 2173 | printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", |
2180 | pci_name(pdev)); | 2174 | hw ? "hardware" : "software", pci_name(pdev)); |
2181 | 2175 | ||
2182 | ret = domain_context_mapping(si_domain, pdev, | 2176 | ret = domain_context_mapping(si_domain, pdev, |
2177 | hw ? CONTEXT_TT_PASS_THROUGH : | ||
2183 | CONTEXT_TT_MULTI_LEVEL); | 2178 | CONTEXT_TT_MULTI_LEVEL); |
2184 | if (ret) | 2179 | if (ret) |
2185 | return ret; | 2180 | return ret; |
2181 | |||
2186 | ret = domain_add_dev_info(si_domain, pdev); | 2182 | ret = domain_add_dev_info(si_domain, pdev); |
2187 | if (ret) | 2183 | if (ret) |
2188 | return ret; | 2184 | return ret; |
@@ -2199,14 +2195,6 @@ int __init init_dmars(void) | |||
2199 | struct pci_dev *pdev; | 2195 | struct pci_dev *pdev; |
2200 | struct intel_iommu *iommu; | 2196 | struct intel_iommu *iommu; |
2201 | int i, ret; | 2197 | int i, ret; |
2202 | int pass_through = 1; | ||
2203 | |||
2204 | /* | ||
2205 | * In case pass through can not be enabled, iommu tries to use identity | ||
2206 | * mapping. | ||
2207 | */ | ||
2208 | if (iommu_pass_through) | ||
2209 | iommu_identity_mapping = 1; | ||
2210 | 2198 | ||
2211 | /* | 2199 | /* |
2212 | * for each drhd | 2200 | * for each drhd |
@@ -2234,7 +2222,6 @@ int __init init_dmars(void) | |||
2234 | deferred_flush = kzalloc(g_num_of_iommus * | 2222 | deferred_flush = kzalloc(g_num_of_iommus * |
2235 | sizeof(struct deferred_flush_tables), GFP_KERNEL); | 2223 | sizeof(struct deferred_flush_tables), GFP_KERNEL); |
2236 | if (!deferred_flush) { | 2224 | if (!deferred_flush) { |
2237 | kfree(g_iommus); | ||
2238 | ret = -ENOMEM; | 2225 | ret = -ENOMEM; |
2239 | goto error; | 2226 | goto error; |
2240 | } | 2227 | } |
@@ -2261,14 +2248,8 @@ int __init init_dmars(void) | |||
2261 | goto error; | 2248 | goto error; |
2262 | } | 2249 | } |
2263 | if (!ecap_pass_through(iommu->ecap)) | 2250 | if (!ecap_pass_through(iommu->ecap)) |
2264 | pass_through = 0; | 2251 | hw_pass_through = 0; |
2265 | } | 2252 | } |
2266 | if (iommu_pass_through) | ||
2267 | if (!pass_through) { | ||
2268 | printk(KERN_INFO | ||
2269 | "Pass Through is not supported by hardware.\n"); | ||
2270 | iommu_pass_through = 0; | ||
2271 | } | ||
2272 | 2253 | ||
2273 | /* | 2254 | /* |
2274 | * Start from the sane iommu hardware state. | 2255 | * Start from the sane iommu hardware state. |
@@ -2323,64 +2304,57 @@ int __init init_dmars(void) | |||
2323 | } | 2304 | } |
2324 | } | 2305 | } |
2325 | 2306 | ||
2307 | if (iommu_pass_through) | ||
2308 | iommu_identity_mapping = 1; | ||
2309 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA | ||
2310 | else | ||
2311 | iommu_identity_mapping = 2; | ||
2312 | #endif | ||
2326 | /* | 2313 | /* |
2327 | * If pass through is set and enabled, context entries of all pci | 2314 | * If pass through is not set or not enabled, setup context entries for |
2328 | * devices are intialized by pass through translation type. | 2315 | * identity mappings for rmrr, gfx, and isa and may fall back to static |
2316 | * identity mapping if iommu_identity_mapping is set. | ||
2329 | */ | 2317 | */ |
2330 | if (iommu_pass_through) { | 2318 | if (iommu_identity_mapping) { |
2331 | ret = init_context_pass_through(); | 2319 | ret = iommu_prepare_static_identity_mapping(hw_pass_through); |
2332 | if (ret) { | 2320 | if (ret) { |
2333 | printk(KERN_ERR "IOMMU: Pass through init failed.\n"); | 2321 | printk(KERN_CRIT "Failed to setup IOMMU pass-through\n"); |
2334 | iommu_pass_through = 0; | 2322 | goto error; |
2335 | } | 2323 | } |
2336 | } | 2324 | } |
2337 | |||
2338 | /* | 2325 | /* |
2339 | * If pass through is not set or not enabled, setup context entries for | 2326 | * For each rmrr |
2340 | * identity mappings for rmrr, gfx, and isa and may fall back to static | 2327 | * for each dev attached to rmrr |
2341 | * identity mapping if iommu_identity_mapping is set. | 2328 | * do |
2329 | * locate drhd for dev, alloc domain for dev | ||
2330 | * allocate free domain | ||
2331 | * allocate page table entries for rmrr | ||
2332 | * if context not allocated for bus | ||
2333 | * allocate and init context | ||
2334 | * set present in root table for this bus | ||
2335 | * init context with domain, translation etc | ||
2336 | * endfor | ||
2337 | * endfor | ||
2342 | */ | 2338 | */ |
2343 | if (!iommu_pass_through) { | 2339 | printk(KERN_INFO "IOMMU: Setting RMRR:\n"); |
2344 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA | 2340 | for_each_rmrr_units(rmrr) { |
2345 | if (!iommu_identity_mapping) | 2341 | for (i = 0; i < rmrr->devices_cnt; i++) { |
2346 | iommu_identity_mapping = 2; | 2342 | pdev = rmrr->devices[i]; |
2347 | #endif | 2343 | /* |
2348 | if (iommu_identity_mapping) | 2344 | * some BIOS lists non-exist devices in DMAR |
2349 | iommu_prepare_static_identity_mapping(); | 2345 | * table. |
2350 | /* | 2346 | */ |
2351 | * For each rmrr | 2347 | if (!pdev) |
2352 | * for each dev attached to rmrr | 2348 | continue; |
2353 | * do | 2349 | ret = iommu_prepare_rmrr_dev(rmrr, pdev); |
2354 | * locate drhd for dev, alloc domain for dev | 2350 | if (ret) |
2355 | * allocate free domain | 2351 | printk(KERN_ERR |
2356 | * allocate page table entries for rmrr | 2352 | "IOMMU: mapping reserved region failed\n"); |
2357 | * if context not allocated for bus | ||
2358 | * allocate and init context | ||
2359 | * set present in root table for this bus | ||
2360 | * init context with domain, translation etc | ||
2361 | * endfor | ||
2362 | * endfor | ||
2363 | */ | ||
2364 | printk(KERN_INFO "IOMMU: Setting RMRR:\n"); | ||
2365 | for_each_rmrr_units(rmrr) { | ||
2366 | for (i = 0; i < rmrr->devices_cnt; i++) { | ||
2367 | pdev = rmrr->devices[i]; | ||
2368 | /* | ||
2369 | * some BIOS lists non-exist devices in DMAR | ||
2370 | * table. | ||
2371 | */ | ||
2372 | if (!pdev) | ||
2373 | continue; | ||
2374 | ret = iommu_prepare_rmrr_dev(rmrr, pdev); | ||
2375 | if (ret) | ||
2376 | printk(KERN_ERR | ||
2377 | "IOMMU: mapping reserved region failed\n"); | ||
2378 | } | ||
2379 | } | 2353 | } |
2380 | |||
2381 | iommu_prepare_isa(); | ||
2382 | } | 2354 | } |
2383 | 2355 | ||
2356 | iommu_prepare_isa(); | ||
2357 | |||
2384 | /* | 2358 | /* |
2385 | * for each drhd | 2359 | * for each drhd |
2386 | * enable fault log | 2360 | * enable fault log |
@@ -2454,8 +2428,7 @@ static struct iova *intel_alloc_iova(struct device *dev, | |||
2454 | return iova; | 2428 | return iova; |
2455 | } | 2429 | } |
2456 | 2430 | ||
2457 | static struct dmar_domain * | 2431 | static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev) |
2458 | get_valid_domain_for_dev(struct pci_dev *pdev) | ||
2459 | { | 2432 | { |
2460 | struct dmar_domain *domain; | 2433 | struct dmar_domain *domain; |
2461 | int ret; | 2434 | int ret; |
@@ -2483,6 +2456,18 @@ get_valid_domain_for_dev(struct pci_dev *pdev) | |||
2483 | return domain; | 2456 | return domain; |
2484 | } | 2457 | } |
2485 | 2458 | ||
2459 | static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev) | ||
2460 | { | ||
2461 | struct device_domain_info *info; | ||
2462 | |||
2463 | /* No lock here, assumes no domain exit in normal case */ | ||
2464 | info = dev->dev.archdata.iommu; | ||
2465 | if (likely(info)) | ||
2466 | return info->domain; | ||
2467 | |||
2468 | return __get_valid_domain_for_dev(dev); | ||
2469 | } | ||
2470 | |||
2486 | static int iommu_dummy(struct pci_dev *pdev) | 2471 | static int iommu_dummy(struct pci_dev *pdev) |
2487 | { | 2472 | { |
2488 | return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; | 2473 | return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; |
@@ -2528,7 +2513,10 @@ static int iommu_no_mapping(struct device *dev) | |||
2528 | ret = domain_add_dev_info(si_domain, pdev); | 2513 | ret = domain_add_dev_info(si_domain, pdev); |
2529 | if (ret) | 2514 | if (ret) |
2530 | return 0; | 2515 | return 0; |
2531 | ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 2516 | ret = domain_context_mapping(si_domain, pdev, |
2517 | hw_pass_through ? | ||
2518 | CONTEXT_TT_PASS_THROUGH : | ||
2519 | CONTEXT_TT_MULTI_LEVEL); | ||
2532 | if (!ret) { | 2520 | if (!ret) { |
2533 | printk(KERN_INFO "64bit %s uses identity mapping\n", | 2521 | printk(KERN_INFO "64bit %s uses identity mapping\n", |
2534 | pci_name(pdev)); | 2522 | pci_name(pdev)); |
@@ -2733,12 +2721,6 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2733 | } | 2721 | } |
2734 | } | 2722 | } |
2735 | 2723 | ||
2736 | static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size, | ||
2737 | int dir) | ||
2738 | { | ||
2739 | intel_unmap_page(dev, dev_addr, size, dir, NULL); | ||
2740 | } | ||
2741 | |||
2742 | static void *intel_alloc_coherent(struct device *hwdev, size_t size, | 2724 | static void *intel_alloc_coherent(struct device *hwdev, size_t size, |
2743 | dma_addr_t *dma_handle, gfp_t flags) | 2725 | dma_addr_t *dma_handle, gfp_t flags) |
2744 | { | 2726 | { |
@@ -2771,7 +2753,7 @@ static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr, | |||
2771 | size = PAGE_ALIGN(size); | 2753 | size = PAGE_ALIGN(size); |
2772 | order = get_order(size); | 2754 | order = get_order(size); |
2773 | 2755 | ||
2774 | intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL); | 2756 | intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL); |
2775 | free_pages((unsigned long)vaddr, order); | 2757 | free_pages((unsigned long)vaddr, order); |
2776 | } | 2758 | } |
2777 | 2759 | ||
@@ -2807,11 +2789,18 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2807 | /* free page tables */ | 2789 | /* free page tables */ |
2808 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); | 2790 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
2809 | 2791 | ||
2810 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, | 2792 | if (intel_iommu_strict) { |
2811 | (last_pfn - start_pfn + 1)); | 2793 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2812 | 2794 | last_pfn - start_pfn + 1); | |
2813 | /* free iova */ | 2795 | /* free iova */ |
2814 | __free_iova(&domain->iovad, iova); | 2796 | __free_iova(&domain->iovad, iova); |
2797 | } else { | ||
2798 | add_unmap(domain, iova); | ||
2799 | /* | ||
2800 | * queue up the release of the unmap to save the 1/6th of the | ||
2801 | * cpu used up by the iotlb flush operation... | ||
2802 | */ | ||
2803 | } | ||
2815 | } | 2804 | } |
2816 | 2805 | ||
2817 | static int intel_nontranslate_map_sg(struct device *hddev, | 2806 | static int intel_nontranslate_map_sg(struct device *hddev, |
@@ -3194,7 +3183,7 @@ int __init intel_iommu_init(void) | |||
3194 | * Check the need for DMA-remapping initialization now. | 3183 | * Check the need for DMA-remapping initialization now. |
3195 | * Above initialization will also be used by Interrupt-remapping. | 3184 | * Above initialization will also be used by Interrupt-remapping. |
3196 | */ | 3185 | */ |
3197 | if (no_iommu || (swiotlb && !iommu_pass_through) || dmar_disabled) | 3186 | if (no_iommu || swiotlb || dmar_disabled) |
3198 | return -ENODEV; | 3187 | return -ENODEV; |
3199 | 3188 | ||
3200 | iommu_init_mempool(); | 3189 | iommu_init_mempool(); |
@@ -3214,14 +3203,7 @@ int __init intel_iommu_init(void) | |||
3214 | 3203 | ||
3215 | init_timer(&unmap_timer); | 3204 | init_timer(&unmap_timer); |
3216 | force_iommu = 1; | 3205 | force_iommu = 1; |
3217 | 3206 | dma_ops = &intel_dma_ops; | |
3218 | if (!iommu_pass_through) { | ||
3219 | printk(KERN_INFO | ||
3220 | "Multi-level page-table translation for DMAR.\n"); | ||
3221 | dma_ops = &intel_dma_ops; | ||
3222 | } else | ||
3223 | printk(KERN_INFO | ||
3224 | "DMAR: Pass through translation for DMAR.\n"); | ||
3225 | 3207 | ||
3226 | init_iommu_sysfs(); | 3208 | init_iommu_sysfs(); |
3227 | 3209 | ||