blob: a49afa11673cc5aae3e346a9429cbe412ec8d84e [file] [log] [blame]
Thomas Gleixner2025cf92019-05-29 07:18:02 -07001// SPDX-License-Identifier: GPL-2.0-only
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002/*
David Woodhouseea8ea462014-03-05 17:09:32 +00003 * Copyright © 2006-2014 Intel Corporation.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004 *
David Woodhouseea8ea462014-03-05 17:09:32 +00005 * Authors: David Woodhouse <dwmw2@infradead.org>,
6 * Ashok Raj <ashok.raj@intel.com>,
7 * Shaohua Li <shaohua.li@intel.com>,
8 * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
9 * Fenghua Yu <fenghua.yu@intel.com>
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020010 * Joerg Roedel <jroedel@suse.de>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070011 */
12
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020013#define pr_fmt(fmt) "DMAR: " fmt
Bjorn Helgaas932a6522019-02-08 16:06:00 -060014#define dev_fmt(fmt) pr_fmt(fmt)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020015
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070016#include <linux/init.h>
17#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080018#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040019#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070020#include <linux/slab.h>
21#include <linux/irq.h>
22#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070023#include <linux/spinlock.h>
24#include <linux/pci.h>
25#include <linux/dmar.h>
Christoph Hellwig0a0f0d82020-09-22 15:31:03 +020026#include <linux/dma-map-ops.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070027#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080028#include <linux/memory.h>
Omer Pelegaa473242016-04-20 11:33:02 +030029#include <linux/cpu.h>
mark gross5e0d2a62008-03-04 15:22:08 -080030#include <linux/timer.h>
Dan Williamsdfddb962015-10-09 18:16:46 -040031#include <linux/io.h>
Kay, Allen M38717942008-09-09 18:37:29 +030032#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010033#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030034#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010035#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070036#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100037#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020038#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080039#include <linux/memblock.h>
Christoph Hellwig0b1abd12020-09-11 10:56:52 +020040#include <linux/dma-map-ops.h>
Christoph Hellwigfec777c2018-03-19 11:38:15 +010041#include <linux/dma-direct.h>
Joerg Roedel091d42e2015-06-12 11:56:10 +020042#include <linux/crash_dump.h>
Anshuman Khandual98fa15f2019-03-05 15:42:58 -080043#include <linux/numa.h>
Lu Baolucfb94a32019-09-06 14:14:52 +080044#include <linux/swiotlb.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070045#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070046#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090047#include <asm/iommu.h>
Lu Baolucfb94a32019-09-06 14:14:52 +080048#include <trace/events/intel_iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070049
Joerg Roedel672cf6d2020-06-09 15:03:03 +020050#include "../irq_remapping.h"
Lu Baolu02f3eff2020-07-24 09:49:25 +080051#include "pasid.h"
Joerg Roedel078e1ee2012-09-26 12:44:43 +020052
Fenghua Yu5b6985c2008-10-16 18:02:32 -070053#define ROOT_SIZE VTD_PAGE_SIZE
54#define CONTEXT_SIZE VTD_PAGE_SIZE
55
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070056#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000057#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070058#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070059#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070060
61#define IOAPIC_RANGE_START (0xfee00000)
62#define IOAPIC_RANGE_END (0xfeefffff)
63#define IOVA_START_ADDR (0x1000)
64
Sohil Mehta5e3b4a12017-12-20 11:59:24 -080065#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070066
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070067#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080068#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070069
David Woodhouse2ebe3152009-09-19 07:34:04 -070070#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
71#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
72
73/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
74 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
75#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
76 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
77#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070078
Robin Murphy1b722502015-01-12 17:51:15 +000079/* IO virtual address start page frame number */
80#define IOVA_START_PFN (1)
81
Mark McLoughlinf27be032008-11-20 15:49:43 +000082#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
mark gross5e0d2a62008-03-04 15:22:08 -080083
Andrew Mortondf08cdc2010-09-22 13:05:11 -070084/* page table handling */
85#define LEVEL_STRIDE (9)
86#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
87
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020088/*
89 * This bitmap is used to advertise the page sizes our hardware support
90 * to the IOMMU core, which will then use this information to split
91 * physically contiguous memory regions it is mapping into page sizes
92 * that we support.
93 *
94 * Traditionally the IOMMU core just handed us the mappings directly,
95 * after making sure the size is an order of a 4KiB page and that the
96 * mapping has natural alignment.
97 *
98 * To retain this behavior, we currently advertise that we support
99 * all page sizes that are an order of 4KiB.
100 *
101 * If at some point we'd like to utilize the IOMMU core's new behavior,
102 * we could change this to advertise the real page sizes we support.
103 */
104#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
105
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700106static inline int agaw_to_level(int agaw)
107{
108 return agaw + 2;
109}
110
111static inline int agaw_to_width(int agaw)
112{
Jiang Liu5c645b32014-01-06 14:18:12 +0800113 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700114}
115
116static inline int width_to_agaw(int width)
117{
Jiang Liu5c645b32014-01-06 14:18:12 +0800118 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700119}
120
121static inline unsigned int level_to_offset_bits(int level)
122{
123 return (level - 1) * LEVEL_STRIDE;
124}
125
Chris Wilson29aaebb2020-08-22 17:02:09 +0100126static inline int pfn_level_offset(u64 pfn, int level)
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700127{
128 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
129}
130
Chris Wilson29aaebb2020-08-22 17:02:09 +0100131static inline u64 level_mask(int level)
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700132{
Chris Wilson29aaebb2020-08-22 17:02:09 +0100133 return -1ULL << level_to_offset_bits(level);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700134}
135
Chris Wilson29aaebb2020-08-22 17:02:09 +0100136static inline u64 level_size(int level)
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700137{
Chris Wilson29aaebb2020-08-22 17:02:09 +0100138 return 1ULL << level_to_offset_bits(level);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700139}
140
Chris Wilson29aaebb2020-08-22 17:02:09 +0100141static inline u64 align_to_level(u64 pfn, int level)
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700142{
143 return (pfn + level_size(level) - 1) & level_mask(level);
144}
David Woodhousefd18de52009-05-10 23:57:41 +0100145
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100146static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
147{
Chris Wilson29aaebb2020-08-22 17:02:09 +0100148 return 1UL << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100149}
150
David Woodhousedd4e8312009-06-27 16:21:20 +0100151/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
152 are never going to work. */
153static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
154{
155 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
156}
157
158static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
159{
160 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
161}
162static inline unsigned long page_to_dma_pfn(struct page *pg)
163{
164 return mm_to_dma_pfn(page_to_pfn(pg));
165}
166static inline unsigned long virt_to_dma_pfn(void *p)
167{
168 return page_to_dma_pfn(virt_to_page(p));
169}
170
Weidong Hand9630fe2008-12-08 11:06:32 +0800171/* global iommu list, set NULL for ignored DMAR units */
172static struct intel_iommu **g_iommus;
173
David Woodhousee0fc7e02009-09-30 09:12:17 -0700174static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000175static int rwbf_quirk;
176
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000177/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700178 * set to 1 to panic kernel if can't successfully enable VT-d
179 * (used when kernel is launched w/ TXT)
180 */
181static int force_on = 0;
Zhenzhong Duan4d213e72020-11-10 15:19:08 +0800182static int intel_iommu_tboot_noforce;
Lu Baolu89a60792018-10-23 15:45:01 +0800183static int no_platform_optin;
Joseph Cihulab7792602011-05-03 00:08:37 -0700184
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000185#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000186
Joerg Roedel091d42e2015-06-12 11:56:10 +0200187/*
188 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
189 * if marked present.
190 */
191static phys_addr_t root_entry_lctp(struct root_entry *re)
192{
193 if (!(re->lo & 1))
194 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000195
Joerg Roedel091d42e2015-06-12 11:56:10 +0200196 return re->lo & VTD_PAGE_MASK;
197}
198
199/*
200 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
201 * if marked present.
202 */
203static phys_addr_t root_entry_uctp(struct root_entry *re)
204{
205 if (!(re->hi & 1))
206 return 0;
207
208 return re->hi & VTD_PAGE_MASK;
209}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000210
Joerg Roedelcf484d02015-06-12 12:21:46 +0200211static inline void context_clear_pasid_enable(struct context_entry *context)
212{
213 context->lo &= ~(1ULL << 11);
214}
215
216static inline bool context_pasid_enabled(struct context_entry *context)
217{
218 return !!(context->lo & (1ULL << 11));
219}
220
221static inline void context_set_copied(struct context_entry *context)
222{
223 context->hi |= (1ull << 3);
224}
225
226static inline bool context_copied(struct context_entry *context)
227{
228 return !!(context->hi & (1ULL << 3));
229}
230
231static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000232{
233 return (context->lo & 1);
234}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200235
Sohil Mehta26b86092018-09-11 17:11:36 -0700236bool context_present(struct context_entry *context)
Joerg Roedelcf484d02015-06-12 12:21:46 +0200237{
238 return context_pasid_enabled(context) ?
239 __context_present(context) :
240 __context_present(context) && !context_copied(context);
241}
242
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000243static inline void context_set_present(struct context_entry *context)
244{
245 context->lo |= 1;
246}
247
248static inline void context_set_fault_enable(struct context_entry *context)
249{
250 context->lo &= (((u64)-1) << 2) | 1;
251}
252
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000253static inline void context_set_translation_type(struct context_entry *context,
254 unsigned long value)
255{
256 context->lo &= (((u64)-1) << 4) | 3;
257 context->lo |= (value & 3) << 2;
258}
259
260static inline void context_set_address_root(struct context_entry *context,
261 unsigned long value)
262{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800263 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000264 context->lo |= value & VTD_PAGE_MASK;
265}
266
267static inline void context_set_address_width(struct context_entry *context,
268 unsigned long value)
269{
270 context->hi |= value & 7;
271}
272
273static inline void context_set_domain_id(struct context_entry *context,
274 unsigned long value)
275{
276 context->hi |= (value & ((1 << 16) - 1)) << 8;
277}
278
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200279static inline int context_domain_id(struct context_entry *c)
280{
281 return((c->hi >> 8) & 0xffff);
282}
283
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000284static inline void context_clear_entry(struct context_entry *context)
285{
286 context->lo = 0;
287 context->hi = 0;
288}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000289
Mark McLoughlin622ba122008-11-20 15:49:46 +0000290/*
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700291 * This domain is a statically identity mapping domain.
292 * 1. This domain creats a static 1:1 mapping to all usable memory.
293 * 2. It maps to each iommu if successful.
294 * 3. Each iommu mapps to this domain if successful.
295 */
David Woodhouse19943b02009-08-04 16:19:20 +0100296static struct dmar_domain *si_domain;
297static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700298
Joerg Roedel29a27712015-07-21 17:17:12 +0200299#define for_each_domain_iommu(idx, domain) \
300 for (idx = 0; idx < g_num_of_iommus; idx++) \
301 if (domain->iommu_refcnt[idx])
302
Jiang Liub94e4112014-02-19 14:07:25 +0800303struct dmar_rmrr_unit {
304 struct list_head list; /* list of rmrr units */
305 struct acpi_dmar_header *hdr; /* ACPI header */
306 u64 base_address; /* reserved base address*/
307 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000308 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800309 int devices_cnt; /* target device count */
310};
311
312struct dmar_atsr_unit {
313 struct list_head list; /* list of ATSR units */
314 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000315 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800316 int devices_cnt; /* target device count */
317 u8 include_all:1; /* include all ports */
318};
319
320static LIST_HEAD(dmar_atsr_units);
321static LIST_HEAD(dmar_rmrr_units);
322
323#define for_each_rmrr_units(rmrr) \
324 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
325
mark gross5e0d2a62008-03-04 15:22:08 -0800326/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800327static int g_num_of_iommus;
328
Jiang Liu92d03cc2014-02-19 14:07:28 +0800329static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700330static void domain_remove_dev_info(struct dmar_domain *domain);
Bjorn Helgaas71753232019-02-08 16:06:15 -0600331static void dmar_remove_one_dev_info(struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200332static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Lu Baolu8af46c72019-05-25 13:41:32 +0800333static int intel_iommu_attach_device(struct iommu_domain *domain,
334 struct device *dev);
Lu Baolucfb94a32019-09-06 14:14:52 +0800335static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
336 dma_addr_t iova);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700337
Suresh Siddhad3f13812011-08-23 17:05:25 -0700338#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800339int dmar_disabled = 0;
340#else
341int dmar_disabled = 1;
Lu Baolu04618252020-01-02 08:18:02 +0800342#endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800343
Lu Baoluba61c3d2020-05-01 15:24:27 +0800344#ifdef CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
Lu Baolu04618252020-01-02 08:18:02 +0800345int intel_iommu_sm = 1;
346#else
Sai Praneeth Prakhyacdd3a242019-05-24 16:40:16 -0700347int intel_iommu_sm;
Lu Baoluba61c3d2020-05-01 15:24:27 +0800348#endif /* CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON */
Lu Baolu04618252020-01-02 08:18:02 +0800349
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200350int intel_iommu_enabled = 0;
351EXPORT_SYMBOL_GPL(intel_iommu_enabled);
352
David Woodhouse2d9e6672010-06-15 10:57:57 +0100353static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700354static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800355static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100356static int intel_iommu_superpage = 1;
David Woodhouseae853dd2015-09-09 11:58:59 +0100357static int iommu_identity_mapping;
Lu Baolue5e04d02019-09-06 14:14:49 +0800358static int intel_no_bounce;
Lu Baolub1012ca2020-07-23 09:34:37 +0800359static int iommu_skip_te_disable;
David Woodhousec83b2f22015-06-12 10:15:49 +0100360
David Woodhouseae853dd2015-09-09 11:58:59 +0100361#define IDENTMAP_GFX 2
362#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100363
David Woodhousec0771df2011-10-14 20:59:46 +0100364int intel_iommu_gfx_mapped;
365EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
366
Lu Baolu8af46c72019-05-25 13:41:32 +0800367#define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2))
Lu Baolue85bb992020-05-16 14:20:52 +0800368struct device_domain_info *get_domain_info(struct device *dev)
369{
370 struct device_domain_info *info;
371
372 if (!dev)
373 return NULL;
374
Joerg Roedel01b9d4e2020-06-25 15:08:25 +0200375 info = dev_iommu_priv_get(dev);
Lu Baolu2d33b7d2020-09-03 14:51:32 +0800376 if (unlikely(info == DEFER_DEVICE_DOMAIN_INFO))
Lu Baolue85bb992020-05-16 14:20:52 +0800377 return NULL;
378
379 return info;
380}
381
Lu Baolue2726da2020-01-02 08:18:22 +0800382DEFINE_SPINLOCK(device_domain_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700383static LIST_HEAD(device_domain_list);
384
Lu Baolue5e04d02019-09-06 14:14:49 +0800385#define device_needs_bounce(d) (!intel_no_bounce && dev_is_pci(d) && \
386 to_pci_dev(d)->untrusted)
387
Lu Baolu85319dc2018-07-14 15:46:58 +0800388/*
389 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800390 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800391 */
392int for_each_device_domain(int (*fn)(struct device_domain_info *info,
393 void *data), void *data)
394{
395 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800396 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800397 struct device_domain_info *info;
398
Lu Baolu0bbeb012018-12-10 09:58:56 +0800399 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800400 list_for_each_entry(info, &device_domain_list, global) {
401 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800402 if (ret) {
403 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800404 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800405 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800406 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800407 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800408
409 return 0;
410}
411
Joerg Roedelb0119e82017-02-01 13:23:08 +0100412const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100413
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200414static bool translation_pre_enabled(struct intel_iommu *iommu)
415{
416 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
417}
418
Joerg Roedel091d42e2015-06-12 11:56:10 +0200419static void clear_translation_pre_enabled(struct intel_iommu *iommu)
420{
421 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
422}
423
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200424static void init_translation_status(struct intel_iommu *iommu)
425{
426 u32 gsts;
427
428 gsts = readl(iommu->reg + DMAR_GSTS_REG);
429 if (gsts & DMA_GSTS_TES)
430 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
431}
432
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700433static int __init intel_iommu_setup(char *str)
434{
435 if (!str)
436 return -EINVAL;
437 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800438 if (!strncmp(str, "on", 2)) {
439 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200440 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800441 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700442 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800443 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200444 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700445 } else if (!strncmp(str, "igfx_off", 8)) {
446 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200447 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700448 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200449 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700450 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800451 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200452 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800453 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100454 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200455 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100456 intel_iommu_superpage = 0;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800457 } else if (!strncmp(str, "sm_on", 5)) {
458 pr_info("Intel-IOMMU: scalable mode supported\n");
459 intel_iommu_sm = 1;
Shaohua Libfd20f12017-04-26 09:18:35 -0700460 } else if (!strncmp(str, "tboot_noforce", 13)) {
Andy Shevchenko86278922020-05-07 19:18:02 +0300461 pr_info("Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
Shaohua Libfd20f12017-04-26 09:18:35 -0700462 intel_iommu_tboot_noforce = 1;
Lu Baolue5e04d02019-09-06 14:14:49 +0800463 } else if (!strncmp(str, "nobounce", 8)) {
464 pr_info("Intel-IOMMU: No bounce buffer. This could expose security risks of DMA attacks\n");
465 intel_no_bounce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700466 }
467
468 str += strcspn(str, ",");
469 while (*str == ',')
470 str++;
471 }
472 return 0;
473}
474__setup("intel_iommu=", intel_iommu_setup);
475
476static struct kmem_cache *iommu_domain_cache;
477static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700478
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200479static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
480{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200481 struct dmar_domain **domains;
482 int idx = did >> 8;
483
484 domains = iommu->domains[idx];
485 if (!domains)
486 return NULL;
487
488 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200489}
490
491static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
492 struct dmar_domain *domain)
493{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200494 struct dmar_domain **domains;
495 int idx = did >> 8;
496
497 if (!iommu->domains[idx]) {
498 size_t size = 256 * sizeof(struct dmar_domain *);
499 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
500 }
501
502 domains = iommu->domains[idx];
503 if (WARN_ON(!domains))
504 return;
505 else
506 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200507}
508
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800509void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700510{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700511 struct page *page;
512 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700513
Suresh Siddha4c923d42009-10-02 11:01:24 -0700514 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
515 if (page)
516 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700517 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700518}
519
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800520void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700521{
522 free_page((unsigned long)vaddr);
523}
524
525static inline void *alloc_domain_mem(void)
526{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900527 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700528}
529
Kay, Allen M38717942008-09-09 18:37:29 +0300530static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700531{
532 kmem_cache_free(iommu_domain_cache, vaddr);
533}
534
535static inline void * alloc_devinfo_mem(void)
536{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900537 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700538}
539
540static inline void free_devinfo_mem(void *vaddr)
541{
542 kmem_cache_free(iommu_devinfo_cache, vaddr);
543}
544
Joerg Roedel28ccce02015-07-21 14:45:31 +0200545static inline int domain_type_is_si(struct dmar_domain *domain)
546{
547 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
548}
549
Lu Baoluddf09b62020-01-02 08:18:17 +0800550static inline bool domain_use_first_level(struct dmar_domain *domain)
551{
552 return domain->flags & DOMAIN_FLAG_USE_FIRST_LEVEL;
553}
554
Jiang Liu162d1b12014-07-11 14:19:35 +0800555static inline int domain_pfn_supported(struct dmar_domain *domain,
556 unsigned long pfn)
557{
558 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
559
560 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
561}
562
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700563static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800564{
565 unsigned long sagaw;
566 int agaw = -1;
567
568 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700569 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800570 agaw >= 0; agaw--) {
571 if (test_bit(agaw, &sagaw))
572 break;
573 }
574
575 return agaw;
576}
577
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700578/*
579 * Calculate max SAGAW for each iommu.
580 */
581int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
582{
583 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
584}
585
586/*
587 * calculate agaw for each iommu.
588 * "SAGAW" may be different across iommus, use a default agaw, and
589 * get a supported less agaw for iommus that don't support the default agaw.
590 */
591int iommu_calculate_agaw(struct intel_iommu *iommu)
592{
593 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
594}
595
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700596/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800597struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800598{
599 int iommu_id;
600
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700601 /* si_domain and vm domain should not get here. */
Lu Baolufa954e62019-05-25 13:41:28 +0800602 if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_DMA))
603 return NULL;
604
Joerg Roedel29a27712015-07-21 17:17:12 +0200605 for_each_domain_iommu(iommu_id, domain)
606 break;
607
Weidong Han8c11e792008-12-08 15:29:22 +0800608 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
609 return NULL;
610
611 return g_iommus[iommu_id];
612}
613
Lu Baolu04c00952020-06-23 07:13:44 +0800614static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu)
615{
616 return sm_supported(iommu) ?
617 ecap_smpwc(iommu->ecap) : ecap_coherent(iommu->ecap);
618}
619
Weidong Han8e6040972008-12-08 15:49:06 +0800620static void domain_update_iommu_coherency(struct dmar_domain *domain)
621{
David Woodhoused0501962014-03-11 17:10:29 -0700622 struct dmar_drhd_unit *drhd;
623 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100624 bool found = false;
625 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800626
David Woodhoused0501962014-03-11 17:10:29 -0700627 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800628
Joerg Roedel29a27712015-07-21 17:17:12 +0200629 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100630 found = true;
Lu Baolu04c00952020-06-23 07:13:44 +0800631 if (!iommu_paging_structure_coherency(g_iommus[i])) {
Weidong Han8e6040972008-12-08 15:49:06 +0800632 domain->iommu_coherency = 0;
633 break;
634 }
Weidong Han8e6040972008-12-08 15:49:06 +0800635 }
David Woodhoused0501962014-03-11 17:10:29 -0700636 if (found)
637 return;
638
639 /* No hardware attached; use lowest common denominator */
640 rcu_read_lock();
641 for_each_active_iommu(iommu, drhd) {
Lu Baolu04c00952020-06-23 07:13:44 +0800642 if (!iommu_paging_structure_coherency(iommu)) {
David Woodhoused0501962014-03-11 17:10:29 -0700643 domain->iommu_coherency = 0;
644 break;
645 }
646 }
647 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800648}
649
Jiang Liu161f6932014-07-11 14:19:37 +0800650static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100651{
Allen Kay8140a952011-10-14 12:32:17 -0700652 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800653 struct intel_iommu *iommu;
654 int ret = 1;
655
656 rcu_read_lock();
657 for_each_active_iommu(iommu, drhd) {
658 if (iommu != skip) {
659 if (!ecap_sc_support(iommu->ecap)) {
660 ret = 0;
661 break;
662 }
663 }
664 }
665 rcu_read_unlock();
666
667 return ret;
668}
669
Lu Baolu64229e82020-01-02 08:18:20 +0800670static int domain_update_iommu_superpage(struct dmar_domain *domain,
671 struct intel_iommu *skip)
Jiang Liu161f6932014-07-11 14:19:37 +0800672{
673 struct dmar_drhd_unit *drhd;
674 struct intel_iommu *iommu;
Lu Baolu64229e82020-01-02 08:18:20 +0800675 int mask = 0x3;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100676
677 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800678 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100679 }
680
Allen Kay8140a952011-10-14 12:32:17 -0700681 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800682 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700683 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800684 if (iommu != skip) {
Lu Baolu64229e82020-01-02 08:18:20 +0800685 if (domain && domain_use_first_level(domain)) {
686 if (!cap_fl1gp_support(iommu->cap))
687 mask = 0x1;
688 } else {
689 mask &= cap_super_page_val(iommu->cap);
690 }
691
Jiang Liu161f6932014-07-11 14:19:37 +0800692 if (!mask)
693 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100694 }
695 }
Jiang Liu0e242612014-02-19 14:07:34 +0800696 rcu_read_unlock();
697
Jiang Liu161f6932014-07-11 14:19:37 +0800698 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100699}
700
Lu Baolud2ef0962020-09-22 14:08:43 +0800701static int domain_update_device_node(struct dmar_domain *domain)
702{
703 struct device_domain_info *info;
704 int nid = NUMA_NO_NODE;
705
706 assert_spin_locked(&device_domain_lock);
707
708 if (list_empty(&domain->devices))
709 return NUMA_NO_NODE;
710
711 list_for_each_entry(info, &domain->devices, link) {
712 if (!info->dev)
713 continue;
714
715 /*
716 * There could possibly be multiple device numa nodes as devices
717 * within the same domain may sit behind different IOMMUs. There
718 * isn't perfect answer in such situation, so we select first
719 * come first served policy.
720 */
721 nid = dev_to_node(info->dev);
722 if (nid != NUMA_NO_NODE)
723 break;
724 }
725
726 return nid;
727}
728
Sheng Yang58c610b2009-03-18 15:33:05 +0800729/* Some capabilities may be different across iommus */
730static void domain_update_iommu_cap(struct dmar_domain *domain)
731{
732 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800733 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
Lu Baolu64229e82020-01-02 08:18:20 +0800734 domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL);
Lu Baolud2ef0962020-09-22 14:08:43 +0800735
736 /*
737 * If RHSA is missing, we should default to the device numa domain
738 * as fall back.
739 */
740 if (domain->nid == NUMA_NO_NODE)
741 domain->nid = domain_update_device_node(domain);
Sheng Yang58c610b2009-03-18 15:33:05 +0800742}
743
Sohil Mehta26b86092018-09-11 17:11:36 -0700744struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
745 u8 devfn, int alloc)
David Woodhouse03ecc322015-02-13 14:35:21 +0000746{
747 struct root_entry *root = &iommu->root_entry[bus];
748 struct context_entry *context;
749 u64 *entry;
750
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200751 entry = &root->lo;
Lu Baolu765b6a92018-12-10 09:58:55 +0800752 if (sm_supported(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000753 if (devfn >= 0x80) {
754 devfn -= 0x80;
755 entry = &root->hi;
756 }
757 devfn *= 2;
758 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000759 if (*entry & 1)
760 context = phys_to_virt(*entry & VTD_PAGE_MASK);
761 else {
762 unsigned long phy_addr;
763 if (!alloc)
764 return NULL;
765
766 context = alloc_pgtable_page(iommu->node);
767 if (!context)
768 return NULL;
769
770 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
771 phy_addr = virt_to_phys((void *)context);
772 *entry = phy_addr | 1;
773 __iommu_flush_cache(iommu, entry, sizeof(*entry));
774 }
775 return &context[devfn];
776}
777
Joerg Roedel1d46159782020-02-17 17:12:37 +0100778static bool attach_deferred(struct device *dev)
779{
Joerg Roedel01b9d4e2020-06-25 15:08:25 +0200780 return dev_iommu_priv_get(dev) == DEFER_DEVICE_DOMAIN_INFO;
Joerg Roedel1d46159782020-02-17 17:12:37 +0100781}
782
Eric Augerb9a7f982019-06-03 08:53:32 +0200783/**
784 * is_downstream_to_pci_bridge - test if a device belongs to the PCI
785 * sub-hierarchy of a candidate PCI-PCI bridge
786 * @dev: candidate PCI device belonging to @bridge PCI sub-hierarchy
787 * @bridge: the candidate PCI-PCI bridge
788 *
789 * Return: true if @dev belongs to @bridge PCI sub-hierarchy, else false.
790 */
791static bool
792is_downstream_to_pci_bridge(struct device *dev, struct device *bridge)
793{
794 struct pci_dev *pdev, *pbridge;
795
796 if (!dev_is_pci(dev) || !dev_is_pci(bridge))
797 return false;
798
799 pdev = to_pci_dev(dev);
800 pbridge = to_pci_dev(bridge);
801
802 if (pbridge->subordinate &&
803 pbridge->subordinate->number <= pdev->bus->number &&
804 pbridge->subordinate->busn_res.end >= pdev->bus->number)
805 return true;
806
807 return false;
808}
809
Lu Baolu2d33b7d2020-09-03 14:51:32 +0800810static bool quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
811{
812 struct dmar_drhd_unit *drhd;
813 u32 vtbar;
814 int rc;
815
816 /* We know that this device on this chipset has its own IOMMU.
817 * If we find it under a different IOMMU, then the BIOS is lying
818 * to us. Hope that the IOMMU for this device is actually
819 * disabled, and it needs no translation...
820 */
821 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
822 if (rc) {
823 /* "can't" happen */
824 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
825 return false;
826 }
827 vtbar &= 0xffff0000;
828
829 /* we know that the this iommu should be at offset 0xa000 from vtbar */
830 drhd = dmar_find_matched_drhd_unit(pdev);
831 if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) {
832 pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n");
833 add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
834 return true;
835 }
836
837 return false;
838}
839
840static bool iommu_is_dummy(struct intel_iommu *iommu, struct device *dev)
841{
842 if (!iommu || iommu->drhd->ignored)
843 return true;
844
845 if (dev_is_pci(dev)) {
846 struct pci_dev *pdev = to_pci_dev(dev);
847
848 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
849 pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SNB &&
850 quirk_ioat_snb_local_iommu(pdev))
851 return true;
852 }
853
854 return false;
855}
856
Lu Baoludd6692f2020-07-24 09:49:21 +0800857struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800858{
859 struct dmar_drhd_unit *drhd = NULL;
Lu Baoludd6692f2020-07-24 09:49:21 +0800860 struct pci_dev *pdev = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800861 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700862 struct device *tmp;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800863 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800864 int i;
865
Lu Baolu2d33b7d2020-09-03 14:51:32 +0800866 if (!dev)
David Woodhouse4ed6a542015-05-11 14:59:20 +0100867 return NULL;
868
David Woodhouse156baca2014-03-09 14:00:57 -0700869 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700870 struct pci_dev *pf_pdev;
871
Jon Derricke3560ee2020-01-21 06:37:49 -0700872 pdev = pci_real_dma_dev(to_pci_dev(dev));
Jon Derrick5823e332017-08-30 15:05:59 -0600873
Ashok Raj1c387182016-10-21 15:32:05 -0700874 /* VFs aren't listed in scope tables; we need to look up
875 * the PF instead to find the IOMMU. */
876 pf_pdev = pci_physfn(pdev);
877 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700878 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100879 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700880 dev = &ACPI_COMPANION(dev)->dev;
881
Jiang Liu0e242612014-02-19 14:07:34 +0800882 rcu_read_lock();
Lu Baolu2d33b7d2020-09-03 14:51:32 +0800883 for_each_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700884 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100885 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800886
Jiang Liub683b232014-02-19 14:07:32 +0800887 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700888 drhd->devices_cnt, i, tmp) {
889 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700890 /* For a VF use its original BDF# not that of the PF
891 * which we used for the IOMMU lookup. Strictly speaking
892 * we could do this for all PCI devices; we only need to
893 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100894 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700895 goto got_pdev;
896
Lu Baoludd6692f2020-07-24 09:49:21 +0800897 if (bus && devfn) {
898 *bus = drhd->devices[i].bus;
899 *devfn = drhd->devices[i].devfn;
900 }
David Woodhouse156baca2014-03-09 14:00:57 -0700901 goto out;
902 }
903
Eric Augerb9a7f982019-06-03 08:53:32 +0200904 if (is_downstream_to_pci_bridge(dev, tmp))
David Woodhouse156baca2014-03-09 14:00:57 -0700905 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100906 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800907
David Woodhouse156baca2014-03-09 14:00:57 -0700908 if (pdev && drhd->include_all) {
909 got_pdev:
Lu Baoludd6692f2020-07-24 09:49:21 +0800910 if (bus && devfn) {
911 *bus = pdev->bus->number;
912 *devfn = pdev->devfn;
913 }
Jiang Liub683b232014-02-19 14:07:32 +0800914 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700915 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800916 }
Jiang Liub683b232014-02-19 14:07:32 +0800917 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700918 out:
Lu Baolu2d33b7d2020-09-03 14:51:32 +0800919 if (iommu_is_dummy(iommu, dev))
920 iommu = NULL;
921
Jiang Liu0e242612014-02-19 14:07:34 +0800922 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800923
Jiang Liub683b232014-02-19 14:07:32 +0800924 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800925}
926
Weidong Han5331fe62008-12-08 23:00:00 +0800927static void domain_flush_cache(struct dmar_domain *domain,
928 void *addr, int size)
929{
930 if (!domain->iommu_coherency)
931 clflush_cache_range(addr, size);
932}
933
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700934static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
935{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700936 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000937 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700938 unsigned long flags;
939
940 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000941 context = iommu_context_addr(iommu, bus, devfn, 0);
942 if (context)
943 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700944 spin_unlock_irqrestore(&iommu->lock, flags);
945 return ret;
946}
947
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700948static void free_context_table(struct intel_iommu *iommu)
949{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700950 int i;
951 unsigned long flags;
952 struct context_entry *context;
953
954 spin_lock_irqsave(&iommu->lock, flags);
955 if (!iommu->root_entry) {
956 goto out;
957 }
958 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000959 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700960 if (context)
961 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000962
Lu Baolu765b6a92018-12-10 09:58:55 +0800963 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000964 continue;
965
966 context = iommu_context_addr(iommu, i, 0x80, 0);
967 if (context)
968 free_pgtable_page(context);
969
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700970 }
971 free_pgtable_page(iommu->root_entry);
972 iommu->root_entry = NULL;
973out:
974 spin_unlock_irqrestore(&iommu->lock, flags);
975}
976
David Woodhouseb026fd22009-06-28 10:37:25 +0100977static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000978 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700979{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600980 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700981 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700982 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700983
984 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200985
Jiang Liu162d1b12014-07-11 14:19:35 +0800986 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200987 /* Address beyond IOMMU's addressing capabilities. */
988 return NULL;
989
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700990 parent = domain->pgd;
991
David Woodhouse5cf0a762014-03-19 16:07:49 +0000992 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700993 void *tmp_page;
994
David Woodhouseb026fd22009-06-28 10:37:25 +0100995 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700996 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000997 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100998 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000999 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001000 break;
1001
Mark McLoughlin19c239c2008-11-21 16:56:53 +00001002 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +01001003 uint64_t pteval;
1004
Suresh Siddha4c923d42009-10-02 11:01:24 -07001005 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001006
David Woodhouse206a73c2009-07-01 19:30:28 +01001007 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001008 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +01001009
David Woodhousec85994e2009-07-01 19:21:24 +01001010 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -04001011 pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
Lu Baoluddf09b62020-01-02 08:18:17 +08001012 if (domain_use_first_level(domain))
Lu Baolu16ecf102020-06-23 07:13:41 +08001013 pteval |= DMA_FL_PTE_XD | DMA_FL_PTE_US;
Yijing Wangeffad4b2014-05-26 20:13:47 +08001014 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +01001015 /* Someone else set it while we were thinking; use theirs. */
1016 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +08001017 else
David Woodhousec85994e2009-07-01 19:21:24 +01001018 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001019 }
David Woodhouse5cf0a762014-03-19 16:07:49 +00001020 if (level == 1)
1021 break;
1022
Mark McLoughlin19c239c2008-11-21 16:56:53 +00001023 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001024 level--;
1025 }
1026
David Woodhouse5cf0a762014-03-19 16:07:49 +00001027 if (!*target_level)
1028 *target_level = level;
1029
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001030 return pte;
1031}
1032
1033/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +01001034static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
1035 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001036 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001037{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001038 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001039 int total = agaw_to_level(domain->agaw);
1040 int offset;
1041
1042 parent = domain->pgd;
1043 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +01001044 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001045 pte = &parent[offset];
1046 if (level == total)
1047 return pte;
1048
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001049 if (!dma_pte_present(pte)) {
1050 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001051 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001052 }
1053
Yijing Wange16922a2014-05-20 20:37:51 +08001054 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001055 *large_page = total;
1056 return pte;
1057 }
1058
Mark McLoughlin19c239c2008-11-21 16:56:53 +00001059 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001060 total--;
1061 }
1062 return NULL;
1063}
1064
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001065/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +00001066static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +01001067 unsigned long start_pfn,
1068 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001069{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001070 unsigned int large_page;
David Woodhouse310a5ab2009-06-28 18:52:20 +01001071 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001072
Jiang Liu162d1b12014-07-11 14:19:35 +08001073 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1074 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001075 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +01001076
David Woodhouse04b18e62009-06-27 19:15:01 +01001077 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -07001078 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001079 large_page = 1;
1080 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001081 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001082 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001083 continue;
1084 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001085 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +01001086 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001087 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001088 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +01001089 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
1090
David Woodhouse310a5ab2009-06-28 18:52:20 +01001091 domain_flush_cache(domain, first_pte,
1092 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -07001093
1094 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001095}
1096
Alex Williamson3269ee02013-06-15 10:27:19 -06001097static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -07001098 int retain_level, struct dma_pte *pte,
1099 unsigned long pfn, unsigned long start_pfn,
1100 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -06001101{
1102 pfn = max(start_pfn, pfn);
1103 pte = &pte[pfn_level_offset(pfn, level)];
1104
1105 do {
1106 unsigned long level_pfn;
1107 struct dma_pte *level_pte;
1108
1109 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
1110 goto next;
1111
David Dillowf7116e12017-01-30 19:11:11 -08001112 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -06001113 level_pte = phys_to_virt(dma_pte_addr(pte));
1114
David Dillowbc24c572017-06-28 19:42:23 -07001115 if (level > 2) {
1116 dma_pte_free_level(domain, level - 1, retain_level,
1117 level_pte, level_pfn, start_pfn,
1118 last_pfn);
1119 }
Alex Williamson3269ee02013-06-15 10:27:19 -06001120
David Dillowbc24c572017-06-28 19:42:23 -07001121 /*
1122 * Free the page table if we're below the level we want to
1123 * retain and the range covers the entire table.
1124 */
1125 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001126 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001127 dma_clear_pte(pte);
1128 domain_flush_cache(domain, pte, sizeof(*pte));
1129 free_pgtable_page(level_pte);
1130 }
1131next:
1132 pfn += level_size(level);
1133 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1134}
1135
David Dillowbc24c572017-06-28 19:42:23 -07001136/*
1137 * clear last level (leaf) ptes and free page table pages below the
1138 * level we wish to keep intact.
1139 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001140static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001141 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001142 unsigned long last_pfn,
1143 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001144{
Jiang Liu162d1b12014-07-11 14:19:35 +08001145 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1146 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001147 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001148
Jiang Liud41a4ad2014-07-11 14:19:34 +08001149 dma_pte_clear_range(domain, start_pfn, last_pfn);
1150
David Woodhousef3a0a522009-06-30 03:40:07 +01001151 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001152 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001153 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001154
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001155 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001156 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001157 free_pgtable_page(domain->pgd);
1158 domain->pgd = NULL;
1159 }
1160}
1161
David Woodhouseea8ea462014-03-05 17:09:32 +00001162/* When a page at a given level is being unlinked from its parent, we don't
1163 need to *modify* it at all. All we need to do is make a list of all the
1164 pages which can be freed just as soon as we've flushed the IOTLB and we
1165 know the hardware page-walk will no longer touch them.
1166 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1167 be freed. */
1168static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1169 int level, struct dma_pte *pte,
1170 struct page *freelist)
1171{
1172 struct page *pg;
1173
1174 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1175 pg->freelist = freelist;
1176 freelist = pg;
1177
1178 if (level == 1)
1179 return freelist;
1180
Jiang Liuadeb2592014-04-09 10:20:39 +08001181 pte = page_address(pg);
1182 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001183 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1184 freelist = dma_pte_list_pagetables(domain, level - 1,
1185 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001186 pte++;
1187 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001188
1189 return freelist;
1190}
1191
1192static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1193 struct dma_pte *pte, unsigned long pfn,
1194 unsigned long start_pfn,
1195 unsigned long last_pfn,
1196 struct page *freelist)
1197{
1198 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1199
1200 pfn = max(start_pfn, pfn);
1201 pte = &pte[pfn_level_offset(pfn, level)];
1202
1203 do {
1204 unsigned long level_pfn;
1205
1206 if (!dma_pte_present(pte))
1207 goto next;
1208
1209 level_pfn = pfn & level_mask(level);
1210
1211 /* If range covers entire pagetable, free it */
1212 if (start_pfn <= level_pfn &&
1213 last_pfn >= level_pfn + level_size(level) - 1) {
1214 /* These suborbinate page tables are going away entirely. Don't
1215 bother to clear them; we're just going to *free* them. */
1216 if (level > 1 && !dma_pte_superpage(pte))
1217 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1218
1219 dma_clear_pte(pte);
1220 if (!first_pte)
1221 first_pte = pte;
1222 last_pte = pte;
1223 } else if (level > 1) {
1224 /* Recurse down into a level that isn't *entirely* obsolete */
1225 freelist = dma_pte_clear_level(domain, level - 1,
1226 phys_to_virt(dma_pte_addr(pte)),
1227 level_pfn, start_pfn, last_pfn,
1228 freelist);
1229 }
1230next:
1231 pfn += level_size(level);
1232 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1233
1234 if (first_pte)
1235 domain_flush_cache(domain, first_pte,
1236 (void *)++last_pte - (void *)first_pte);
1237
1238 return freelist;
1239}
1240
1241/* We can't just free the pages because the IOMMU may still be walking
1242 the page tables, and may have cached the intermediate levels. The
1243 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001244static struct page *domain_unmap(struct dmar_domain *domain,
1245 unsigned long start_pfn,
1246 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001247{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001248 struct page *freelist;
David Woodhouseea8ea462014-03-05 17:09:32 +00001249
Jiang Liu162d1b12014-07-11 14:19:35 +08001250 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1251 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001252 BUG_ON(start_pfn > last_pfn);
1253
1254 /* we don't need lock here; nobody else touches the iova range */
1255 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1256 domain->pgd, 0, start_pfn, last_pfn, NULL);
1257
1258 /* free pgd */
1259 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1260 struct page *pgd_page = virt_to_page(domain->pgd);
1261 pgd_page->freelist = freelist;
1262 freelist = pgd_page;
1263
1264 domain->pgd = NULL;
1265 }
1266
1267 return freelist;
1268}
1269
Joerg Roedelb6904202015-08-13 11:32:18 +02001270static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001271{
1272 struct page *pg;
1273
1274 while ((pg = freelist)) {
1275 freelist = pg->freelist;
1276 free_pgtable_page(page_address(pg));
1277 }
1278}
1279
Joerg Roedel13cf0172017-08-11 11:40:10 +02001280static void iova_entry_free(unsigned long data)
1281{
1282 struct page *freelist = (struct page *)data;
1283
1284 dma_free_pagelist(freelist);
1285}
1286
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001287/* iommu handling */
1288static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1289{
1290 struct root_entry *root;
1291 unsigned long flags;
1292
Suresh Siddha4c923d42009-10-02 11:01:24 -07001293 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001294 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001295 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001296 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001297 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001298 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001299
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001300 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001301
1302 spin_lock_irqsave(&iommu->lock, flags);
1303 iommu->root_entry = root;
1304 spin_unlock_irqrestore(&iommu->lock, flags);
1305
1306 return 0;
1307}
1308
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001309static void iommu_set_root_entry(struct intel_iommu *iommu)
1310{
David Woodhouse03ecc322015-02-13 14:35:21 +00001311 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001312 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001313 unsigned long flag;
1314
David Woodhouse03ecc322015-02-13 14:35:21 +00001315 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001316 if (sm_supported(iommu))
1317 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001318
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001319 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001320 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001321
David Woodhousec416daa2009-05-10 20:30:58 +01001322 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001323
1324 /* Make sure hardware complete it */
1325 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001326 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001327
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001328 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001329}
1330
Lu Baolu6f7db752018-12-10 09:59:00 +08001331void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001332{
1333 u32 val;
1334 unsigned long flag;
1335
David Woodhouse9af88142009-02-13 23:18:03 +00001336 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001337 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001338
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001339 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001340 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001341
1342 /* Make sure hardware complete it */
1343 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001344 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001345
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001346 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001347}
1348
1349/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001350static void __iommu_flush_context(struct intel_iommu *iommu,
1351 u16 did, u16 source_id, u8 function_mask,
1352 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001353{
1354 u64 val = 0;
1355 unsigned long flag;
1356
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001357 switch (type) {
1358 case DMA_CCMD_GLOBAL_INVL:
1359 val = DMA_CCMD_GLOBAL_INVL;
1360 break;
1361 case DMA_CCMD_DOMAIN_INVL:
1362 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1363 break;
1364 case DMA_CCMD_DEVICE_INVL:
1365 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1366 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1367 break;
1368 default:
1369 BUG();
1370 }
1371 val |= DMA_CCMD_ICC;
1372
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001373 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001374 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1375
1376 /* Make sure hardware complete it */
1377 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1378 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1379
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001380 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001381}
1382
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001383/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001384static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1385 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001386{
1387 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1388 u64 val = 0, val_iva = 0;
1389 unsigned long flag;
1390
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001391 switch (type) {
1392 case DMA_TLB_GLOBAL_FLUSH:
1393 /* global flush doesn't need set IVA_REG */
1394 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1395 break;
1396 case DMA_TLB_DSI_FLUSH:
1397 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1398 break;
1399 case DMA_TLB_PSI_FLUSH:
1400 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001401 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001402 val_iva = size_order | addr;
1403 break;
1404 default:
1405 BUG();
1406 }
1407 /* Note: set drain read/write */
1408#if 0
1409 /*
1410 * This is probably to be super secure.. Looks like we can
1411 * ignore it without any impact.
1412 */
1413 if (cap_read_drain(iommu->cap))
1414 val |= DMA_TLB_READ_DRAIN;
1415#endif
1416 if (cap_write_drain(iommu->cap))
1417 val |= DMA_TLB_WRITE_DRAIN;
1418
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001419 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001420 /* Note: Only uses first TLB reg currently */
1421 if (val_iva)
1422 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1423 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1424
1425 /* Make sure hardware complete it */
1426 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1427 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1428
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001429 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001430
1431 /* check IOTLB invalidation granularity */
1432 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001433 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001434 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001435 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001436 (unsigned long long)DMA_TLB_IIRG(type),
1437 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001438}
1439
David Woodhouse64ae8922014-03-09 12:52:30 -07001440static struct device_domain_info *
1441iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1442 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001443{
Yu Zhao93a23a72009-05-18 13:51:37 +08001444 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001445
Joerg Roedel55d94042015-07-22 16:50:40 +02001446 assert_spin_locked(&device_domain_lock);
1447
Yu Zhao93a23a72009-05-18 13:51:37 +08001448 if (!iommu->qi)
1449 return NULL;
1450
Yu Zhao93a23a72009-05-18 13:51:37 +08001451 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001452 if (info->iommu == iommu && info->bus == bus &&
1453 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001454 if (info->ats_supported && info->dev)
1455 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001456 break;
1457 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001458
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001459 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001460}
1461
Omer Peleg0824c592016-04-20 19:03:35 +03001462static void domain_update_iotlb(struct dmar_domain *domain)
1463{
1464 struct device_domain_info *info;
1465 bool has_iotlb_device = false;
1466
1467 assert_spin_locked(&device_domain_lock);
1468
1469 list_for_each_entry(info, &domain->devices, link) {
1470 struct pci_dev *pdev;
1471
1472 if (!info->dev || !dev_is_pci(info->dev))
1473 continue;
1474
1475 pdev = to_pci_dev(info->dev);
1476 if (pdev->ats_enabled) {
1477 has_iotlb_device = true;
1478 break;
1479 }
1480 }
1481
1482 domain->has_iotlb_device = has_iotlb_device;
1483}
1484
Yu Zhao93a23a72009-05-18 13:51:37 +08001485static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1486{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001487 struct pci_dev *pdev;
1488
Omer Peleg0824c592016-04-20 19:03:35 +03001489 assert_spin_locked(&device_domain_lock);
1490
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001491 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001492 return;
1493
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001494 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001495 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1496 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1497 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1498 * reserved, which should be set to 0.
1499 */
1500 if (!ecap_dit(info->iommu->ecap))
1501 info->pfsid = 0;
1502 else {
1503 struct pci_dev *pf_pdev;
1504
1505 /* pdev will be returned if device is not a vf */
1506 pf_pdev = pci_physfn(pdev);
Heiner Kallweitcc49baa2019-04-24 21:16:10 +02001507 info->pfsid = pci_dev_id(pf_pdev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001508 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001509
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001510#ifdef CONFIG_INTEL_IOMMU_SVM
1511 /* The PCIe spec, in its wisdom, declares that the behaviour of
1512 the device if you enable PASID support after ATS support is
1513 undefined. So always enable PASID support on devices which
1514 have it, even if we can't yet know if we're ever going to
1515 use it. */
1516 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1517 info->pasid_enabled = 1;
1518
Kuppuswamy Sathyanarayanan1b84778a2019-02-19 11:04:52 -08001519 if (info->pri_supported &&
1520 (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
1521 !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001522 info->pri_enabled = 1;
1523#endif
Jean-Philippe Bruckerda656a02020-05-20 17:22:03 +02001524 if (info->ats_supported && pci_ats_page_aligned(pdev) &&
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001525 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001526 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001527 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001528 info->ats_qdep = pci_ats_queue_depth(pdev);
1529 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001530}
1531
1532static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1533{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001534 struct pci_dev *pdev;
1535
Omer Peleg0824c592016-04-20 19:03:35 +03001536 assert_spin_locked(&device_domain_lock);
1537
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001538 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001539 return;
1540
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001541 pdev = to_pci_dev(info->dev);
1542
1543 if (info->ats_enabled) {
1544 pci_disable_ats(pdev);
1545 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001546 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001547 }
1548#ifdef CONFIG_INTEL_IOMMU_SVM
1549 if (info->pri_enabled) {
1550 pci_disable_pri(pdev);
1551 info->pri_enabled = 0;
1552 }
1553 if (info->pasid_enabled) {
1554 pci_disable_pasid(pdev);
1555 info->pasid_enabled = 0;
1556 }
1557#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001558}
1559
1560static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1561 u64 addr, unsigned mask)
1562{
1563 u16 sid, qdep;
1564 unsigned long flags;
1565 struct device_domain_info *info;
1566
Omer Peleg0824c592016-04-20 19:03:35 +03001567 if (!domain->has_iotlb_device)
1568 return;
1569
Yu Zhao93a23a72009-05-18 13:51:37 +08001570 spin_lock_irqsave(&device_domain_lock, flags);
1571 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001572 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001573 continue;
1574
1575 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001576 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001577 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1578 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001579 }
1580 spin_unlock_irqrestore(&device_domain_lock, flags);
1581}
1582
Lu Baolu33cd6e62020-01-02 08:18:18 +08001583static void domain_flush_piotlb(struct intel_iommu *iommu,
1584 struct dmar_domain *domain,
1585 u64 addr, unsigned long npages, bool ih)
1586{
1587 u16 did = domain->iommu_did[iommu->seq_id];
1588
1589 if (domain->default_pasid)
1590 qi_flush_piotlb(iommu, did, domain->default_pasid,
1591 addr, npages, ih);
1592
1593 if (!list_empty(&domain->devices))
1594 qi_flush_piotlb(iommu, did, PASID_RID2PASID, addr, npages, ih);
1595}
1596
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001597static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1598 struct dmar_domain *domain,
1599 unsigned long pfn, unsigned int pages,
1600 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001601{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001602 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001603 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001604 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001605
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001606 BUG_ON(pages == 0);
1607
David Woodhouseea8ea462014-03-05 17:09:32 +00001608 if (ih)
1609 ih = 1 << 6;
Lu Baolu33cd6e62020-01-02 08:18:18 +08001610
1611 if (domain_use_first_level(domain)) {
1612 domain_flush_piotlb(iommu, domain, addr, pages, ih);
1613 } else {
1614 /*
1615 * Fallback to domain selective flush if no PSI support or
1616 * the size is too big. PSI requires page size to be 2 ^ x,
1617 * and the base address is naturally aligned to the size.
1618 */
1619 if (!cap_pgsel_inv(iommu->cap) ||
1620 mask > cap_max_amask_val(iommu->cap))
1621 iommu->flush.flush_iotlb(iommu, did, 0, 0,
1622 DMA_TLB_DSI_FLUSH);
1623 else
1624 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
1625 DMA_TLB_PSI_FLUSH);
1626 }
Yu Zhaobf92df32009-06-29 11:31:45 +08001627
1628 /*
Nadav Amit82653632010-04-01 13:24:40 +03001629 * In caching mode, changes of pages from non-present to present require
1630 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001631 */
Nadav Amit82653632010-04-01 13:24:40 +03001632 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001633 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001634}
1635
Peter Xueed91a02018-05-04 10:34:52 +08001636/* Notification for newly created mappings */
1637static inline void __mapping_notify_one(struct intel_iommu *iommu,
1638 struct dmar_domain *domain,
1639 unsigned long pfn, unsigned int pages)
1640{
Lu Baolu33cd6e62020-01-02 08:18:18 +08001641 /*
1642 * It's a non-present to present mapping. Only flush if caching mode
1643 * and second level.
1644 */
1645 if (cap_caching_mode(iommu->cap) && !domain_use_first_level(domain))
Peter Xueed91a02018-05-04 10:34:52 +08001646 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1647 else
1648 iommu_flush_write_buffer(iommu);
1649}
1650
Joerg Roedel13cf0172017-08-11 11:40:10 +02001651static void iommu_flush_iova(struct iova_domain *iovad)
1652{
1653 struct dmar_domain *domain;
1654 int idx;
1655
1656 domain = container_of(iovad, struct dmar_domain, iovad);
1657
1658 for_each_domain_iommu(idx, domain) {
1659 struct intel_iommu *iommu = g_iommus[idx];
1660 u16 did = domain->iommu_did[iommu->seq_id];
1661
Lu Baolu33cd6e62020-01-02 08:18:18 +08001662 if (domain_use_first_level(domain))
1663 domain_flush_piotlb(iommu, domain, 0, -1, 0);
1664 else
1665 iommu->flush.flush_iotlb(iommu, did, 0, 0,
1666 DMA_TLB_DSI_FLUSH);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001667
1668 if (!cap_caching_mode(iommu->cap))
1669 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1670 0, MAX_AGAW_PFN_WIDTH);
1671 }
1672}
1673
mark grossf8bab732008-02-08 04:18:38 -08001674static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1675{
1676 u32 pmen;
1677 unsigned long flags;
1678
Lu Baolu5bb71fc72019-03-20 09:58:33 +08001679 if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
1680 return;
1681
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001682 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001683 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1684 pmen &= ~DMA_PMEN_EPM;
1685 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1686
1687 /* wait for the protected region status bit to clear */
1688 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1689 readl, !(pmen & DMA_PMEN_PRS), pmen);
1690
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001691 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001692}
1693
Jiang Liu2a41cce2014-07-11 14:19:33 +08001694static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001695{
1696 u32 sts;
1697 unsigned long flags;
1698
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001699 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001700 iommu->gcmd |= DMA_GCMD_TE;
1701 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001702
1703 /* Make sure hardware complete it */
1704 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001705 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001706
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001707 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001708}
1709
Jiang Liu2a41cce2014-07-11 14:19:33 +08001710static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711{
1712 u32 sts;
1713 unsigned long flag;
1714
Lu Baolub1012ca2020-07-23 09:34:37 +08001715 if (iommu_skip_te_disable && iommu->drhd->gfx_dedicated &&
1716 (cap_read_drain(iommu->cap) || cap_write_drain(iommu->cap)))
1717 return;
1718
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001719 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001720 iommu->gcmd &= ~DMA_GCMD_TE;
1721 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1722
1723 /* Make sure hardware complete it */
1724 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001725 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001726
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001727 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001728}
1729
1730static int iommu_init_domains(struct intel_iommu *iommu)
1731{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001732 u32 ndomains, nlongs;
1733 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001734
1735 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001736 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001737 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001738 nlongs = BITS_TO_LONGS(ndomains);
1739
Donald Dutile94a91b502009-08-20 16:51:34 -04001740 spin_lock_init(&iommu->lock);
1741
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001742 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1743 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001744 pr_err("%s: Allocating domain id array failed\n",
1745 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001746 return -ENOMEM;
1747 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001748
Wei Yang86f004c2016-05-21 02:41:51 +00001749 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001750 iommu->domains = kzalloc(size, GFP_KERNEL);
1751
1752 if (iommu->domains) {
1753 size = 256 * sizeof(struct dmar_domain *);
1754 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1755 }
1756
1757 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001758 pr_err("%s: Allocating domain array failed\n",
1759 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001760 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001761 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001762 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001763 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001764 return -ENOMEM;
1765 }
1766
1767 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001768 * If Caching mode is set, then invalid translations are tagged
1769 * with domain-id 0, hence we need to pre-allocate it. We also
1770 * use domain-id 0 as a marker for non-allocated domain-id, so
1771 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001772 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001773 set_bit(0, iommu->domain_ids);
1774
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001775 /*
1776 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1777 * entry for first-level or pass-through translation modes should
1778 * be programmed with a domain id different from those used for
1779 * second-level or nested translation. We reserve a domain id for
1780 * this purpose.
1781 */
1782 if (sm_supported(iommu))
1783 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1784
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001785 return 0;
1786}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001787
Jiang Liuffebeb42014-11-09 22:48:02 +08001788static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001789{
Joerg Roedel29a27712015-07-21 17:17:12 +02001790 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001791 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001792
Joerg Roedel29a27712015-07-21 17:17:12 +02001793 if (!iommu->domains || !iommu->domain_ids)
1794 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001795
Joerg Roedel55d94042015-07-22 16:50:40 +02001796 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001797 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
Joerg Roedel29a27712015-07-21 17:17:12 +02001798 if (info->iommu != iommu)
1799 continue;
1800
1801 if (!info->dev || !info->domain)
1802 continue;
1803
Joerg Roedelbea64032016-11-08 15:08:26 +01001804 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001805 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001806 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001807
1808 if (iommu->gcmd & DMA_GCMD_TE)
1809 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001810}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001811
Jiang Liuffebeb42014-11-09 22:48:02 +08001812static void free_dmar_iommu(struct intel_iommu *iommu)
1813{
1814 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001815 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001816 int i;
1817
1818 for (i = 0; i < elems; i++)
1819 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001820 kfree(iommu->domains);
1821 kfree(iommu->domain_ids);
1822 iommu->domains = NULL;
1823 iommu->domain_ids = NULL;
1824 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001825
Weidong Hand9630fe2008-12-08 11:06:32 +08001826 g_iommus[iommu->seq_id] = NULL;
1827
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001828 /* free context mapping */
1829 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001830
1831#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001832 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001833 if (ecap_prs(iommu->ecap))
1834 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001835 }
David Woodhoused76b42e2020-11-26 11:13:51 +00001836 if (vccap_pasid(iommu->vccap))
Jacob Pan33753032020-05-16 14:20:51 +08001837 ioasid_unregister_allocator(&iommu->pasid_allocator);
1838
David Woodhouse8a94ade2015-03-24 14:54:56 +00001839#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001840}
1841
Lu Baolua1948f22020-01-02 08:18:14 +08001842/*
1843 * Check and return whether first level is used by default for
Lu Baolub802d072020-01-02 08:18:21 +08001844 * DMA translation.
Lu Baolua1948f22020-01-02 08:18:14 +08001845 */
1846static bool first_level_by_default(void)
1847{
1848 struct dmar_drhd_unit *drhd;
1849 struct intel_iommu *iommu;
Lu Baolub802d072020-01-02 08:18:21 +08001850 static int first_level_support = -1;
Lu Baolua1948f22020-01-02 08:18:14 +08001851
1852 if (likely(first_level_support != -1))
1853 return first_level_support;
1854
1855 first_level_support = 1;
1856
1857 rcu_read_lock();
1858 for_each_active_iommu(iommu, drhd) {
1859 if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) {
1860 first_level_support = 0;
1861 break;
1862 }
1863 }
1864 rcu_read_unlock();
1865
1866 return first_level_support;
1867}
1868
Jiang Liuab8dfe22014-07-11 14:19:27 +08001869static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001870{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001871 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001872
1873 domain = alloc_domain_mem();
1874 if (!domain)
1875 return NULL;
1876
Jiang Liuab8dfe22014-07-11 14:19:27 +08001877 memset(domain, 0, sizeof(*domain));
Anshuman Khandual98fa15f2019-03-05 15:42:58 -08001878 domain->nid = NUMA_NO_NODE;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001879 domain->flags = flags;
Lu Baolua1948f22020-01-02 08:18:14 +08001880 if (first_level_by_default())
1881 domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL;
Omer Peleg0824c592016-04-20 19:03:35 +03001882 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001883 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001884
1885 return domain;
1886}
1887
Joerg Roedeld160aca2015-07-22 11:52:53 +02001888/* Must be called with iommu->lock */
1889static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001890 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001891{
Jiang Liu44bde612014-07-11 14:19:29 +08001892 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001893 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001894
Joerg Roedel55d94042015-07-22 16:50:40 +02001895 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001896 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001897
Joerg Roedel29a27712015-07-21 17:17:12 +02001898 domain->iommu_refcnt[iommu->seq_id] += 1;
1899 domain->iommu_count += 1;
1900 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001901 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001902 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1903
1904 if (num >= ndomains) {
1905 pr_err("%s: No free domain ids\n", iommu->name);
1906 domain->iommu_refcnt[iommu->seq_id] -= 1;
1907 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001908 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001909 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001910
Joerg Roedeld160aca2015-07-22 11:52:53 +02001911 set_bit(num, iommu->domain_ids);
1912 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001913
Joerg Roedeld160aca2015-07-22 11:52:53 +02001914 domain->iommu_did[iommu->seq_id] = num;
1915 domain->nid = iommu->node;
1916
Jiang Liufb170fb2014-07-11 14:19:28 +08001917 domain_update_iommu_cap(domain);
1918 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001919
Joerg Roedel55d94042015-07-22 16:50:40 +02001920 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001921}
1922
1923static int domain_detach_iommu(struct dmar_domain *domain,
1924 struct intel_iommu *iommu)
1925{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001926 int num, count;
Jiang Liufb170fb2014-07-11 14:19:28 +08001927
Joerg Roedel55d94042015-07-22 16:50:40 +02001928 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001929 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001930
Joerg Roedel29a27712015-07-21 17:17:12 +02001931 domain->iommu_refcnt[iommu->seq_id] -= 1;
1932 count = --domain->iommu_count;
1933 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001934 num = domain->iommu_did[iommu->seq_id];
1935 clear_bit(num, iommu->domain_ids);
1936 set_iommu_domain(iommu, num, NULL);
1937
Jiang Liufb170fb2014-07-11 14:19:28 +08001938 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001939 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001940 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001941
1942 return count;
1943}
1944
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001945static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001946static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001947
Joseph Cihula51a63e62011-03-21 11:04:24 -07001948static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001949{
1950 struct pci_dev *pdev = NULL;
1951 struct iova *iova;
1952 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001953
Zhen Leiaa3ac942017-09-21 16:52:45 +01001954 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001955
Mark Gross8a443df2008-03-04 14:59:31 -08001956 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1957 &reserved_rbtree_key);
1958
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001959 /* IOAPIC ranges shouldn't be accessed by DMA */
1960 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1961 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001962 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001963 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001964 return -ENODEV;
1965 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001966
1967 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1968 for_each_pci_dev(pdev) {
1969 struct resource *r;
1970
1971 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1972 r = &pdev->resource[i];
1973 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1974 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001975 iova = reserve_iova(&reserved_iova_list,
1976 IOVA_PFN(r->start),
1977 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001978 if (!iova) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06001979 pci_err(pdev, "Reserve iova for %pR failed\n", r);
Joseph Cihula51a63e62011-03-21 11:04:24 -07001980 return -ENODEV;
1981 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001982 }
1983 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001984 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001985}
1986
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001987static inline int guestwidth_to_adjustwidth(int gaw)
1988{
1989 int agaw;
1990 int r = (gaw - 12) % 9;
1991
1992 if (r == 0)
1993 agaw = gaw;
1994 else
1995 agaw = gaw + 9 - r;
1996 if (agaw > 64)
1997 agaw = 64;
1998 return agaw;
1999}
2000
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002001static void domain_exit(struct dmar_domain *domain)
2002{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002003
Joerg Roedeld160aca2015-07-22 11:52:53 +02002004 /* Remove associated devices and clear attached or cached domains */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002005 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08002006
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002007 /* destroy iovas */
Tom Murphye70b0812020-05-16 14:21:01 +08002008 if (domain->domain.type == IOMMU_DOMAIN_DMA)
2009 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002010
Dmitry Safonov3ee9eca2019-07-16 22:38:06 +01002011 if (domain->pgd) {
2012 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002013
Dmitry Safonov3ee9eca2019-07-16 22:38:06 +01002014 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
2015 dma_free_pagelist(freelist);
2016 }
David Woodhouseea8ea462014-03-05 17:09:32 +00002017
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002018 free_domain_mem(domain);
2019}
2020
Lu Baolu7373a8c2018-12-10 09:59:03 +08002021/*
2022 * Get the PASID directory size for scalable mode context entry.
2023 * Value of X in the PDTS field of a scalable mode context entry
2024 * indicates PASID directory with 2^(X + 7) entries.
2025 */
2026static inline unsigned long context_get_sm_pds(struct pasid_table *table)
2027{
2028 int pds, max_pde;
2029
2030 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
2031 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
2032 if (pds < 7)
2033 return 0;
2034
2035 return pds - 7;
2036}
2037
2038/*
2039 * Set the RID_PASID field of a scalable mode context entry. The
2040 * IOMMU hardware will use the PASID value set in this field for
2041 * DMA translations of DMA requests without PASID.
2042 */
2043static inline void
2044context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
2045{
2046 context->hi |= pasid & ((1 << 20) - 1);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002047}
2048
2049/*
2050 * Set the DTE(Device-TLB Enable) field of a scalable mode context
2051 * entry.
2052 */
2053static inline void context_set_sm_dte(struct context_entry *context)
2054{
2055 context->lo |= (1 << 2);
2056}
2057
2058/*
2059 * Set the PRE(Page Request Enable) field of a scalable mode context
2060 * entry.
2061 */
2062static inline void context_set_sm_pre(struct context_entry *context)
2063{
2064 context->lo |= (1 << 4);
2065}
2066
2067/* Convert value to context PASID directory size field coding. */
2068#define context_pdts(pds) (((pds) & 0x7) << 9)
2069
David Woodhouse64ae8922014-03-09 12:52:30 -07002070static int domain_context_mapping_one(struct dmar_domain *domain,
2071 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002072 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02002073 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002074{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002075 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02002076 int translation = CONTEXT_TT_MULTI_LEVEL;
2077 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002078 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002079 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08002080 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02002081
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002082 WARN_ON(did == 0);
2083
Joerg Roedel28ccce02015-07-21 14:45:31 +02002084 if (hw_pass_through && domain_type_is_si(domain))
2085 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002086
2087 pr_debug("Set context mapping for %02x:%02x.%d\n",
2088 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002089
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002090 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08002091
Joerg Roedel55d94042015-07-22 16:50:40 +02002092 spin_lock_irqsave(&device_domain_lock, flags);
2093 spin_lock(&iommu->lock);
2094
2095 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00002096 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002097 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02002098 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002099
Joerg Roedel55d94042015-07-22 16:50:40 +02002100 ret = 0;
2101 if (context_present(context))
2102 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002103
Xunlei Pangaec0e862016-12-05 20:09:07 +08002104 /*
2105 * For kdump cases, old valid entries may be cached due to the
2106 * in-flight DMA and copied pgtable, but there is no unmapping
2107 * behaviour for them, thus we need an explicit cache flush for
2108 * the newly-mapped device. For kdump, at this point, the device
2109 * is supposed to finish reset at its driver probe stage, so no
2110 * in-flight DMA will exist, and we don't need to worry anymore
2111 * hereafter.
2112 */
2113 if (context_copied(context)) {
2114 u16 did_old = context_domain_id(context);
2115
Christos Gkekasb117e032017-10-08 23:33:31 +01002116 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002117 iommu->flush.flush_context(iommu, did_old,
2118 (((u16)bus) << 8) | devfn,
2119 DMA_CCMD_MASK_NOBIT,
2120 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002121 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2122 DMA_TLB_DSI_FLUSH);
2123 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002124 }
2125
Joerg Roedelde24e552015-07-21 14:53:04 +02002126 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002127
Lu Baolu7373a8c2018-12-10 09:59:03 +08002128 if (sm_supported(iommu)) {
2129 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002130
Lu Baolu7373a8c2018-12-10 09:59:03 +08002131 WARN_ON(!table);
2132
2133 /* Setup the PASID DIR pointer: */
2134 pds = context_get_sm_pds(table);
2135 context->lo = (u64)virt_to_phys(table->table) |
2136 context_pdts(pds);
2137
2138 /* Setup the RID_PASID field: */
2139 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2140
2141 /*
2142 * Setup the Device-TLB enable bit and Page request
2143 * Enable bit:
2144 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002145 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002146 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002147 context_set_sm_dte(context);
2148 if (info && info->pri_supported)
2149 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002150 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002151 struct dma_pte *pgd = domain->pgd;
2152 int agaw;
2153
2154 context_set_domain_id(context, did);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002155
2156 if (translation != CONTEXT_TT_PASS_THROUGH) {
2157 /*
2158 * Skip top levels of page tables for iommu which has
2159 * less agaw than default. Unnecessary for PT mode.
2160 */
2161 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2162 ret = -ENOMEM;
2163 pgd = phys_to_virt(dma_pte_addr(pgd));
2164 if (!dma_pte_present(pgd))
2165 goto out_unlock;
2166 }
2167
2168 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2169 if (info && info->ats_supported)
2170 translation = CONTEXT_TT_DEV_IOTLB;
2171 else
2172 translation = CONTEXT_TT_MULTI_LEVEL;
2173
2174 context_set_address_root(context, virt_to_phys(pgd));
2175 context_set_address_width(context, agaw);
2176 } else {
2177 /*
2178 * In pass through mode, AW must be programmed to
2179 * indicate the largest AGAW value supported by
2180 * hardware. And ASR is ignored by hardware.
2181 */
2182 context_set_address_width(context, iommu->msagaw);
2183 }
Lu Baolu41b80db2019-03-01 11:23:11 +08002184
2185 context_set_translation_type(context, translation);
Yu Zhao93a23a72009-05-18 13:51:37 +08002186 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002187
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002188 context_set_fault_enable(context);
2189 context_set_present(context);
Lu Baolu04c00952020-06-23 07:13:44 +08002190 if (!ecap_coherent(iommu->ecap))
2191 clflush_cache_range(context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002192
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002193 /*
2194 * It's a non-present to present mapping. If hardware doesn't cache
2195 * non-present entry we only need to flush the write-buffer. If the
2196 * _does_ cache non-present entries, then it does so in the special
2197 * domain #0, which we have to flush:
2198 */
2199 if (cap_caching_mode(iommu->cap)) {
2200 iommu->flush.flush_context(iommu, 0,
2201 (((u16)bus) << 8) | devfn,
2202 DMA_CCMD_MASK_NOBIT,
2203 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002204 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002205 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002206 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002207 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002208 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002209
Joerg Roedel55d94042015-07-22 16:50:40 +02002210 ret = 0;
2211
2212out_unlock:
2213 spin_unlock(&iommu->lock);
2214 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002215
Wei Yang5c365d12016-07-13 13:53:21 +00002216 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002217}
2218
Lu Baolu0ce4a852019-08-26 16:50:56 +08002219struct domain_context_mapping_data {
2220 struct dmar_domain *domain;
2221 struct intel_iommu *iommu;
2222 struct pasid_table *table;
2223};
2224
2225static int domain_context_mapping_cb(struct pci_dev *pdev,
2226 u16 alias, void *opaque)
2227{
2228 struct domain_context_mapping_data *data = opaque;
2229
2230 return domain_context_mapping_one(data->domain, data->iommu,
2231 data->table, PCI_BUS_NUM(alias),
2232 alias & 0xff);
2233}
2234
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002235static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002236domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002237{
Lu Baolu0ce4a852019-08-26 16:50:56 +08002238 struct domain_context_mapping_data data;
Lu Baoluca6e3222018-12-10 09:59:02 +08002239 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002240 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002241 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002242
David Woodhousee1f167f2014-03-09 15:24:46 -07002243 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002244 if (!iommu)
2245 return -ENODEV;
2246
Lu Baoluca6e3222018-12-10 09:59:02 +08002247 table = intel_pasid_get_table(dev);
Lu Baolu0ce4a852019-08-26 16:50:56 +08002248
2249 if (!dev_is_pci(dev))
2250 return domain_context_mapping_one(domain, iommu, table,
2251 bus, devfn);
2252
2253 data.domain = domain;
2254 data.iommu = iommu;
2255 data.table = table;
2256
2257 return pci_for_each_dma_alias(to_pci_dev(dev),
2258 &domain_context_mapping_cb, &data);
Alex Williamson579305f2014-07-03 09:51:43 -06002259}
2260
2261static int domain_context_mapped_cb(struct pci_dev *pdev,
2262 u16 alias, void *opaque)
2263{
2264 struct intel_iommu *iommu = opaque;
2265
2266 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002267}
2268
David Woodhousee1f167f2014-03-09 15:24:46 -07002269static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002270{
Weidong Han5331fe62008-12-08 23:00:00 +08002271 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002272 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002273
David Woodhousee1f167f2014-03-09 15:24:46 -07002274 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002275 if (!iommu)
2276 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002277
Alex Williamson579305f2014-07-03 09:51:43 -06002278 if (!dev_is_pci(dev))
2279 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002280
Alex Williamson579305f2014-07-03 09:51:43 -06002281 return !pci_for_each_dma_alias(to_pci_dev(dev),
2282 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002283}
2284
Fenghua Yuf5329592009-08-04 15:09:37 -07002285/* Returns a number of VTD pages, but aligned to MM page size */
2286static inline unsigned long aligned_nrpages(unsigned long host_addr,
2287 size_t size)
2288{
2289 host_addr &= ~PAGE_MASK;
2290 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2291}
2292
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002293/* Return largest possible superpage level for a given mapping */
2294static inline int hardware_largepage_caps(struct dmar_domain *domain,
2295 unsigned long iov_pfn,
2296 unsigned long phy_pfn,
2297 unsigned long pages)
2298{
2299 int support, level = 1;
2300 unsigned long pfnmerge;
2301
2302 support = domain->iommu_superpage;
2303
2304 /* To use a large page, the virtual *and* physical addresses
2305 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2306 of them will mean we have to use smaller pages. So just
2307 merge them and check both at once. */
2308 pfnmerge = iov_pfn | phy_pfn;
2309
2310 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2311 pages >>= VTD_STRIDE_SHIFT;
2312 if (!pages)
2313 break;
2314 pfnmerge >>= VTD_STRIDE_SHIFT;
2315 level++;
2316 support--;
2317 }
2318 return level;
2319}
2320
David Woodhouse9051aa02009-06-29 12:30:54 +01002321static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2322 struct scatterlist *sg, unsigned long phys_pfn,
2323 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002324{
2325 struct dma_pte *first_pte = NULL, *pte = NULL;
Kees Cook3f649ab2020-06-03 13:09:38 -07002326 phys_addr_t pteval;
Jiang Liucc4f14a2014-11-26 09:42:10 +08002327 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002328 unsigned int largepage_lvl = 0;
2329 unsigned long lvl_pages = 0;
Lu Baoluddf09b62020-01-02 08:18:17 +08002330 u64 attr;
David Woodhousee1605492009-06-29 11:17:38 +01002331
Jiang Liu162d1b12014-07-11 14:19:35 +08002332 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002333
2334 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2335 return -EINVAL;
2336
Lu Baoluddf09b62020-01-02 08:18:17 +08002337 attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
2338 if (domain_use_first_level(domain))
Lu Baolu16ecf102020-06-23 07:13:41 +08002339 attr |= DMA_FL_PTE_PRESENT | DMA_FL_PTE_XD | DMA_FL_PTE_US;
David Woodhousee1605492009-06-29 11:17:38 +01002340
Jiang Liucc4f14a2014-11-26 09:42:10 +08002341 if (!sg) {
2342 sg_res = nr_pages;
Lu Baoluddf09b62020-01-02 08:18:17 +08002343 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
David Woodhouse9051aa02009-06-29 12:30:54 +01002344 }
2345
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002346 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002347 uint64_t tmp;
2348
David Woodhousee1605492009-06-29 11:17:38 +01002349 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002350 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2351
Fenghua Yuf5329592009-08-04 15:09:37 -07002352 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002353 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002354 sg->dma_length = sg->length;
Lu Baoluddf09b62020-01-02 08:18:17 +08002355 pteval = (sg_phys(sg) - pgoff) | attr;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002356 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002357 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002358
David Woodhousee1605492009-06-29 11:17:38 +01002359 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002360 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2361
David Woodhouse5cf0a762014-03-19 16:07:49 +00002362 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002363 if (!pte)
2364 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002365 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002366 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002367 unsigned long nr_superpages, end_pfn;
2368
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002369 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002370 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002371
2372 nr_superpages = sg_res / lvl_pages;
2373 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2374
Jiang Liud41a4ad2014-07-11 14:19:34 +08002375 /*
2376 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002377 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002378 * We're adding new large pages, so make sure
2379 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002380 */
David Dillowbc24c572017-06-28 19:42:23 -07002381 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2382 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002383 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002384 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002385 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002386
David Woodhousee1605492009-06-29 11:17:38 +01002387 }
2388 /* We don't need lock here, nobody else
2389 * touches the iova range
2390 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002391 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002392 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002393 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002394 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2395 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002396 if (dumps) {
2397 dumps--;
2398 debug_dma_dump_mappings(NULL);
2399 }
2400 WARN_ON(1);
2401 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002402
2403 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2404
2405 BUG_ON(nr_pages < lvl_pages);
2406 BUG_ON(sg_res < lvl_pages);
2407
2408 nr_pages -= lvl_pages;
2409 iov_pfn += lvl_pages;
2410 phys_pfn += lvl_pages;
2411 pteval += lvl_pages * VTD_PAGE_SIZE;
2412 sg_res -= lvl_pages;
2413
2414 /* If the next PTE would be the first in a new page, then we
2415 need to flush the cache on the entries we've just written.
2416 And then we'll need to recalculate 'pte', so clear it and
2417 let it get set again in the if (!pte) block above.
2418
2419 If we're done (!nr_pages) we need to flush the cache too.
2420
2421 Also if we've been setting superpages, we may need to
2422 recalculate 'pte' and switch back to smaller pages for the
2423 end of the mapping, if the trailing size is not enough to
2424 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002425 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002426 if (!nr_pages || first_pte_in_page(pte) ||
2427 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002428 domain_flush_cache(domain, first_pte,
2429 (void *)pte - (void *)first_pte);
2430 pte = NULL;
2431 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002432
2433 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002434 sg = sg_next(sg);
2435 }
2436 return 0;
2437}
2438
Peter Xu87684fd2018-05-04 10:34:53 +08002439static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
Lu Baolu095303e2019-04-29 09:16:02 +08002440 struct scatterlist *sg, unsigned long phys_pfn,
2441 unsigned long nr_pages, int prot)
Peter Xu87684fd2018-05-04 10:34:53 +08002442{
Lu Baolufa954e62019-05-25 13:41:28 +08002443 int iommu_id, ret;
Lu Baolu095303e2019-04-29 09:16:02 +08002444 struct intel_iommu *iommu;
Peter Xu87684fd2018-05-04 10:34:53 +08002445
Lu Baolu095303e2019-04-29 09:16:02 +08002446 /* Do the real mapping first */
2447 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2448 if (ret)
2449 return ret;
Peter Xu87684fd2018-05-04 10:34:53 +08002450
Lu Baolufa954e62019-05-25 13:41:28 +08002451 for_each_domain_iommu(iommu_id, domain) {
2452 iommu = g_iommus[iommu_id];
Lu Baolu095303e2019-04-29 09:16:02 +08002453 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2454 }
2455
2456 return 0;
Peter Xu87684fd2018-05-04 10:34:53 +08002457}
2458
David Woodhouse9051aa02009-06-29 12:30:54 +01002459static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2460 struct scatterlist *sg, unsigned long nr_pages,
2461 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002462{
Peter Xu87684fd2018-05-04 10:34:53 +08002463 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002464}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002465
David Woodhouse9051aa02009-06-29 12:30:54 +01002466static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2467 unsigned long phys_pfn, unsigned long nr_pages,
2468 int prot)
2469{
Peter Xu87684fd2018-05-04 10:34:53 +08002470 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002471}
2472
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002473static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002474{
Filippo Sironi50822192017-08-31 10:58:11 +02002475 unsigned long flags;
2476 struct context_entry *context;
2477 u16 did_old;
2478
Weidong Hanc7151a82008-12-08 22:51:37 +08002479 if (!iommu)
2480 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002481
Filippo Sironi50822192017-08-31 10:58:11 +02002482 spin_lock_irqsave(&iommu->lock, flags);
2483 context = iommu_context_addr(iommu, bus, devfn, 0);
2484 if (!context) {
2485 spin_unlock_irqrestore(&iommu->lock, flags);
2486 return;
2487 }
2488 did_old = context_domain_id(context);
2489 context_clear_entry(context);
2490 __iommu_flush_cache(iommu, context, sizeof(*context));
2491 spin_unlock_irqrestore(&iommu->lock, flags);
2492 iommu->flush.flush_context(iommu,
2493 did_old,
2494 (((u16)bus) << 8) | devfn,
2495 DMA_CCMD_MASK_NOBIT,
2496 DMA_CCMD_DEVICE_INVL);
2497 iommu->flush.flush_iotlb(iommu,
2498 did_old,
2499 0,
2500 0,
2501 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002502}
2503
David Woodhouse109b9b02012-05-25 17:43:02 +01002504static inline void unlink_domain_info(struct device_domain_info *info)
2505{
2506 assert_spin_locked(&device_domain_lock);
2507 list_del(&info->link);
2508 list_del(&info->global);
2509 if (info->dev)
Joerg Roedel01b9d4e2020-06-25 15:08:25 +02002510 dev_iommu_priv_set(info->dev, NULL);
David Woodhouse109b9b02012-05-25 17:43:02 +01002511}
2512
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002513static void domain_remove_dev_info(struct dmar_domain *domain)
2514{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002515 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002516 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002517
2518 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002519 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002520 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002521 spin_unlock_irqrestore(&device_domain_lock, flags);
2522}
2523
Lu Baolue2726da2020-01-02 08:18:22 +08002524struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002525{
2526 struct device_domain_info *info;
2527
Lu Baolu6097df42020-10-28 15:07:25 +08002528 if (unlikely(!dev || !dev->iommu))
2529 return NULL;
2530
Lu Baolu2d33b7d2020-09-03 14:51:32 +08002531 if (unlikely(attach_deferred(dev)))
Lu Baolu1ee0186b2019-09-21 15:06:44 +08002532 return NULL;
2533
2534 /* No lock here, assumes no domain exit in normal case */
Lu Baolue85bb992020-05-16 14:20:52 +08002535 info = get_domain_info(dev);
Lu Baolu1ee0186b2019-09-21 15:06:44 +08002536 if (likely(info))
2537 return info->domain;
2538
2539 return NULL;
2540}
2541
Joerg Roedel034d98c2020-02-17 17:16:19 +01002542static void do_deferred_attach(struct device *dev)
2543{
2544 struct iommu_domain *domain;
2545
Joerg Roedel01b9d4e2020-06-25 15:08:25 +02002546 dev_iommu_priv_set(dev, NULL);
Joerg Roedel034d98c2020-02-17 17:16:19 +01002547 domain = iommu_get_domain_for_dev(dev);
2548 if (domain)
2549 intel_iommu_attach_device(domain, dev);
2550}
2551
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002552static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002553dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2554{
2555 struct device_domain_info *info;
2556
2557 list_for_each_entry(info, &device_domain_list, global)
Jon Derrick4fda2302020-05-27 10:56:16 -06002558 if (info->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002559 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002560 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002561
2562 return NULL;
2563}
2564
Lu Baoluddf09b62020-01-02 08:18:17 +08002565static int domain_setup_first_level(struct intel_iommu *iommu,
2566 struct dmar_domain *domain,
2567 struct device *dev,
Fenghua Yuc7b6bac2020-09-15 09:30:05 -07002568 u32 pasid)
Lu Baoluddf09b62020-01-02 08:18:17 +08002569{
2570 int flags = PASID_FLAG_SUPERVISOR_MODE;
2571 struct dma_pte *pgd = domain->pgd;
2572 int agaw, level;
2573
2574 /*
2575 * Skip top levels of page tables for iommu which has
2576 * less agaw than default. Unnecessary for PT mode.
2577 */
2578 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2579 pgd = phys_to_virt(dma_pte_addr(pgd));
2580 if (!dma_pte_present(pgd))
2581 return -ENOMEM;
2582 }
2583
2584 level = agaw_to_level(agaw);
2585 if (level != 4 && level != 5)
2586 return -EINVAL;
2587
2588 flags |= (level == 5) ? PASID_FLAG_FL5LP : 0;
2589
2590 return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid,
2591 domain->iommu_did[iommu->seq_id],
2592 flags);
2593}
2594
Jon Derrick8038bdb2020-05-27 10:56:15 -06002595static bool dev_is_real_dma_subdevice(struct device *dev)
2596{
2597 return dev && dev_is_pci(dev) &&
2598 pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
2599}
2600
Joerg Roedel5db31562015-07-22 12:40:43 +02002601static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2602 int bus, int devfn,
2603 struct device *dev,
2604 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002605{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002606 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002607 struct device_domain_info *info;
2608 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002609 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002610
2611 info = alloc_devinfo_mem();
2612 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002613 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002614
Jon Derrick4fda2302020-05-27 10:56:16 -06002615 if (!dev_is_real_dma_subdevice(dev)) {
2616 info->bus = bus;
2617 info->devfn = devfn;
2618 info->segment = iommu->segment;
2619 } else {
2620 struct pci_dev *pdev = to_pci_dev(dev);
2621
2622 info->bus = pdev->bus->number;
2623 info->devfn = pdev->devfn;
2624 info->segment = pci_domain_nr(pdev->bus);
2625 }
2626
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002627 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2628 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2629 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002630 info->dev = dev;
2631 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002632 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002633 info->pasid_table = NULL;
Lu Baolu95587a72019-03-25 09:30:30 +08002634 info->auxd_enabled = 0;
Lu Baolu67b8e022019-03-25 09:30:32 +08002635 INIT_LIST_HEAD(&info->auxiliary_domains);
Jiang Liu745f2582014-02-19 14:07:26 +08002636
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002637 if (dev && dev_is_pci(dev)) {
2638 struct pci_dev *pdev = to_pci_dev(info->dev);
2639
Jean-Philippe Bruckerda656a02020-05-20 17:22:03 +02002640 if (ecap_dev_iotlb_support(iommu->ecap) &&
2641 pci_ats_supported(pdev) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002642 dmar_find_matched_atsr_unit(pdev))
2643 info->ats_supported = 1;
2644
Lu Baolu765b6a92018-12-10 09:58:55 +08002645 if (sm_supported(iommu)) {
2646 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002647 int features = pci_pasid_features(pdev);
2648 if (features >= 0)
2649 info->pasid_supported = features | 1;
2650 }
2651
2652 if (info->ats_supported && ecap_prs(iommu->ecap) &&
Ashok Raj3f9a7a12020-07-23 15:37:29 -07002653 pci_pri_supported(pdev))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002654 info->pri_supported = 1;
2655 }
2656 }
2657
Jiang Liu745f2582014-02-19 14:07:26 +08002658 spin_lock_irqsave(&device_domain_lock, flags);
2659 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002660 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002661
2662 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002663 struct device_domain_info *info2;
Jon Derrick4fda2302020-05-27 10:56:16 -06002664 info2 = dmar_search_domain_by_dev_info(info->segment, info->bus,
2665 info->devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002666 if (info2) {
2667 found = info2->domain;
2668 info2->dev = dev;
2669 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002670 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002671
Jiang Liu745f2582014-02-19 14:07:26 +08002672 if (found) {
2673 spin_unlock_irqrestore(&device_domain_lock, flags);
2674 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002675 /* Caller must free the original domain */
2676 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002677 }
2678
Joerg Roedeld160aca2015-07-22 11:52:53 +02002679 spin_lock(&iommu->lock);
2680 ret = domain_attach_iommu(domain, iommu);
2681 spin_unlock(&iommu->lock);
2682
2683 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002684 spin_unlock_irqrestore(&device_domain_lock, flags);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302685 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002686 return NULL;
2687 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002688
David Woodhouseb718cd32014-03-09 13:11:33 -07002689 list_add(&info->link, &domain->devices);
2690 list_add(&info->global, &device_domain_list);
2691 if (dev)
Joerg Roedel01b9d4e2020-06-25 15:08:25 +02002692 dev_iommu_priv_set(dev, info);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002693 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002694
Lu Baolu0bbeb012018-12-10 09:58:56 +08002695 /* PASID table is mandatory for a PCI device in scalable mode. */
2696 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002697 ret = intel_pasid_alloc_table(dev);
2698 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002699 dev_err(dev, "PASID table allocation failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002700 dmar_remove_one_dev_info(dev);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002701 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002702 }
Lu Baoluef848b72018-12-10 09:59:01 +08002703
2704 /* Setup the PASID entry for requests without PASID: */
Lu Baolu1a3f2fd2020-09-27 14:24:28 +08002705 spin_lock_irqsave(&iommu->lock, flags);
Lu Baoluef848b72018-12-10 09:59:01 +08002706 if (hw_pass_through && domain_type_is_si(domain))
2707 ret = intel_pasid_setup_pass_through(iommu, domain,
2708 dev, PASID_RID2PASID);
Lu Baoluddf09b62020-01-02 08:18:17 +08002709 else if (domain_use_first_level(domain))
2710 ret = domain_setup_first_level(iommu, domain, dev,
2711 PASID_RID2PASID);
Lu Baoluef848b72018-12-10 09:59:01 +08002712 else
2713 ret = intel_pasid_setup_second_level(iommu, domain,
2714 dev, PASID_RID2PASID);
Lu Baolu1a3f2fd2020-09-27 14:24:28 +08002715 spin_unlock_irqrestore(&iommu->lock, flags);
Lu Baoluef848b72018-12-10 09:59:01 +08002716 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002717 dev_err(dev, "Setup RID2PASID failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002718 dmar_remove_one_dev_info(dev);
Lu Baoluef848b72018-12-10 09:59:01 +08002719 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002720 }
2721 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002722
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002723 if (dev && domain_context_mapping(domain, dev)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002724 dev_err(dev, "Domain context map failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002725 dmar_remove_one_dev_info(dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002726 return NULL;
2727 }
2728
David Woodhouseb718cd32014-03-09 13:11:33 -07002729 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002730}
2731
David Woodhouseb2132032009-06-26 18:50:28 +01002732static int iommu_domain_identity_map(struct dmar_domain *domain,
Tom Murphye70b0812020-05-16 14:21:01 +08002733 unsigned long first_vpfn,
2734 unsigned long last_vpfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002735{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002736 /*
2737 * RMRR range might have overlap with physical memory range,
2738 * clear it first
2739 */
David Woodhousec5395d52009-06-28 16:35:56 +01002740 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002741
Peter Xu87684fd2018-05-04 10:34:53 +08002742 return __domain_mapping(domain, first_vpfn, NULL,
2743 first_vpfn, last_vpfn - first_vpfn + 1,
2744 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002745}
2746
Joerg Roedel301e7ee2019-07-22 16:21:05 +02002747static int md_domain_init(struct dmar_domain *domain, int guest_width);
2748
Matt Kraai071e1372009-08-23 22:30:22 -07002749static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002750{
Lu Baolu4de354e2019-05-25 13:41:27 +08002751 struct dmar_rmrr_unit *rmrr;
2752 struct device *dev;
2753 int i, nid, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002754
Jiang Liuab8dfe22014-07-11 14:19:27 +08002755 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002756 if (!si_domain)
2757 return -EFAULT;
2758
Joerg Roedel301e7ee2019-07-22 16:21:05 +02002759 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002760 domain_exit(si_domain);
2761 return -EFAULT;
2762 }
2763
David Woodhouse19943b02009-08-04 16:19:20 +01002764 if (hw)
2765 return 0;
2766
David Woodhousec7ab48d2009-06-26 19:10:36 +01002767 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002768 unsigned long start_pfn, end_pfn;
2769 int i;
2770
2771 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2772 ret = iommu_domain_identity_map(si_domain,
Tom Murphye70b0812020-05-16 14:21:01 +08002773 mm_to_dma_pfn(start_pfn),
2774 mm_to_dma_pfn(end_pfn));
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002775 if (ret)
2776 return ret;
2777 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002778 }
2779
Lu Baolu4de354e2019-05-25 13:41:27 +08002780 /*
Lu Baolu9235cb132020-01-15 11:03:58 +08002781 * Identity map the RMRRs so that devices with RMRRs could also use
2782 * the si_domain.
Lu Baolu4de354e2019-05-25 13:41:27 +08002783 */
2784 for_each_rmrr_units(rmrr) {
2785 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
2786 i, dev) {
2787 unsigned long long start = rmrr->base_address;
2788 unsigned long long end = rmrr->end_address;
2789
Lu Baolu4de354e2019-05-25 13:41:27 +08002790 if (WARN_ON(end < start ||
2791 end >> agaw_to_width(si_domain->agaw)))
2792 continue;
2793
Lu Baolu48f0bcf2020-06-23 07:13:45 +08002794 ret = iommu_domain_identity_map(si_domain,
2795 mm_to_dma_pfn(start >> PAGE_SHIFT),
2796 mm_to_dma_pfn(end >> PAGE_SHIFT));
Lu Baolu4de354e2019-05-25 13:41:27 +08002797 if (ret)
2798 return ret;
2799 }
2800 }
2801
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002802 return 0;
2803}
2804
Joerg Roedel28ccce02015-07-21 14:45:31 +02002805static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002806{
David Woodhouse0ac72662014-03-09 13:19:22 -07002807 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002808 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002809 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002810
David Woodhouse5913c9b2014-03-09 16:27:31 -07002811 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002812 if (!iommu)
2813 return -ENODEV;
2814
Joerg Roedel5db31562015-07-22 12:40:43 +02002815 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002816 if (ndomain != domain)
2817 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002818
2819 return 0;
2820}
2821
David Woodhouse0b9d9752014-03-09 15:48:15 -07002822static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002823{
2824 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002825 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002826 int i;
2827
Jiang Liu0e242612014-02-19 14:07:34 +08002828 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002829 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002830 /*
2831 * Return TRUE if this RMRR contains the device that
2832 * is passed in.
2833 */
2834 for_each_active_dev_scope(rmrr->devices,
2835 rmrr->devices_cnt, i, tmp)
Eric Augere143fd42019-06-03 08:53:33 +02002836 if (tmp == dev ||
2837 is_downstream_to_pci_bridge(dev, tmp)) {
Jiang Liu0e242612014-02-19 14:07:34 +08002838 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002839 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002840 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002841 }
Jiang Liu0e242612014-02-19 14:07:34 +08002842 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002843 return false;
2844}
2845
Eric Auger1c5c59f2019-06-03 08:53:36 +02002846/**
2847 * device_rmrr_is_relaxable - Test whether the RMRR of this device
2848 * is relaxable (ie. is allowed to be not enforced under some conditions)
2849 * @dev: device handle
2850 *
2851 * We assume that PCI USB devices with RMRRs have them largely
2852 * for historical reasons and that the RMRR space is not actively used post
2853 * boot. This exclusion may change if vendors begin to abuse it.
2854 *
2855 * The same exception is made for graphics devices, with the requirement that
2856 * any use of the RMRR regions will be torn down before assigning the device
2857 * to a guest.
2858 *
2859 * Return: true if the RMRR is relaxable, false otherwise
2860 */
2861static bool device_rmrr_is_relaxable(struct device *dev)
2862{
2863 struct pci_dev *pdev;
2864
2865 if (!dev_is_pci(dev))
2866 return false;
2867
2868 pdev = to_pci_dev(dev);
2869 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
2870 return true;
2871 else
2872 return false;
2873}
2874
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002875/*
2876 * There are a couple cases where we need to restrict the functionality of
2877 * devices associated with RMRRs. The first is when evaluating a device for
2878 * identity mapping because problems exist when devices are moved in and out
2879 * of domains and their respective RMRR information is lost. This means that
2880 * a device with associated RMRRs will never be in a "passthrough" domain.
2881 * The second is use of the device through the IOMMU API. This interface
2882 * expects to have full control of the IOVA space for the device. We cannot
2883 * satisfy both the requirement that RMRR access is maintained and have an
2884 * unencumbered IOVA space. We also have no ability to quiesce the device's
2885 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2886 * We therefore prevent devices associated with an RMRR from participating in
2887 * the IOMMU API, which eliminates them from device assignment.
2888 *
Eric Auger1c5c59f2019-06-03 08:53:36 +02002889 * In both cases, devices which have relaxable RMRRs are not concerned by this
2890 * restriction. See device_rmrr_is_relaxable comment.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002891 */
2892static bool device_is_rmrr_locked(struct device *dev)
2893{
2894 if (!device_has_rmrr(dev))
2895 return false;
2896
Eric Auger1c5c59f2019-06-03 08:53:36 +02002897 if (device_rmrr_is_relaxable(dev))
2898 return false;
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002899
2900 return true;
2901}
2902
Lu Baoluf273a452019-05-25 13:41:26 +08002903/*
2904 * Return the required default domain type for a specific device.
2905 *
2906 * @dev: the device in query
2907 * @startup: true if this is during early boot
2908 *
2909 * Returns:
2910 * - IOMMU_DOMAIN_DMA: device requires a dynamic mapping domain
2911 * - IOMMU_DOMAIN_IDENTITY: device requires an identical mapping domain
2912 * - 0: both identity and dynamic domains work for this device
2913 */
Lu Baolu0e31a722019-05-25 13:41:34 +08002914static int device_def_domain_type(struct device *dev)
David Woodhouse6941af22009-07-04 18:24:27 +01002915{
David Woodhouse3bdb2592014-03-09 16:03:08 -07002916 if (dev_is_pci(dev)) {
2917 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002918
Lu Baolu89a60792018-10-23 15:45:01 +08002919 /*
2920 * Prevent any device marked as untrusted from getting
2921 * placed into the statically identity mapping domain.
2922 */
2923 if (pdev->untrusted)
Lu Baoluf273a452019-05-25 13:41:26 +08002924 return IOMMU_DOMAIN_DMA;
Lu Baolu89a60792018-10-23 15:45:01 +08002925
David Woodhouse3bdb2592014-03-09 16:03:08 -07002926 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08002927 return IOMMU_DOMAIN_IDENTITY;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002928
David Woodhouse3bdb2592014-03-09 16:03:08 -07002929 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08002930 return IOMMU_DOMAIN_IDENTITY;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002931 }
David Woodhouse6941af22009-07-04 18:24:27 +01002932
Lu Baolub89b6602020-01-15 11:03:59 +08002933 return 0;
Lu Baoluf273a452019-05-25 13:41:26 +08002934}
2935
Jiang Liuffebeb42014-11-09 22:48:02 +08002936static void intel_iommu_init_qi(struct intel_iommu *iommu)
2937{
2938 /*
2939 * Start from the sane iommu hardware state.
2940 * If the queued invalidation is already initialized by us
2941 * (for example, while enabling interrupt-remapping) then
2942 * we got the things already rolling from a sane state.
2943 */
2944 if (!iommu->qi) {
2945 /*
2946 * Clear any previous faults.
2947 */
2948 dmar_fault(-1, iommu);
2949 /*
2950 * Disable queued invalidation if supported and already enabled
2951 * before OS handover.
2952 */
2953 dmar_disable_qi(iommu);
2954 }
2955
2956 if (dmar_enable_qi(iommu)) {
2957 /*
2958 * Queued Invalidate not enabled, use Register Based Invalidate
2959 */
2960 iommu->flush.flush_context = __iommu_flush_context;
2961 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002962 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08002963 iommu->name);
2964 } else {
2965 iommu->flush.flush_context = qi_flush_context;
2966 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002967 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08002968 }
2969}
2970
Joerg Roedel091d42e2015-06-12 11:56:10 +02002971static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04002972 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02002973 struct context_entry **tbl,
2974 int bus, bool ext)
2975{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02002976 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002977 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04002978 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002979 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02002980 phys_addr_t old_ce_phys;
2981
2982 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04002983 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02002984
2985 for (devfn = 0; devfn < 256; devfn++) {
2986 /* First calculate the correct index */
2987 idx = (ext ? devfn * 2 : devfn) % 256;
2988
2989 if (idx == 0) {
2990 /* First save what we may have and clean up */
2991 if (new_ce) {
2992 tbl[tbl_idx] = new_ce;
2993 __iommu_flush_cache(iommu, new_ce,
2994 VTD_PAGE_SIZE);
2995 pos = 1;
2996 }
2997
2998 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08002999 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003000
3001 ret = 0;
3002 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003003 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003004 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003005 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003006
3007 if (!old_ce_phys) {
3008 if (ext && devfn == 0) {
3009 /* No LCTP, try UCTP */
3010 devfn = 0x7f;
3011 continue;
3012 } else {
3013 goto out;
3014 }
3015 }
3016
3017 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003018 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3019 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003020 if (!old_ce)
3021 goto out;
3022
3023 new_ce = alloc_pgtable_page(iommu->node);
3024 if (!new_ce)
3025 goto out_unmap;
3026
3027 ret = 0;
3028 }
3029
3030 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003031 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003032
Joerg Roedelcf484d02015-06-12 12:21:46 +02003033 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003034 continue;
3035
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003036 did = context_domain_id(&ce);
3037 if (did >= 0 && did < cap_ndoms(iommu->cap))
3038 set_bit(did, iommu->domain_ids);
3039
Joerg Roedelcf484d02015-06-12 12:21:46 +02003040 /*
3041 * We need a marker for copied context entries. This
3042 * marker needs to work for the old format as well as
3043 * for extended context entries.
3044 *
3045 * Bit 67 of the context entry is used. In the old
3046 * format this bit is available to software, in the
3047 * extended format it is the PGE bit, but PGE is ignored
3048 * by HW if PASIDs are disabled (and thus still
3049 * available).
3050 *
3051 * So disable PASIDs first and then mark the entry
3052 * copied. This means that we don't copy PASID
3053 * translations from the old kernel, but this is fine as
3054 * faults there are not fatal.
3055 */
3056 context_clear_pasid_enable(&ce);
3057 context_set_copied(&ce);
3058
Joerg Roedel091d42e2015-06-12 11:56:10 +02003059 new_ce[idx] = ce;
3060 }
3061
3062 tbl[tbl_idx + pos] = new_ce;
3063
3064 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3065
3066out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003067 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003068
3069out:
3070 return ret;
3071}
3072
3073static int copy_translation_tables(struct intel_iommu *iommu)
3074{
3075 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003076 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003077 phys_addr_t old_rt_phys;
3078 int ctxt_table_entries;
3079 unsigned long flags;
3080 u64 rtaddr_reg;
3081 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003082 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003083
3084 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3085 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003086 new_ext = !!ecap_ecs(iommu->ecap);
3087
3088 /*
3089 * The RTT bit can only be changed when translation is disabled,
3090 * but disabling translation means to open a window for data
3091 * corruption. So bail out and don't copy anything if we would
3092 * have to change the bit.
3093 */
3094 if (new_ext != ext)
3095 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003096
3097 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3098 if (!old_rt_phys)
3099 return -EINVAL;
3100
Dan Williamsdfddb962015-10-09 18:16:46 -04003101 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003102 if (!old_rt)
3103 return -ENOMEM;
3104
3105 /* This is too big for the stack - allocate it from slab */
3106 ctxt_table_entries = ext ? 512 : 256;
3107 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003108 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003109 if (!ctxt_tbls)
3110 goto out_unmap;
3111
3112 for (bus = 0; bus < 256; bus++) {
3113 ret = copy_context_table(iommu, &old_rt[bus],
3114 ctxt_tbls, bus, ext);
3115 if (ret) {
3116 pr_err("%s: Failed to copy context table for bus %d\n",
3117 iommu->name, bus);
3118 continue;
3119 }
3120 }
3121
3122 spin_lock_irqsave(&iommu->lock, flags);
3123
3124 /* Context tables are copied, now write them to the root_entry table */
3125 for (bus = 0; bus < 256; bus++) {
3126 int idx = ext ? bus * 2 : bus;
3127 u64 val;
3128
3129 if (ctxt_tbls[idx]) {
3130 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3131 iommu->root_entry[bus].lo = val;
3132 }
3133
3134 if (!ext || !ctxt_tbls[idx + 1])
3135 continue;
3136
3137 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3138 iommu->root_entry[bus].hi = val;
3139 }
3140
3141 spin_unlock_irqrestore(&iommu->lock, flags);
3142
3143 kfree(ctxt_tbls);
3144
3145 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3146
3147 ret = 0;
3148
3149out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003150 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003151
3152 return ret;
3153}
3154
Jacob Pan33753032020-05-16 14:20:51 +08003155#ifdef CONFIG_INTEL_IOMMU_SVM
3156static ioasid_t intel_vcmd_ioasid_alloc(ioasid_t min, ioasid_t max, void *data)
3157{
3158 struct intel_iommu *iommu = data;
3159 ioasid_t ioasid;
3160
3161 if (!iommu)
3162 return INVALID_IOASID;
3163 /*
3164 * VT-d virtual command interface always uses the full 20 bit
3165 * PASID range. Host can partition guest PASID range based on
3166 * policies but it is out of guest's control.
3167 */
3168 if (min < PASID_MIN || max > intel_pasid_max_id)
3169 return INVALID_IOASID;
3170
3171 if (vcmd_alloc_pasid(iommu, &ioasid))
3172 return INVALID_IOASID;
3173
3174 return ioasid;
3175}
3176
3177static void intel_vcmd_ioasid_free(ioasid_t ioasid, void *data)
3178{
3179 struct intel_iommu *iommu = data;
3180
3181 if (!iommu)
3182 return;
3183 /*
3184 * Sanity check the ioasid owner is done at upper layer, e.g. VFIO
3185 * We can only free the PASID when all the devices are unbound.
3186 */
3187 if (ioasid_find(NULL, ioasid, NULL)) {
3188 pr_alert("Cannot free active IOASID %d\n", ioasid);
3189 return;
3190 }
3191 vcmd_free_pasid(iommu, ioasid);
3192}
3193
3194static void register_pasid_allocator(struct intel_iommu *iommu)
3195{
3196 /*
3197 * If we are running in the host, no need for custom allocator
3198 * in that PASIDs are allocated from the host system-wide.
3199 */
3200 if (!cap_caching_mode(iommu->cap))
3201 return;
3202
3203 if (!sm_supported(iommu)) {
3204 pr_warn("VT-d Scalable Mode not enabled, no PASID allocation\n");
3205 return;
3206 }
3207
3208 /*
3209 * Register a custom PASID allocator if we are running in a guest,
3210 * guest PASID must be obtained via virtual command interface.
3211 * There can be multiple vIOMMUs in each guest but only one allocator
3212 * is active. All vIOMMU allocators will eventually be calling the same
3213 * host allocator.
3214 */
David Woodhoused76b42e2020-11-26 11:13:51 +00003215 if (!vccap_pasid(iommu->vccap))
Jacob Pan33753032020-05-16 14:20:51 +08003216 return;
3217
3218 pr_info("Register custom PASID allocator\n");
3219 iommu->pasid_allocator.alloc = intel_vcmd_ioasid_alloc;
3220 iommu->pasid_allocator.free = intel_vcmd_ioasid_free;
3221 iommu->pasid_allocator.pdata = (void *)iommu;
3222 if (ioasid_register_allocator(&iommu->pasid_allocator)) {
3223 pr_warn("Custom PASID allocator failed, scalable mode disabled\n");
3224 /*
3225 * Disable scalable mode on this IOMMU if there
3226 * is no custom allocator. Mixing SM capable vIOMMU
3227 * and non-SM vIOMMU are not supported.
3228 */
3229 intel_iommu_sm = 0;
3230 }
3231}
3232#endif
3233
Joseph Cihulab7792602011-05-03 00:08:37 -07003234static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003235{
3236 struct dmar_drhd_unit *drhd;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003237 struct intel_iommu *iommu;
Lu Baoludf4f3c62019-05-25 13:41:36 +08003238 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003239
3240 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003241 * for each drhd
3242 * allocate root
3243 * initialize and program root entry to not present
3244 * endfor
3245 */
3246 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003247 /*
3248 * lock not needed as this is only incremented in the single
3249 * threaded kernel __init code path all other access are read
3250 * only
3251 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003252 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003253 g_num_of_iommus++;
3254 continue;
3255 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003256 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003257 }
3258
Jiang Liuffebeb42014-11-09 22:48:02 +08003259 /* Preallocate enough resources for IOMMU hot-addition */
3260 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3261 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3262
Weidong Hand9630fe2008-12-08 11:06:32 +08003263 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3264 GFP_KERNEL);
3265 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003266 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003267 ret = -ENOMEM;
3268 goto error;
3269 }
3270
Lu Baolu6a8c6742019-06-12 08:28:47 +08003271 for_each_iommu(iommu, drhd) {
3272 if (drhd->ignored) {
3273 iommu_disable_translation(iommu);
3274 continue;
3275 }
3276
Lu Baolu56283172018-07-14 15:46:54 +08003277 /*
3278 * Find the max pasid size of all IOMMU's in the system.
3279 * We need to ensure the system pasid table is no bigger
3280 * than the smallest supported.
3281 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003282 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003283 u32 temp = 2 << ecap_pss(iommu->ecap);
3284
3285 intel_pasid_max_id = min_t(u32, temp,
3286 intel_pasid_max_id);
3287 }
3288
Weidong Hand9630fe2008-12-08 11:06:32 +08003289 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003290
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003291 intel_iommu_init_qi(iommu);
3292
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003293 ret = iommu_init_domains(iommu);
3294 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003295 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003296
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003297 init_translation_status(iommu);
3298
Joerg Roedel091d42e2015-06-12 11:56:10 +02003299 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3300 iommu_disable_translation(iommu);
3301 clear_translation_pre_enabled(iommu);
3302 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3303 iommu->name);
3304 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003305
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003306 /*
3307 * TBD:
3308 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003309 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003310 */
3311 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003312 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003313 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003314
Joerg Roedel091d42e2015-06-12 11:56:10 +02003315 if (translation_pre_enabled(iommu)) {
3316 pr_info("Translation already enabled - trying to copy translation structures\n");
3317
3318 ret = copy_translation_tables(iommu);
3319 if (ret) {
3320 /*
3321 * We found the IOMMU with translation
3322 * enabled - but failed to copy over the
3323 * old root-entry table. Try to proceed
3324 * by disabling translation now and
3325 * allocating a clean root-entry table.
3326 * This might cause DMAR faults, but
3327 * probably the dump will still succeed.
3328 */
3329 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3330 iommu->name);
3331 iommu_disable_translation(iommu);
3332 clear_translation_pre_enabled(iommu);
3333 } else {
3334 pr_info("Copied translation tables from previous kernel for %s\n",
3335 iommu->name);
3336 }
3337 }
3338
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003339 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003340 hw_pass_through = 0;
Jacob Panff3dc652020-01-02 08:18:03 +08003341 intel_svm_check(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003342 }
3343
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003344 /*
3345 * Now that qi is enabled on all iommus, set the root entry and flush
3346 * caches. This is required on some Intel X58 chipsets, otherwise the
3347 * flush_context function will loop forever and the boot hangs.
3348 */
3349 for_each_active_iommu(iommu, drhd) {
3350 iommu_flush_write_buffer(iommu);
Jacob Pan33753032020-05-16 14:20:51 +08003351#ifdef CONFIG_INTEL_IOMMU_SVM
3352 register_pasid_allocator(iommu);
3353#endif
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003354 iommu_set_root_entry(iommu);
3355 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3356 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3357 }
3358
Suresh Siddhad3f13812011-08-23 17:05:25 -07003359#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
Lu Baolu5daab582019-05-02 09:34:26 +08003360 dmar_map_gfx = 0;
David Woodhouse19943b02009-08-04 16:19:20 +01003361#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003362
Lu Baolu5daab582019-05-02 09:34:26 +08003363 if (!dmar_map_gfx)
3364 iommu_identity_mapping |= IDENTMAP_GFX;
3365
Ashok Raj21e722c2017-01-30 09:39:53 -08003366 check_tylersburg_isoch();
3367
Lu Baolu4de354e2019-05-25 13:41:27 +08003368 ret = si_domain_init(hw_pass_through);
3369 if (ret)
3370 goto free_iommu;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003371
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003372 /*
3373 * for each drhd
3374 * enable fault log
3375 * global invalidate context cache
3376 * global invalidate iotlb
3377 * enable translation
3378 */
Jiang Liu7c919772014-01-06 14:18:18 +08003379 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003380 if (drhd->ignored) {
3381 /*
3382 * we always have to disable PMRs or DMA may fail on
3383 * this device
3384 */
3385 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003386 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003387 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003388 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003389
3390 iommu_flush_write_buffer(iommu);
3391
David Woodhousea222a7f2015-10-07 23:35:18 +01003392#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003393 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
Lu Baolua7755c32019-04-19 14:43:29 +08003394 /*
3395 * Call dmar_alloc_hwirq() with dmar_global_lock held,
3396 * could cause possible lock race condition.
3397 */
3398 up_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003399 ret = intel_svm_enable_prq(iommu);
Lu Baolua7755c32019-04-19 14:43:29 +08003400 down_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003401 if (ret)
3402 goto free_iommu;
3403 }
3404#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003405 ret = dmar_set_interrupt(iommu);
3406 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003407 goto free_iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003408 }
3409
3410 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003411
3412free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003413 for_each_active_iommu(iommu, drhd) {
3414 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003415 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003416 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003417
Weidong Hand9630fe2008-12-08 11:06:32 +08003418 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003419
Jiang Liu989d51f2014-02-19 14:07:21 +08003420error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003421 return ret;
3422}
3423
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003424/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003425static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003426 struct dmar_domain *domain,
3427 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003428{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06003429 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003430
Lu Baolucb8b8922020-01-02 08:18:19 +08003431 /*
3432 * Restrict dma_mask to the width that the iommu can handle.
3433 * First-level translation restricts the input-address to a
3434 * canonical address (i.e., address bits 63:N have the same
3435 * value as address bit [N-1], where N is 48-bits with 4-level
3436 * paging and 57-bits with 5-level paging). Hence, skip bit
3437 * [N-1].
3438 */
3439 if (domain_use_first_level(domain))
3440 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw - 1),
3441 dma_mask);
3442 else
3443 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw),
3444 dma_mask);
3445
Robin Murphy8f6429c2015-07-16 19:40:12 +01003446 /* Ensure we reserve the whole size-aligned region */
3447 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003448
3449 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003450 /*
3451 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003452 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003453 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003454 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003455 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003456 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003457 if (iova_pfn)
3458 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003459 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003460 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3461 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003462 if (unlikely(!iova_pfn)) {
Qian Cai944c9172019-11-22 14:16:54 -05003463 dev_err_once(dev, "Allocating %ld-page iova failed\n",
3464 nrpages);
Omer Peleg2aac6302016-04-20 11:33:57 +03003465 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003466 }
3467
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003468 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003469}
3470
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003471static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3472 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003473{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003474 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003475 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003476 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003477 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003478 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003479 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003480 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003481
3482 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003483
Lu Baolu6fc70202020-05-06 09:59:47 +08003484 if (unlikely(attach_deferred(dev)))
3485 do_deferred_attach(dev);
3486
Joerg Roedel96d170f2020-02-17 17:27:44 +01003487 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003488 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003489 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003490
Weidong Han8c11e792008-12-08 15:29:22 +08003491 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003492 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003493
Omer Peleg2aac6302016-04-20 11:33:57 +03003494 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3495 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003496 goto error;
3497
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003498 /*
3499 * Check if DMAR supports zero-length reads on write only
3500 * mappings..
3501 */
3502 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003503 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003504 prot |= DMA_PTE_READ;
3505 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3506 prot |= DMA_PTE_WRITE;
3507 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003508 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003509 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003510 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003511 * is not a big problem
3512 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003513 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003514 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003515 if (ret)
3516 goto error;
3517
Omer Peleg2aac6302016-04-20 11:33:57 +03003518 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003519 start_paddr += paddr & ~PAGE_MASK;
Lu Baolu3b530342019-09-06 14:14:51 +08003520
3521 trace_map_single(dev, start_paddr, paddr, size << VTD_PAGE_SHIFT);
3522
David Woodhouse03d6a242009-06-28 15:33:46 +01003523 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003524
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003525error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003526 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003527 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003528 dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n",
3529 size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003530 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003531}
3532
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003533static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3534 unsigned long offset, size_t size,
3535 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003536 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003537{
Lu Baolu6fc70202020-05-06 09:59:47 +08003538 return __intel_map_single(dev, page_to_phys(page) + offset,
3539 size, dir, *dev->dma_mask);
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003540}
3541
3542static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3543 size_t size, enum dma_data_direction dir,
3544 unsigned long attrs)
3545{
Lu Baolu6fc70202020-05-06 09:59:47 +08003546 return __intel_map_single(dev, phys_addr, size, dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003547}
3548
Omer Peleg769530e2016-04-20 11:33:25 +03003549static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003550{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003551 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003552 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003553 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003554 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003555 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003556 struct page *freelist;
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003557 struct pci_dev *pdev = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003558
David Woodhouse1525a292014-03-06 16:19:30 +00003559 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003560 BUG_ON(!domain);
3561
Weidong Han8c11e792008-12-08 15:29:22 +08003562 iommu = domain_get_iommu(domain);
3563
Omer Peleg2aac6302016-04-20 11:33:57 +03003564 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003565
Omer Peleg769530e2016-04-20 11:33:25 +03003566 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003567 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003568 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003569
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003570 if (dev_is_pci(dev))
3571 pdev = to_pci_dev(dev);
3572
David Woodhouseea8ea462014-03-05 17:09:32 +00003573 freelist = domain_unmap(domain, start_pfn, last_pfn);
Dmitry Safonoveffa4672019-07-16 22:38:05 +01003574 if (intel_iommu_strict || (pdev && pdev->untrusted) ||
3575 !has_iova_flush_queue(&domain->iovad)) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003576 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003577 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003578 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003579 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003580 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003581 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003582 queue_iova(&domain->iovad, iova_pfn, nrpages,
3583 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003584 /*
3585 * queue up the release of the unmap to save the 1/6th of the
3586 * cpu used up by the iotlb flush operation...
3587 */
mark gross5e0d2a62008-03-04 15:22:08 -08003588 }
Lu Baolu3b530342019-09-06 14:14:51 +08003589
3590 trace_unmap_single(dev, dev_addr, size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003591}
3592
Jiang Liud41a4ad2014-07-11 14:19:34 +08003593static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3594 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003595 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003596{
Lu Baolu6fc70202020-05-06 09:59:47 +08003597 intel_unmap(dev, dev_addr, size);
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003598}
3599
3600static void intel_unmap_resource(struct device *dev, dma_addr_t dev_addr,
3601 size_t size, enum dma_data_direction dir, unsigned long attrs)
3602{
Lu Baolu6fc70202020-05-06 09:59:47 +08003603 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003604}
3605
David Woodhouse5040a912014-03-09 16:14:00 -07003606static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003607 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003608 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003609{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003610 struct page *page = NULL;
3611 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003612
Lu Baolu6fc70202020-05-06 09:59:47 +08003613 if (unlikely(attach_deferred(dev)))
3614 do_deferred_attach(dev);
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003615
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003616 size = PAGE_ALIGN(size);
3617 order = get_order(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003618
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003619 if (gfpflags_allow_blocking(flags)) {
3620 unsigned int count = size >> PAGE_SHIFT;
3621
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003622 page = dma_alloc_from_contiguous(dev, count, order,
3623 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003624 }
3625
3626 if (!page)
3627 page = alloc_pages(flags, order);
3628 if (!page)
3629 return NULL;
3630 memset(page_address(page), 0, size);
3631
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003632 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3633 DMA_BIDIRECTIONAL,
3634 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003635 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003636 return page_address(page);
3637 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3638 __free_pages(page, order);
3639
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003640 return NULL;
3641}
3642
David Woodhouse5040a912014-03-09 16:14:00 -07003643static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003644 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003645{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003646 int order;
3647 struct page *page = virt_to_page(vaddr);
3648
3649 size = PAGE_ALIGN(size);
3650 order = get_order(size);
3651
3652 intel_unmap(dev, dma_handle, size);
3653 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3654 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003655}
3656
David Woodhouse5040a912014-03-09 16:14:00 -07003657static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003658 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003659 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003660{
Omer Peleg769530e2016-04-20 11:33:25 +03003661 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3662 unsigned long nrpages = 0;
3663 struct scatterlist *sg;
3664 int i;
3665
3666 for_each_sg(sglist, sg, nelems, i) {
3667 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3668 }
3669
3670 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Lu Baolu3b530342019-09-06 14:14:51 +08003671
3672 trace_unmap_sg(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003673}
3674
David Woodhouse5040a912014-03-09 16:14:00 -07003675static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003676 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003677{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003678 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003679 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003680 size_t size = 0;
3681 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003682 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003683 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003684 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003685 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003686 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003687
3688 BUG_ON(dir == DMA_NONE);
Lu Baolu6fc70202020-05-06 09:59:47 +08003689
3690 if (unlikely(attach_deferred(dev)))
3691 do_deferred_attach(dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003692
Joerg Roedel96d170f2020-02-17 17:27:44 +01003693 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003694 if (!domain)
3695 return 0;
3696
Weidong Han8c11e792008-12-08 15:29:22 +08003697 iommu = domain_get_iommu(domain);
3698
David Woodhouseb536d242009-06-28 14:49:31 +01003699 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003700 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003701
Omer Peleg2aac6302016-04-20 11:33:57 +03003702 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003703 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003704 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003705 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003706 return 0;
3707 }
3708
3709 /*
3710 * Check if DMAR supports zero-length reads on write only
3711 * mappings..
3712 */
3713 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003714 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003715 prot |= DMA_PTE_READ;
3716 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3717 prot |= DMA_PTE_WRITE;
3718
Omer Peleg2aac6302016-04-20 11:33:57 +03003719 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003720
Fenghua Yuf5329592009-08-04 15:09:37 -07003721 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003722 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003723 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003724 start_vpfn + size - 1,
3725 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003726 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003727 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003728 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729
Lu Baolu984d03a2020-01-02 08:18:11 +08003730 for_each_sg(sglist, sg, nelems, i)
3731 trace_map_sg(dev, i + 1, nelems, sg);
Lu Baolu3b530342019-09-06 14:14:51 +08003732
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003733 return nelems;
3734}
3735
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003736static u64 intel_get_required_mask(struct device *dev)
3737{
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003738 return DMA_BIT_MASK(32);
3739}
3740
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003741static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003742 .alloc = intel_alloc_coherent,
3743 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003744 .map_sg = intel_map_sg,
3745 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003746 .map_page = intel_map_page,
3747 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003748 .map_resource = intel_map_resource,
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003749 .unmap_resource = intel_unmap_resource,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003750 .dma_supported = dma_direct_supported,
Christoph Hellwigf9f32322019-08-06 15:01:50 +03003751 .mmap = dma_common_mmap,
3752 .get_sgtable = dma_common_get_sgtable,
Christoph Hellwigefa70f22020-09-01 13:34:33 +02003753 .alloc_pages = dma_common_alloc_pages,
3754 .free_pages = dma_common_free_pages,
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003755 .get_required_mask = intel_get_required_mask,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003756};
3757
Lu Baolucfb94a32019-09-06 14:14:52 +08003758static void
3759bounce_sync_single(struct device *dev, dma_addr_t addr, size_t size,
3760 enum dma_data_direction dir, enum dma_sync_target target)
3761{
3762 struct dmar_domain *domain;
3763 phys_addr_t tlb_addr;
3764
3765 domain = find_domain(dev);
3766 if (WARN_ON(!domain))
3767 return;
3768
3769 tlb_addr = intel_iommu_iova_to_phys(&domain->domain, addr);
3770 if (is_swiotlb_buffer(tlb_addr))
3771 swiotlb_tbl_sync_single(dev, tlb_addr, size, dir, target);
3772}
3773
3774static dma_addr_t
3775bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
3776 enum dma_data_direction dir, unsigned long attrs,
3777 u64 dma_mask)
3778{
3779 size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
3780 struct dmar_domain *domain;
3781 struct intel_iommu *iommu;
3782 unsigned long iova_pfn;
3783 unsigned long nrpages;
3784 phys_addr_t tlb_addr;
3785 int prot = 0;
3786 int ret;
3787
Joerg Roedela11bfde2020-02-17 17:20:59 +01003788 if (unlikely(attach_deferred(dev)))
3789 do_deferred_attach(dev);
3790
Joerg Roedel96d170f2020-02-17 17:27:44 +01003791 domain = find_domain(dev);
Joerg Roedela11bfde2020-02-17 17:20:59 +01003792
Lu Baolucfb94a32019-09-06 14:14:52 +08003793 if (WARN_ON(dir == DMA_NONE || !domain))
3794 return DMA_MAPPING_ERROR;
3795
3796 iommu = domain_get_iommu(domain);
3797 if (WARN_ON(!iommu))
3798 return DMA_MAPPING_ERROR;
3799
3800 nrpages = aligned_nrpages(0, size);
3801 iova_pfn = intel_alloc_iova(dev, domain,
3802 dma_to_mm_pfn(nrpages), dma_mask);
3803 if (!iova_pfn)
3804 return DMA_MAPPING_ERROR;
3805
3806 /*
3807 * Check if DMAR supports zero-length reads on write only
3808 * mappings..
3809 */
3810 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL ||
3811 !cap_zlr(iommu->cap))
3812 prot |= DMA_PTE_READ;
3813 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3814 prot |= DMA_PTE_WRITE;
3815
3816 /*
3817 * If both the physical buffer start address and size are
3818 * page aligned, we don't need to use a bounce page.
3819 */
3820 if (!IS_ALIGNED(paddr | size, VTD_PAGE_SIZE)) {
Christoph Hellwigfc0021a2020-10-23 08:33:09 +02003821 tlb_addr = swiotlb_tbl_map_single(dev, paddr, size,
3822 aligned_size, dir, attrs);
Lu Baolucfb94a32019-09-06 14:14:52 +08003823 if (tlb_addr == DMA_MAPPING_ERROR) {
3824 goto swiotlb_error;
3825 } else {
3826 /* Cleanup the padding area. */
3827 void *padding_start = phys_to_virt(tlb_addr);
3828 size_t padding_size = aligned_size;
3829
3830 if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
3831 (dir == DMA_TO_DEVICE ||
3832 dir == DMA_BIDIRECTIONAL)) {
3833 padding_start += size;
3834 padding_size -= size;
3835 }
3836
3837 memset(padding_start, 0, padding_size);
3838 }
3839 } else {
3840 tlb_addr = paddr;
3841 }
3842
3843 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
3844 tlb_addr >> VTD_PAGE_SHIFT, nrpages, prot);
3845 if (ret)
3846 goto mapping_error;
3847
3848 trace_bounce_map_single(dev, iova_pfn << PAGE_SHIFT, paddr, size);
3849
3850 return (phys_addr_t)iova_pfn << PAGE_SHIFT;
3851
3852mapping_error:
3853 if (is_swiotlb_buffer(tlb_addr))
3854 swiotlb_tbl_unmap_single(dev, tlb_addr, size,
3855 aligned_size, dir, attrs);
3856swiotlb_error:
3857 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
3858 dev_err(dev, "Device bounce map: %zx@%llx dir %d --- failed\n",
3859 size, (unsigned long long)paddr, dir);
3860
3861 return DMA_MAPPING_ERROR;
3862}
3863
3864static void
3865bounce_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
3866 enum dma_data_direction dir, unsigned long attrs)
3867{
3868 size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
3869 struct dmar_domain *domain;
3870 phys_addr_t tlb_addr;
3871
3872 domain = find_domain(dev);
3873 if (WARN_ON(!domain))
3874 return;
3875
3876 tlb_addr = intel_iommu_iova_to_phys(&domain->domain, dev_addr);
3877 if (WARN_ON(!tlb_addr))
3878 return;
3879
3880 intel_unmap(dev, dev_addr, size);
3881 if (is_swiotlb_buffer(tlb_addr))
3882 swiotlb_tbl_unmap_single(dev, tlb_addr, size,
3883 aligned_size, dir, attrs);
3884
3885 trace_bounce_unmap_single(dev, dev_addr, size);
3886}
3887
3888static dma_addr_t
3889bounce_map_page(struct device *dev, struct page *page, unsigned long offset,
3890 size_t size, enum dma_data_direction dir, unsigned long attrs)
3891{
3892 return bounce_map_single(dev, page_to_phys(page) + offset,
3893 size, dir, attrs, *dev->dma_mask);
3894}
3895
3896static dma_addr_t
3897bounce_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
3898 enum dma_data_direction dir, unsigned long attrs)
3899{
3900 return bounce_map_single(dev, phys_addr, size,
3901 dir, attrs, *dev->dma_mask);
3902}
3903
3904static void
3905bounce_unmap_page(struct device *dev, dma_addr_t dev_addr, size_t size,
3906 enum dma_data_direction dir, unsigned long attrs)
3907{
3908 bounce_unmap_single(dev, dev_addr, size, dir, attrs);
3909}
3910
3911static void
3912bounce_unmap_resource(struct device *dev, dma_addr_t dev_addr, size_t size,
3913 enum dma_data_direction dir, unsigned long attrs)
3914{
3915 bounce_unmap_single(dev, dev_addr, size, dir, attrs);
3916}
3917
3918static void
3919bounce_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems,
3920 enum dma_data_direction dir, unsigned long attrs)
3921{
3922 struct scatterlist *sg;
3923 int i;
3924
3925 for_each_sg(sglist, sg, nelems, i)
3926 bounce_unmap_page(dev, sg->dma_address,
3927 sg_dma_len(sg), dir, attrs);
3928}
3929
3930static int
3931bounce_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
3932 enum dma_data_direction dir, unsigned long attrs)
3933{
3934 int i;
3935 struct scatterlist *sg;
3936
3937 for_each_sg(sglist, sg, nelems, i) {
3938 sg->dma_address = bounce_map_page(dev, sg_page(sg),
3939 sg->offset, sg->length,
3940 dir, attrs);
3941 if (sg->dma_address == DMA_MAPPING_ERROR)
3942 goto out_unmap;
3943 sg_dma_len(sg) = sg->length;
3944 }
3945
Lu Baolu984d03a2020-01-02 08:18:11 +08003946 for_each_sg(sglist, sg, nelems, i)
3947 trace_bounce_map_sg(dev, i + 1, nelems, sg);
3948
Lu Baolucfb94a32019-09-06 14:14:52 +08003949 return nelems;
3950
3951out_unmap:
3952 bounce_unmap_sg(dev, sglist, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
3953 return 0;
3954}
3955
3956static void
3957bounce_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
3958 size_t size, enum dma_data_direction dir)
3959{
3960 bounce_sync_single(dev, addr, size, dir, SYNC_FOR_CPU);
3961}
3962
3963static void
3964bounce_sync_single_for_device(struct device *dev, dma_addr_t addr,
3965 size_t size, enum dma_data_direction dir)
3966{
3967 bounce_sync_single(dev, addr, size, dir, SYNC_FOR_DEVICE);
3968}
3969
3970static void
3971bounce_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
3972 int nelems, enum dma_data_direction dir)
3973{
3974 struct scatterlist *sg;
3975 int i;
3976
3977 for_each_sg(sglist, sg, nelems, i)
3978 bounce_sync_single(dev, sg_dma_address(sg),
3979 sg_dma_len(sg), dir, SYNC_FOR_CPU);
3980}
3981
3982static void
3983bounce_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
3984 int nelems, enum dma_data_direction dir)
3985{
3986 struct scatterlist *sg;
3987 int i;
3988
3989 for_each_sg(sglist, sg, nelems, i)
3990 bounce_sync_single(dev, sg_dma_address(sg),
3991 sg_dma_len(sg), dir, SYNC_FOR_DEVICE);
3992}
3993
3994static const struct dma_map_ops bounce_dma_ops = {
3995 .alloc = intel_alloc_coherent,
3996 .free = intel_free_coherent,
3997 .map_sg = bounce_map_sg,
3998 .unmap_sg = bounce_unmap_sg,
3999 .map_page = bounce_map_page,
4000 .unmap_page = bounce_unmap_page,
4001 .sync_single_for_cpu = bounce_sync_single_for_cpu,
4002 .sync_single_for_device = bounce_sync_single_for_device,
4003 .sync_sg_for_cpu = bounce_sync_sg_for_cpu,
4004 .sync_sg_for_device = bounce_sync_sg_for_device,
4005 .map_resource = bounce_map_resource,
4006 .unmap_resource = bounce_unmap_resource,
Christoph Hellwigefa70f22020-09-01 13:34:33 +02004007 .alloc_pages = dma_common_alloc_pages,
4008 .free_pages = dma_common_free_pages,
Lu Baolucfb94a32019-09-06 14:14:52 +08004009 .dma_supported = dma_direct_supported,
4010};
4011
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004012static inline int iommu_domain_cache_init(void)
4013{
4014 int ret = 0;
4015
4016 iommu_domain_cache = kmem_cache_create("iommu_domain",
4017 sizeof(struct dmar_domain),
4018 0,
4019 SLAB_HWCACHE_ALIGN,
4020
4021 NULL);
4022 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004023 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004024 ret = -ENOMEM;
4025 }
4026
4027 return ret;
4028}
4029
4030static inline int iommu_devinfo_cache_init(void)
4031{
4032 int ret = 0;
4033
4034 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
4035 sizeof(struct device_domain_info),
4036 0,
4037 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004038 NULL);
4039 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004040 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004041 ret = -ENOMEM;
4042 }
4043
4044 return ret;
4045}
4046
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004047static int __init iommu_init_mempool(void)
4048{
4049 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004050 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004051 if (ret)
4052 return ret;
4053
4054 ret = iommu_domain_cache_init();
4055 if (ret)
4056 goto domain_error;
4057
4058 ret = iommu_devinfo_cache_init();
4059 if (!ret)
4060 return ret;
4061
4062 kmem_cache_destroy(iommu_domain_cache);
4063domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004064 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004065
4066 return -ENOMEM;
4067}
4068
4069static void __init iommu_exit_mempool(void)
4070{
4071 kmem_cache_destroy(iommu_devinfo_cache);
4072 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004073 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004074}
4075
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004076static void __init init_no_remapping_devices(void)
4077{
4078 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004079 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004080 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004081
4082 for_each_drhd_unit(drhd) {
4083 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004084 for_each_active_dev_scope(drhd->devices,
4085 drhd->devices_cnt, i, dev)
4086 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004087 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004088 if (i == drhd->devices_cnt)
4089 drhd->ignored = 1;
4090 }
4091 }
4092
Jiang Liu7c919772014-01-06 14:18:18 +08004093 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004094 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004095 continue;
4096
Jiang Liub683b232014-02-19 14:07:32 +08004097 for_each_active_dev_scope(drhd->devices,
4098 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004099 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004100 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004101 if (i < drhd->devices_cnt)
4102 continue;
4103
David Woodhousec0771df2011-10-14 20:59:46 +01004104 /* This IOMMU has *only* gfx devices. Either bypass it or
4105 set the gfx_mapped flag, as appropriate */
Lu Baolub1012ca2020-07-23 09:34:37 +08004106 drhd->gfx_dedicated = 1;
Lu Baolu2d33b7d2020-09-03 14:51:32 +08004107 if (!dmar_map_gfx)
David Woodhousec0771df2011-10-14 20:59:46 +01004108 drhd->ignored = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004109 }
4110}
4111
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004112#ifdef CONFIG_SUSPEND
4113static int init_iommu_hw(void)
4114{
4115 struct dmar_drhd_unit *drhd;
4116 struct intel_iommu *iommu = NULL;
4117
4118 for_each_active_iommu(iommu, drhd)
4119 if (iommu->qi)
4120 dmar_reenable_qi(iommu);
4121
Joseph Cihulab7792602011-05-03 00:08:37 -07004122 for_each_iommu(iommu, drhd) {
4123 if (drhd->ignored) {
4124 /*
4125 * we always have to disable PMRs or DMA may fail on
4126 * this device
4127 */
4128 if (force_on)
4129 iommu_disable_protect_mem_regions(iommu);
4130 continue;
4131 }
Lu Baolu095303e2019-04-29 09:16:02 +08004132
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004133 iommu_flush_write_buffer(iommu);
4134
4135 iommu_set_root_entry(iommu);
4136
4137 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004138 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004139 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4140 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004141 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004142 }
4143
4144 return 0;
4145}
4146
4147static void iommu_flush_all(void)
4148{
4149 struct dmar_drhd_unit *drhd;
4150 struct intel_iommu *iommu;
4151
4152 for_each_active_iommu(iommu, drhd) {
4153 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004154 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004155 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004156 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004157 }
4158}
4159
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004160static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004161{
4162 struct dmar_drhd_unit *drhd;
4163 struct intel_iommu *iommu = NULL;
4164 unsigned long flag;
4165
4166 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004167 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004168 GFP_ATOMIC);
4169 if (!iommu->iommu_state)
4170 goto nomem;
4171 }
4172
4173 iommu_flush_all();
4174
4175 for_each_active_iommu(iommu, drhd) {
4176 iommu_disable_translation(iommu);
4177
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004178 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004179
4180 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4181 readl(iommu->reg + DMAR_FECTL_REG);
4182 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4183 readl(iommu->reg + DMAR_FEDATA_REG);
4184 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4185 readl(iommu->reg + DMAR_FEADDR_REG);
4186 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4187 readl(iommu->reg + DMAR_FEUADDR_REG);
4188
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004189 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004190 }
4191 return 0;
4192
4193nomem:
4194 for_each_active_iommu(iommu, drhd)
4195 kfree(iommu->iommu_state);
4196
4197 return -ENOMEM;
4198}
4199
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004200static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004201{
4202 struct dmar_drhd_unit *drhd;
4203 struct intel_iommu *iommu = NULL;
4204 unsigned long flag;
4205
4206 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004207 if (force_on)
4208 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4209 else
4210 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004211 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004212 }
4213
4214 for_each_active_iommu(iommu, drhd) {
4215
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004216 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004217
4218 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4219 iommu->reg + DMAR_FECTL_REG);
4220 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4221 iommu->reg + DMAR_FEDATA_REG);
4222 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4223 iommu->reg + DMAR_FEADDR_REG);
4224 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4225 iommu->reg + DMAR_FEUADDR_REG);
4226
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004227 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004228 }
4229
4230 for_each_active_iommu(iommu, drhd)
4231 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004232}
4233
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004234static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004235 .resume = iommu_resume,
4236 .suspend = iommu_suspend,
4237};
4238
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004239static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004240{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004241 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004242}
4243
4244#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004245static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004246#endif /* CONFIG_PM */
4247
Barret Rhodence4cc52b2020-01-15 11:03:57 +08004248static int rmrr_sanity_check(struct acpi_dmar_reserved_memory *rmrr)
4249{
4250 if (!IS_ALIGNED(rmrr->base_address, PAGE_SIZE) ||
4251 !IS_ALIGNED(rmrr->end_address + 1, PAGE_SIZE) ||
4252 rmrr->end_address <= rmrr->base_address ||
4253 arch_rmrr_sanity_check(rmrr))
4254 return -EINVAL;
4255
4256 return 0;
4257}
4258
Jiang Liuc2a0b532014-11-09 22:47:56 +08004259int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004260{
4261 struct acpi_dmar_reserved_memory *rmrr;
4262 struct dmar_rmrr_unit *rmrru;
Yian Chenf036c7f2019-10-17 04:39:19 -07004263
4264 rmrr = (struct acpi_dmar_reserved_memory *)header;
Hans de Goede96788c72020-03-09 15:01:38 +01004265 if (rmrr_sanity_check(rmrr)) {
4266 pr_warn(FW_BUG
Barret Rhodenf5a68bb2020-01-15 11:03:56 +08004267 "Your BIOS is broken; bad RMRR [%#018Lx-%#018Lx]\n"
4268 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4269 rmrr->base_address, rmrr->end_address,
4270 dmi_get_system_info(DMI_BIOS_VENDOR),
4271 dmi_get_system_info(DMI_BIOS_VERSION),
4272 dmi_get_system_info(DMI_PRODUCT_VERSION));
Hans de Goede96788c72020-03-09 15:01:38 +01004273 add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
4274 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004275
4276 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4277 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004278 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004279
4280 rmrru->hdr = header;
Yian Chenf036c7f2019-10-17 04:39:19 -07004281
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004282 rmrru->base_address = rmrr->base_address;
4283 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004284
Jiang Liu2e455282014-02-19 14:07:36 +08004285 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4286 ((void *)rmrr) + rmrr->header.length,
4287 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004288 if (rmrru->devices_cnt && rmrru->devices == NULL)
Eric Auger5f64ce52019-06-03 08:53:31 +02004289 goto free_rmrru;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004290
Jiang Liu2e455282014-02-19 14:07:36 +08004291 list_add(&rmrru->list, &dmar_rmrr_units);
4292
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004293 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004294free_rmrru:
4295 kfree(rmrru);
4296out:
4297 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004298}
4299
Jiang Liu6b197242014-11-09 22:47:58 +08004300static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4301{
4302 struct dmar_atsr_unit *atsru;
4303 struct acpi_dmar_atsr *tmp;
4304
Qian Caic6f4ebd2020-03-17 11:03:26 -04004305 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list,
4306 dmar_rcu_check()) {
Jiang Liu6b197242014-11-09 22:47:58 +08004307 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4308 if (atsr->segment != tmp->segment)
4309 continue;
4310 if (atsr->header.length != tmp->header.length)
4311 continue;
4312 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4313 return atsru;
4314 }
4315
4316 return NULL;
4317}
4318
4319int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004320{
4321 struct acpi_dmar_atsr *atsr;
4322 struct dmar_atsr_unit *atsru;
4323
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004324 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004325 return 0;
4326
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004327 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004328 atsru = dmar_find_atsr(atsr);
4329 if (atsru)
4330 return 0;
4331
4332 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004333 if (!atsru)
4334 return -ENOMEM;
4335
Jiang Liu6b197242014-11-09 22:47:58 +08004336 /*
4337 * If memory is allocated from slab by ACPI _DSM method, we need to
4338 * copy the memory content because the memory buffer will be freed
4339 * on return.
4340 */
4341 atsru->hdr = (void *)(atsru + 1);
4342 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004343 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004344 if (!atsru->include_all) {
4345 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4346 (void *)atsr + atsr->header.length,
4347 &atsru->devices_cnt);
4348 if (atsru->devices_cnt && atsru->devices == NULL) {
4349 kfree(atsru);
4350 return -ENOMEM;
4351 }
4352 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004353
Jiang Liu0e242612014-02-19 14:07:34 +08004354 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004355
4356 return 0;
4357}
4358
Jiang Liu9bdc5312014-01-06 14:18:27 +08004359static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4360{
4361 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4362 kfree(atsru);
4363}
4364
Jiang Liu6b197242014-11-09 22:47:58 +08004365int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4366{
4367 struct acpi_dmar_atsr *atsr;
4368 struct dmar_atsr_unit *atsru;
4369
4370 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4371 atsru = dmar_find_atsr(atsr);
4372 if (atsru) {
4373 list_del_rcu(&atsru->list);
4374 synchronize_rcu();
4375 intel_iommu_free_atsr(atsru);
4376 }
4377
4378 return 0;
4379}
4380
4381int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4382{
4383 int i;
4384 struct device *dev;
4385 struct acpi_dmar_atsr *atsr;
4386 struct dmar_atsr_unit *atsru;
4387
4388 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4389 atsru = dmar_find_atsr(atsr);
4390 if (!atsru)
4391 return 0;
4392
Linus Torvalds194dc872016-07-27 20:03:31 -07004393 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004394 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4395 i, dev)
4396 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004397 }
Jiang Liu6b197242014-11-09 22:47:58 +08004398
4399 return 0;
4400}
4401
Jiang Liuffebeb42014-11-09 22:48:02 +08004402static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4403{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004404 int sp, ret;
Jiang Liuffebeb42014-11-09 22:48:02 +08004405 struct intel_iommu *iommu = dmaru->iommu;
4406
4407 if (g_iommus[iommu->seq_id])
4408 return 0;
4409
4410 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004411 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004412 iommu->name);
4413 return -ENXIO;
4414 }
4415 if (!ecap_sc_support(iommu->ecap) &&
4416 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004417 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004418 iommu->name);
4419 return -ENXIO;
4420 }
Lu Baolu64229e82020-01-02 08:18:20 +08004421 sp = domain_update_iommu_superpage(NULL, iommu) - 1;
Jiang Liuffebeb42014-11-09 22:48:02 +08004422 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004423 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004424 iommu->name);
4425 return -ENXIO;
4426 }
4427
4428 /*
4429 * Disable translation if already enabled prior to OS handover.
4430 */
4431 if (iommu->gcmd & DMA_GCMD_TE)
4432 iommu_disable_translation(iommu);
4433
4434 g_iommus[iommu->seq_id] = iommu;
4435 ret = iommu_init_domains(iommu);
4436 if (ret == 0)
4437 ret = iommu_alloc_root_entry(iommu);
4438 if (ret)
4439 goto out;
4440
Jacob Panff3dc652020-01-02 08:18:03 +08004441 intel_svm_check(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004442
Jiang Liuffebeb42014-11-09 22:48:02 +08004443 if (dmaru->ignored) {
4444 /*
4445 * we always have to disable PMRs or DMA may fail on this device
4446 */
4447 if (force_on)
4448 iommu_disable_protect_mem_regions(iommu);
4449 return 0;
4450 }
4451
4452 intel_iommu_init_qi(iommu);
4453 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004454
4455#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004456 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004457 ret = intel_svm_enable_prq(iommu);
4458 if (ret)
4459 goto disable_iommu;
4460 }
4461#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004462 ret = dmar_set_interrupt(iommu);
4463 if (ret)
4464 goto disable_iommu;
4465
4466 iommu_set_root_entry(iommu);
4467 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4468 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4469 iommu_enable_translation(iommu);
4470
Jiang Liuffebeb42014-11-09 22:48:02 +08004471 iommu_disable_protect_mem_regions(iommu);
4472 return 0;
4473
4474disable_iommu:
4475 disable_dmar_iommu(iommu);
4476out:
4477 free_dmar_iommu(iommu);
4478 return ret;
4479}
4480
Jiang Liu6b197242014-11-09 22:47:58 +08004481int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4482{
Jiang Liuffebeb42014-11-09 22:48:02 +08004483 int ret = 0;
4484 struct intel_iommu *iommu = dmaru->iommu;
4485
4486 if (!intel_iommu_enabled)
4487 return 0;
4488 if (iommu == NULL)
4489 return -EINVAL;
4490
4491 if (insert) {
4492 ret = intel_iommu_add(dmaru);
4493 } else {
4494 disable_dmar_iommu(iommu);
4495 free_dmar_iommu(iommu);
4496 }
4497
4498 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004499}
4500
Jiang Liu9bdc5312014-01-06 14:18:27 +08004501static void intel_iommu_free_dmars(void)
4502{
4503 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4504 struct dmar_atsr_unit *atsru, *atsr_n;
4505
4506 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4507 list_del(&rmrru->list);
4508 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
4509 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004510 }
4511
Jiang Liu9bdc5312014-01-06 14:18:27 +08004512 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4513 list_del(&atsru->list);
4514 intel_iommu_free_atsr(atsru);
4515 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004516}
4517
4518int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4519{
Jiang Liub683b232014-02-19 14:07:32 +08004520 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004521 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004522 struct pci_dev *bridge = NULL;
4523 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004524 struct acpi_dmar_atsr *atsr;
4525 struct dmar_atsr_unit *atsru;
4526
4527 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004528 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004529 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004530 /* If it's an integrated device, allow ATS */
4531 if (!bridge)
4532 return 1;
4533 /* Connected via non-PCIe: no ATS */
4534 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004535 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004536 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004537 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004538 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004539 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004540 }
4541
Jiang Liu0e242612014-02-19 14:07:34 +08004542 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004543 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4544 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4545 if (atsr->segment != pci_domain_nr(dev->bus))
4546 continue;
4547
Jiang Liub683b232014-02-19 14:07:32 +08004548 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004549 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004550 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004551
4552 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004553 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004554 }
Jiang Liub683b232014-02-19 14:07:32 +08004555 ret = 0;
4556out:
Jiang Liu0e242612014-02-19 14:07:34 +08004557 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004558
Jiang Liub683b232014-02-19 14:07:32 +08004559 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004560}
4561
Jiang Liu59ce0512014-02-19 14:07:35 +08004562int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4563{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004564 int ret;
Jiang Liu59ce0512014-02-19 14:07:35 +08004565 struct dmar_rmrr_unit *rmrru;
4566 struct dmar_atsr_unit *atsru;
4567 struct acpi_dmar_atsr *atsr;
4568 struct acpi_dmar_reserved_memory *rmrr;
4569
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004570 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004571 return 0;
4572
4573 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4574 rmrr = container_of(rmrru->hdr,
4575 struct acpi_dmar_reserved_memory, header);
4576 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4577 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4578 ((void *)rmrr) + rmrr->header.length,
4579 rmrr->segment, rmrru->devices,
4580 rmrru->devices_cnt);
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004581 if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004582 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004583 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004584 dmar_remove_dev_scope(info, rmrr->segment,
4585 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004586 }
4587 }
4588
4589 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4590 if (atsru->include_all)
4591 continue;
4592
4593 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4594 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4595 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4596 (void *)atsr + atsr->header.length,
4597 atsr->segment, atsru->devices,
4598 atsru->devices_cnt);
4599 if (ret > 0)
4600 break;
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004601 else if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004602 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004603 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004604 if (dmar_remove_dev_scope(info, atsr->segment,
4605 atsru->devices, atsru->devices_cnt))
4606 break;
4607 }
4608 }
4609
4610 return 0;
4611}
4612
Jiang Liu75f05562014-02-19 14:07:37 +08004613static int intel_iommu_memory_notifier(struct notifier_block *nb,
4614 unsigned long val, void *v)
4615{
4616 struct memory_notify *mhp = v;
Tom Murphye70b0812020-05-16 14:21:01 +08004617 unsigned long start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4618 unsigned long last_vpfn = mm_to_dma_pfn(mhp->start_pfn +
4619 mhp->nr_pages - 1);
Jiang Liu75f05562014-02-19 14:07:37 +08004620
4621 switch (val) {
4622 case MEM_GOING_ONLINE:
Tom Murphye70b0812020-05-16 14:21:01 +08004623 if (iommu_domain_identity_map(si_domain,
4624 start_vpfn, last_vpfn)) {
4625 pr_warn("Failed to build identity map for [%lx-%lx]\n",
4626 start_vpfn, last_vpfn);
Jiang Liu75f05562014-02-19 14:07:37 +08004627 return NOTIFY_BAD;
4628 }
4629 break;
4630
4631 case MEM_OFFLINE:
4632 case MEM_CANCEL_ONLINE:
Tom Murphye70b0812020-05-16 14:21:01 +08004633 {
Jiang Liu75f05562014-02-19 14:07:37 +08004634 struct dmar_drhd_unit *drhd;
4635 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004636 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004637
Tom Murphye70b0812020-05-16 14:21:01 +08004638 freelist = domain_unmap(si_domain,
4639 start_vpfn, last_vpfn);
David Woodhouseea8ea462014-03-05 17:09:32 +00004640
Jiang Liu75f05562014-02-19 14:07:37 +08004641 rcu_read_lock();
4642 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004643 iommu_flush_iotlb_psi(iommu, si_domain,
Tom Murphye70b0812020-05-16 14:21:01 +08004644 start_vpfn, mhp->nr_pages,
David Woodhouseea8ea462014-03-05 17:09:32 +00004645 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004646 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004647 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004648 }
4649 break;
4650 }
4651
4652 return NOTIFY_OK;
4653}
4654
4655static struct notifier_block intel_iommu_memory_nb = {
4656 .notifier_call = intel_iommu_memory_notifier,
4657 .priority = 0
4658};
4659
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004660static void free_all_cpu_cached_iovas(unsigned int cpu)
4661{
4662 int i;
4663
4664 for (i = 0; i < g_num_of_iommus; i++) {
4665 struct intel_iommu *iommu = g_iommus[i];
4666 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004667 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004668
4669 if (!iommu)
4670 continue;
4671
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004672 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004673 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004674
Tom Murphye70b0812020-05-16 14:21:01 +08004675 if (!domain || domain->domain.type != IOMMU_DOMAIN_DMA)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004676 continue;
Tom Murphye70b0812020-05-16 14:21:01 +08004677
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004678 free_cpu_cached_iovas(cpu, &domain->iovad);
4679 }
4680 }
4681}
4682
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004683static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004684{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004685 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004686 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004687}
4688
Joerg Roedel161b28a2017-03-28 17:04:52 +02004689static void intel_disable_iommus(void)
4690{
4691 struct intel_iommu *iommu = NULL;
4692 struct dmar_drhd_unit *drhd;
4693
4694 for_each_iommu(iommu, drhd)
4695 iommu_disable_translation(iommu);
4696}
4697
Deepa Dinamani6c3a44e2019-11-10 09:27:44 -08004698void intel_iommu_shutdown(void)
4699{
4700 struct dmar_drhd_unit *drhd;
4701 struct intel_iommu *iommu = NULL;
4702
4703 if (no_iommu || dmar_disabled)
4704 return;
4705
4706 down_write(&dmar_global_lock);
4707
4708 /* Disable PMRs explicitly here. */
4709 for_each_iommu(iommu, drhd)
4710 iommu_disable_protect_mem_regions(iommu);
4711
4712 /* Make sure the IOMMUs are switched off */
4713 intel_disable_iommus();
4714
4715 up_write(&dmar_global_lock);
4716}
4717
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004718static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4719{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004720 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4721
4722 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004723}
4724
Alex Williamsona5459cf2014-06-12 16:12:31 -06004725static ssize_t intel_iommu_show_version(struct device *dev,
4726 struct device_attribute *attr,
4727 char *buf)
4728{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004729 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004730 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4731 return sprintf(buf, "%d:%d\n",
4732 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4733}
4734static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4735
4736static ssize_t intel_iommu_show_address(struct device *dev,
4737 struct device_attribute *attr,
4738 char *buf)
4739{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004740 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004741 return sprintf(buf, "%llx\n", iommu->reg_phys);
4742}
4743static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4744
4745static ssize_t intel_iommu_show_cap(struct device *dev,
4746 struct device_attribute *attr,
4747 char *buf)
4748{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004749 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004750 return sprintf(buf, "%llx\n", iommu->cap);
4751}
4752static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4753
4754static ssize_t intel_iommu_show_ecap(struct device *dev,
4755 struct device_attribute *attr,
4756 char *buf)
4757{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004758 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004759 return sprintf(buf, "%llx\n", iommu->ecap);
4760}
4761static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4762
Alex Williamson2238c082015-07-14 15:24:53 -06004763static ssize_t intel_iommu_show_ndoms(struct device *dev,
4764 struct device_attribute *attr,
4765 char *buf)
4766{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004767 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004768 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4769}
4770static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4771
4772static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4773 struct device_attribute *attr,
4774 char *buf)
4775{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004776 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004777 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4778 cap_ndoms(iommu->cap)));
4779}
4780static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4781
Alex Williamsona5459cf2014-06-12 16:12:31 -06004782static struct attribute *intel_iommu_attrs[] = {
4783 &dev_attr_version.attr,
4784 &dev_attr_address.attr,
4785 &dev_attr_cap.attr,
4786 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004787 &dev_attr_domains_supported.attr,
4788 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004789 NULL,
4790};
4791
4792static struct attribute_group intel_iommu_group = {
4793 .name = "intel-iommu",
4794 .attrs = intel_iommu_attrs,
4795};
4796
4797const struct attribute_group *intel_iommu_groups[] = {
4798 &intel_iommu_group,
4799 NULL,
4800};
4801
Rajat Jain99b50be2020-07-07 15:46:03 -07004802static inline bool has_external_pci(void)
Lu Baolu89a60792018-10-23 15:45:01 +08004803{
4804 struct pci_dev *pdev = NULL;
Lu Baolu89a60792018-10-23 15:45:01 +08004805
Lu Baoluc5a5dc42019-09-06 14:14:50 +08004806 for_each_pci_dev(pdev)
Rajat Jain99b50be2020-07-07 15:46:03 -07004807 if (pdev->external_facing)
Lu Baoluc5a5dc42019-09-06 14:14:50 +08004808 return true;
Lu Baolu89a60792018-10-23 15:45:01 +08004809
Lu Baoluc5a5dc42019-09-06 14:14:50 +08004810 return false;
4811}
Lu Baolu89a60792018-10-23 15:45:01 +08004812
Lu Baoluc5a5dc42019-09-06 14:14:50 +08004813static int __init platform_optin_force_iommu(void)
4814{
Rajat Jain99b50be2020-07-07 15:46:03 -07004815 if (!dmar_platform_optin() || no_platform_optin || !has_external_pci())
Lu Baolu89a60792018-10-23 15:45:01 +08004816 return 0;
4817
4818 if (no_iommu || dmar_disabled)
4819 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4820
4821 /*
4822 * If Intel-IOMMU is disabled by default, we will apply identity
4823 * map for all devices except those marked as being untrusted.
4824 */
4825 if (dmar_disabled)
Lu Baolub89b6602020-01-15 11:03:59 +08004826 iommu_set_default_passthrough(false);
Lu Baolu89a60792018-10-23 15:45:01 +08004827
4828 dmar_disabled = 0;
Lu Baolu89a60792018-10-23 15:45:01 +08004829 no_iommu = 0;
4830
4831 return 1;
4832}
4833
Lu Baolufa212a92019-05-25 13:41:31 +08004834static int __init probe_acpi_namespace_devices(void)
4835{
4836 struct dmar_drhd_unit *drhd;
Qian Caiaf88ec32019-06-03 10:05:19 -04004837 /* To avoid a -Wunused-but-set-variable warning. */
4838 struct intel_iommu *iommu __maybe_unused;
Lu Baolufa212a92019-05-25 13:41:31 +08004839 struct device *dev;
4840 int i, ret = 0;
4841
4842 for_each_active_iommu(iommu, drhd) {
4843 for_each_active_dev_scope(drhd->devices,
4844 drhd->devices_cnt, i, dev) {
4845 struct acpi_device_physical_node *pn;
4846 struct iommu_group *group;
4847 struct acpi_device *adev;
4848
4849 if (dev->bus != &acpi_bus_type)
4850 continue;
4851
4852 adev = to_acpi_device(dev);
4853 mutex_lock(&adev->physical_node_lock);
4854 list_for_each_entry(pn,
4855 &adev->physical_node_list, node) {
4856 group = iommu_group_get(pn->dev);
4857 if (group) {
4858 iommu_group_put(group);
4859 continue;
4860 }
4861
4862 pn->dev->bus->iommu_ops = &intel_iommu_ops;
4863 ret = iommu_probe_device(pn->dev);
4864 if (ret)
4865 break;
4866 }
4867 mutex_unlock(&adev->physical_node_lock);
4868
4869 if (ret)
4870 return ret;
4871 }
4872 }
4873
4874 return 0;
4875}
4876
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004877int __init intel_iommu_init(void)
4878{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004879 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004880 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004881 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004882
Lu Baolu89a60792018-10-23 15:45:01 +08004883 /*
4884 * Intel IOMMU is required for a TXT/tboot launch or platform
4885 * opt in, so enforce that.
4886 */
Zhenzhong Duan4d213e72020-11-10 15:19:08 +08004887 force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
4888 platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004889
Jiang Liu3a5670e2014-02-19 14:07:33 +08004890 if (iommu_init_mempool()) {
4891 if (force_on)
4892 panic("tboot: Failed to initialize iommu memory\n");
4893 return -ENOMEM;
4894 }
4895
4896 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004897 if (dmar_table_init()) {
4898 if (force_on)
4899 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004900 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004901 }
4902
Suresh Siddhac2c72862011-08-23 17:05:19 -07004903 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004904 if (force_on)
4905 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004906 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004907 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004908
Joerg Roedelec154bf2017-10-06 15:00:53 +02004909 up_write(&dmar_global_lock);
4910
4911 /*
4912 * The bus notifier takes the dmar_global_lock, so lockdep will
4913 * complain later when we register it under the lock.
4914 */
4915 dmar_register_bus_notifier();
4916
4917 down_write(&dmar_global_lock);
4918
Megha Dey1da83472020-03-14 11:39:59 +08004919 if (!no_iommu)
4920 intel_iommu_debugfs_init();
4921
Joerg Roedel161b28a2017-03-28 17:04:52 +02004922 if (no_iommu || dmar_disabled) {
4923 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004924 * We exit the function here to ensure IOMMU's remapping and
4925 * mempool aren't setup, which means that the IOMMU's PMRs
4926 * won't be disabled via the call to init_dmars(). So disable
4927 * it explicitly here. The PMRs were setup by tboot prior to
4928 * calling SENTER, but the kernel is expected to reset/tear
4929 * down the PMRs.
4930 */
4931 if (intel_iommu_tboot_noforce) {
4932 for_each_iommu(iommu, drhd)
4933 iommu_disable_protect_mem_regions(iommu);
4934 }
4935
4936 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004937 * Make sure the IOMMUs are switched off, even when we
4938 * boot into a kexec kernel and the previous kernel left
4939 * them enabled
4940 */
4941 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004942 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004943 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004944
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004945 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004946 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004947
4948 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004949 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004950
Joseph Cihula51a63e62011-03-21 11:04:24 -07004951 if (dmar_init_reserved_ranges()) {
4952 if (force_on)
4953 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004954 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004955 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004956
Lu Baolucf1ec452019-05-02 09:34:25 +08004957 if (dmar_map_gfx)
4958 intel_iommu_gfx_mapped = 1;
4959
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004960 init_no_remapping_devices();
4961
Joseph Cihulab7792602011-05-03 00:08:37 -07004962 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004963 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004964 if (force_on)
4965 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004966 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004967 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004968 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004969 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004970
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004971 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004972
Qian Cai2d48ea02020-03-05 15:00:46 -05004973 down_read(&dmar_global_lock);
Joerg Roedel39ab9552017-02-01 16:56:46 +01004974 for_each_active_iommu(iommu, drhd) {
4975 iommu_device_sysfs_add(&iommu->iommu, NULL,
4976 intel_iommu_groups,
4977 "%s", iommu->name);
4978 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4979 iommu_device_register(&iommu->iommu);
4980 }
Qian Cai2d48ea02020-03-05 15:00:46 -05004981 up_read(&dmar_global_lock);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004982
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004983 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Jiang Liu75f05562014-02-19 14:07:37 +08004984 if (si_domain && !hw_pass_through)
4985 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004986 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4987 intel_iommu_cpu_dead);
Lu Baolud8190dc2019-05-25 13:41:25 +08004988
Lu Baolud5692d42019-06-12 08:28:49 +08004989 down_read(&dmar_global_lock);
Lu Baolufa212a92019-05-25 13:41:31 +08004990 if (probe_acpi_namespace_devices())
4991 pr_warn("ACPI name space devices didn't probe correctly\n");
4992
Lu Baolud8190dc2019-05-25 13:41:25 +08004993 /* Finally, we enable the DMA remapping hardware. */
4994 for_each_iommu(iommu, drhd) {
Lu Baolu6a8c6742019-06-12 08:28:47 +08004995 if (!drhd->ignored && !translation_pre_enabled(iommu))
Lu Baolud8190dc2019-05-25 13:41:25 +08004996 iommu_enable_translation(iommu);
4997
4998 iommu_disable_protect_mem_regions(iommu);
4999 }
Qian Cai2d48ea02020-03-05 15:00:46 -05005000 up_read(&dmar_global_lock);
5001
Lu Baolud8190dc2019-05-25 13:41:25 +08005002 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
5003
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02005004 intel_iommu_enabled = 1;
5005
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005006 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08005007
5008out_free_reserved_range:
5009 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08005010out_free_dmar:
5011 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08005012 up_write(&dmar_global_lock);
5013 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08005014 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005015}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07005016
Lu Baolu0ce4a852019-08-26 16:50:56 +08005017static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
5018{
5019 struct intel_iommu *iommu = opaque;
5020
5021 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
5022 return 0;
5023}
5024
5025/*
5026 * NB - intel-iommu lacks any sort of reference counting for the users of
5027 * dependent devices. If multiple endpoints have intersecting dependent
5028 * devices, unbinding the driver from any one of them will possibly leave
5029 * the others unable to operate.
5030 */
5031static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
5032{
5033 if (!iommu || !dev || !dev_is_pci(dev))
5034 return;
5035
5036 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
5037}
5038
Joerg Roedel127c7612015-07-23 17:44:46 +02005039static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08005040{
Lu Baolu942067f2019-05-25 13:41:29 +08005041 struct dmar_domain *domain;
Weidong Hanc7151a82008-12-08 22:51:37 +08005042 struct intel_iommu *iommu;
5043 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08005044
Joerg Roedel55d94042015-07-22 16:50:40 +02005045 assert_spin_locked(&device_domain_lock);
5046
Joerg Roedelb608ac32015-07-21 18:19:08 +02005047 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08005048 return;
5049
Joerg Roedel127c7612015-07-23 17:44:46 +02005050 iommu = info->iommu;
Lu Baolu942067f2019-05-25 13:41:29 +08005051 domain = info->domain;
Joerg Roedel127c7612015-07-23 17:44:46 +02005052
5053 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08005054 if (dev_is_pci(info->dev) && sm_supported(iommu))
5055 intel_pasid_tear_down_entry(iommu, info->dev,
Lu Baolu37e91bd2020-05-16 14:20:57 +08005056 PASID_RID2PASID, false);
Lu Baoluef848b72018-12-10 09:59:01 +08005057
Joerg Roedel127c7612015-07-23 17:44:46 +02005058 iommu_disable_dev_iotlb(info);
Jon Derrick8038bdb2020-05-27 10:56:15 -06005059 if (!dev_is_real_dma_subdevice(info->dev))
5060 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08005061 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02005062 }
5063
Joerg Roedelb608ac32015-07-21 18:19:08 +02005064 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07005065
Joerg Roedeld160aca2015-07-22 11:52:53 +02005066 spin_lock_irqsave(&iommu->lock, flags);
Lu Baolu942067f2019-05-25 13:41:29 +08005067 domain_detach_iommu(domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02005068 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005069
5070 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08005071}
5072
Bjorn Helgaas71753232019-02-08 16:06:15 -06005073static void dmar_remove_one_dev_info(struct device *dev)
Joerg Roedel55d94042015-07-22 16:50:40 +02005074{
Joerg Roedel127c7612015-07-23 17:44:46 +02005075 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02005076 unsigned long flags;
5077
Weidong Hanc7151a82008-12-08 22:51:37 +08005078 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolue85bb992020-05-16 14:20:52 +08005079 info = get_domain_info(dev);
5080 if (info)
Lu Baoluae23bfb62019-08-06 08:14:08 +08005081 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005082 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005083}
5084
Joerg Roedel301e7ee2019-07-22 16:21:05 +02005085static int md_domain_init(struct dmar_domain *domain, int guest_width)
5086{
5087 int adjust_width;
5088
Joerg Roedel301e7ee2019-07-22 16:21:05 +02005089 /* calculate AGAW */
5090 domain->gaw = guest_width;
5091 adjust_width = guestwidth_to_adjustwidth(guest_width);
5092 domain->agaw = width_to_agaw(adjust_width);
5093
5094 domain->iommu_coherency = 0;
5095 domain->iommu_snooping = 0;
5096 domain->iommu_superpage = 0;
5097 domain->max_addr = 0;
5098
5099 /* always allocate the top pgd */
5100 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
5101 if (!domain->pgd)
5102 return -ENOMEM;
5103 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5104 return 0;
5105}
5106
Tom Murphye70b0812020-05-16 14:21:01 +08005107static void intel_init_iova_domain(struct dmar_domain *dmar_domain)
5108{
5109 init_iova_domain(&dmar_domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
5110 copy_reserved_iova(&reserved_iova_list, &dmar_domain->iovad);
5111
5112 if (!intel_iommu_strict &&
5113 init_iova_flush_queue(&dmar_domain->iovad,
5114 iommu_flush_iova, iova_entry_free))
5115 pr_info("iova flush queue initialization failed\n");
5116}
5117
Joerg Roedel00a77de2015-03-26 13:43:08 +01005118static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005119{
Joerg Roedel5d450802008-12-03 14:52:32 +01005120 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005121 struct iommu_domain *domain;
5122
Lu Baolu4de354e2019-05-25 13:41:27 +08005123 switch (type) {
Lu Baolufa954e62019-05-25 13:41:28 +08005124 case IOMMU_DOMAIN_DMA:
Lu Baolu4de354e2019-05-25 13:41:27 +08005125 case IOMMU_DOMAIN_UNMANAGED:
Lu Baolufa954e62019-05-25 13:41:28 +08005126 dmar_domain = alloc_domain(0);
Lu Baolu4de354e2019-05-25 13:41:27 +08005127 if (!dmar_domain) {
5128 pr_err("Can't allocate dmar_domain\n");
5129 return NULL;
5130 }
Joerg Roedel301e7ee2019-07-22 16:21:05 +02005131 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Lu Baolu4de354e2019-05-25 13:41:27 +08005132 pr_err("Domain initialization failed\n");
5133 domain_exit(dmar_domain);
5134 return NULL;
5135 }
Lu Baolufa954e62019-05-25 13:41:28 +08005136
Tom Murphye70b0812020-05-16 14:21:01 +08005137 if (type == IOMMU_DOMAIN_DMA)
5138 intel_init_iova_domain(dmar_domain);
Lu Baolufa954e62019-05-25 13:41:28 +08005139
Lu Baolu4de354e2019-05-25 13:41:27 +08005140 domain = &dmar_domain->domain;
5141 domain->geometry.aperture_start = 0;
5142 domain->geometry.aperture_end =
5143 __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5144 domain->geometry.force_aperture = true;
5145
5146 return domain;
5147 case IOMMU_DOMAIN_IDENTITY:
5148 return &si_domain->domain;
5149 default:
Joerg Roedel00a77de2015-03-26 13:43:08 +01005150 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005151 }
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005152
Lu Baolu4de354e2019-05-25 13:41:27 +08005153 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005154}
Kay, Allen M38717942008-09-09 18:37:29 +03005155
Joerg Roedel00a77de2015-03-26 13:43:08 +01005156static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005157{
Lu Baolu4de354e2019-05-25 13:41:27 +08005158 if (domain != &si_domain->domain)
5159 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005160}
Kay, Allen M38717942008-09-09 18:37:29 +03005161
Lu Baolu67b8e022019-03-25 09:30:32 +08005162/*
5163 * Check whether a @domain could be attached to the @dev through the
5164 * aux-domain attach/detach APIs.
5165 */
5166static inline bool
5167is_aux_domain(struct device *dev, struct iommu_domain *domain)
5168{
Lu Baolue85bb992020-05-16 14:20:52 +08005169 struct device_domain_info *info = get_domain_info(dev);
Lu Baolu67b8e022019-03-25 09:30:32 +08005170
5171 return info && info->auxd_enabled &&
5172 domain->type == IOMMU_DOMAIN_UNMANAGED;
5173}
5174
5175static void auxiliary_link_device(struct dmar_domain *domain,
5176 struct device *dev)
5177{
Lu Baolue85bb992020-05-16 14:20:52 +08005178 struct device_domain_info *info = get_domain_info(dev);
Lu Baolu67b8e022019-03-25 09:30:32 +08005179
5180 assert_spin_locked(&device_domain_lock);
5181 if (WARN_ON(!info))
5182 return;
5183
5184 domain->auxd_refcnt++;
5185 list_add(&domain->auxd, &info->auxiliary_domains);
5186}
5187
5188static void auxiliary_unlink_device(struct dmar_domain *domain,
5189 struct device *dev)
5190{
Lu Baolue85bb992020-05-16 14:20:52 +08005191 struct device_domain_info *info = get_domain_info(dev);
Lu Baolu67b8e022019-03-25 09:30:32 +08005192
5193 assert_spin_locked(&device_domain_lock);
5194 if (WARN_ON(!info))
5195 return;
5196
5197 list_del(&domain->auxd);
5198 domain->auxd_refcnt--;
5199
5200 if (!domain->auxd_refcnt && domain->default_pasid > 0)
Jacob Pan59a62332020-01-02 08:18:08 +08005201 ioasid_free(domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005202}
5203
5204static int aux_domain_add_dev(struct dmar_domain *domain,
5205 struct device *dev)
5206{
5207 int ret;
Lu Baolu67b8e022019-03-25 09:30:32 +08005208 unsigned long flags;
5209 struct intel_iommu *iommu;
5210
Lu Baoludd6692f2020-07-24 09:49:21 +08005211 iommu = device_to_iommu(dev, NULL, NULL);
Lu Baolu67b8e022019-03-25 09:30:32 +08005212 if (!iommu)
5213 return -ENODEV;
5214
5215 if (domain->default_pasid <= 0) {
Fenghua Yuc7b6bac2020-09-15 09:30:05 -07005216 u32 pasid;
Lu Baolu67b8e022019-03-25 09:30:32 +08005217
Jacob Pan59a62332020-01-02 08:18:08 +08005218 /* No private data needed for the default pasid */
5219 pasid = ioasid_alloc(NULL, PASID_MIN,
5220 pci_max_pasids(to_pci_dev(dev)) - 1,
5221 NULL);
5222 if (pasid == INVALID_IOASID) {
Lu Baolu67b8e022019-03-25 09:30:32 +08005223 pr_err("Can't allocate default pasid\n");
5224 return -ENODEV;
5225 }
5226 domain->default_pasid = pasid;
5227 }
5228
5229 spin_lock_irqsave(&device_domain_lock, flags);
5230 /*
5231 * iommu->lock must be held to attach domain to iommu and setup the
5232 * pasid entry for second level translation.
5233 */
5234 spin_lock(&iommu->lock);
5235 ret = domain_attach_iommu(domain, iommu);
5236 if (ret)
5237 goto attach_failed;
5238
5239 /* Setup the PASID entry for mediated devices: */
Lu Baoluddf09b62020-01-02 08:18:17 +08005240 if (domain_use_first_level(domain))
5241 ret = domain_setup_first_level(iommu, domain, dev,
5242 domain->default_pasid);
5243 else
5244 ret = intel_pasid_setup_second_level(iommu, domain, dev,
5245 domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005246 if (ret)
5247 goto table_failed;
5248 spin_unlock(&iommu->lock);
5249
5250 auxiliary_link_device(domain, dev);
5251
5252 spin_unlock_irqrestore(&device_domain_lock, flags);
5253
5254 return 0;
5255
5256table_failed:
5257 domain_detach_iommu(domain, iommu);
5258attach_failed:
5259 spin_unlock(&iommu->lock);
5260 spin_unlock_irqrestore(&device_domain_lock, flags);
5261 if (!domain->auxd_refcnt && domain->default_pasid > 0)
Jacob Pan59a62332020-01-02 08:18:08 +08005262 ioasid_free(domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005263
5264 return ret;
5265}
5266
5267static void aux_domain_remove_dev(struct dmar_domain *domain,
5268 struct device *dev)
5269{
5270 struct device_domain_info *info;
5271 struct intel_iommu *iommu;
5272 unsigned long flags;
5273
5274 if (!is_aux_domain(dev, &domain->domain))
5275 return;
5276
5277 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolue85bb992020-05-16 14:20:52 +08005278 info = get_domain_info(dev);
Lu Baolu67b8e022019-03-25 09:30:32 +08005279 iommu = info->iommu;
5280
5281 auxiliary_unlink_device(domain, dev);
5282
5283 spin_lock(&iommu->lock);
Lu Baolu37e91bd2020-05-16 14:20:57 +08005284 intel_pasid_tear_down_entry(iommu, dev, domain->default_pasid, false);
Lu Baolu67b8e022019-03-25 09:30:32 +08005285 domain_detach_iommu(domain, iommu);
5286 spin_unlock(&iommu->lock);
5287
5288 spin_unlock_irqrestore(&device_domain_lock, flags);
5289}
5290
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005291static int prepare_domain_attach_device(struct iommu_domain *domain,
5292 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005293{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005294 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005295 struct intel_iommu *iommu;
5296 int addr_width;
Kay, Allen M38717942008-09-09 18:37:29 +03005297
Lu Baoludd6692f2020-07-24 09:49:21 +08005298 iommu = device_to_iommu(dev, NULL, NULL);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005299 if (!iommu)
5300 return -ENODEV;
5301
5302 /* check if this iommu agaw is sufficient for max mapped address */
5303 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005304 if (addr_width > cap_mgaw(iommu->cap))
5305 addr_width = cap_mgaw(iommu->cap);
5306
5307 if (dmar_domain->max_addr > (1LL << addr_width)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005308 dev_err(dev, "%s: iommu width (%d) is not "
5309 "sufficient for the mapped address (%llx)\n",
5310 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005311 return -EFAULT;
5312 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005313 dmar_domain->gaw = addr_width;
5314
5315 /*
5316 * Knock out extra levels of page tables if necessary
5317 */
5318 while (iommu->agaw < dmar_domain->agaw) {
5319 struct dma_pte *pte;
5320
5321 pte = dmar_domain->pgd;
5322 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005323 dmar_domain->pgd = (struct dma_pte *)
5324 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005325 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005326 }
5327 dmar_domain->agaw--;
5328 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005329
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005330 return 0;
5331}
5332
5333static int intel_iommu_attach_device(struct iommu_domain *domain,
5334 struct device *dev)
5335{
5336 int ret;
5337
Lu Baolu56795822019-06-12 08:28:48 +08005338 if (domain->type == IOMMU_DOMAIN_UNMANAGED &&
5339 device_is_rmrr_locked(dev)) {
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005340 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5341 return -EPERM;
5342 }
5343
Lu Baolu67b8e022019-03-25 09:30:32 +08005344 if (is_aux_domain(dev, domain))
5345 return -EPERM;
5346
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005347 /* normally dev is not mapped */
5348 if (unlikely(domain_context_mapped(dev))) {
5349 struct dmar_domain *old_domain;
5350
5351 old_domain = find_domain(dev);
Lu Baolufa954e62019-05-25 13:41:28 +08005352 if (old_domain)
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005353 dmar_remove_one_dev_info(dev);
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005354 }
5355
5356 ret = prepare_domain_attach_device(domain, dev);
5357 if (ret)
5358 return ret;
5359
5360 return domain_add_dev_info(to_dmar_domain(domain), dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005361}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005362
Lu Baolu67b8e022019-03-25 09:30:32 +08005363static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
5364 struct device *dev)
5365{
5366 int ret;
5367
5368 if (!is_aux_domain(dev, domain))
5369 return -EPERM;
5370
5371 ret = prepare_domain_attach_device(domain, dev);
5372 if (ret)
5373 return ret;
5374
5375 return aux_domain_add_dev(to_dmar_domain(domain), dev);
5376}
5377
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005378static void intel_iommu_detach_device(struct iommu_domain *domain,
5379 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005380{
Bjorn Helgaas71753232019-02-08 16:06:15 -06005381 dmar_remove_one_dev_info(dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005382}
Kay, Allen M38717942008-09-09 18:37:29 +03005383
Lu Baolu67b8e022019-03-25 09:30:32 +08005384static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
5385 struct device *dev)
5386{
5387 aux_domain_remove_dev(to_dmar_domain(domain), dev);
5388}
5389
Jacob Pan6ee1b772020-05-16 14:20:49 +08005390/*
5391 * 2D array for converting and sanitizing IOMMU generic TLB granularity to
5392 * VT-d granularity. Invalidation is typically included in the unmap operation
5393 * as a result of DMA or VFIO unmap. However, for assigned devices guest
5394 * owns the first level page tables. Invalidations of translation caches in the
5395 * guest are trapped and passed down to the host.
5396 *
5397 * vIOMMU in the guest will only expose first level page tables, therefore
5398 * we do not support IOTLB granularity for request without PASID (second level).
5399 *
5400 * For example, to find the VT-d granularity encoding for IOTLB
5401 * type and page selective granularity within PASID:
5402 * X: indexed by iommu cache type
5403 * Y: indexed by enum iommu_inv_granularity
5404 * [IOMMU_CACHE_INV_TYPE_IOTLB][IOMMU_INV_GRANU_ADDR]
5405 */
5406
Qian Cai7809c4d2020-05-21 17:50:30 -04005407static const int
Jacob Pan6ee1b772020-05-16 14:20:49 +08005408inv_type_granu_table[IOMMU_CACHE_INV_TYPE_NR][IOMMU_INV_GRANU_NR] = {
5409 /*
5410 * PASID based IOTLB invalidation: PASID selective (per PASID),
5411 * page selective (address granularity)
5412 */
5413 {-EINVAL, QI_GRAN_NONG_PASID, QI_GRAN_PSI_PASID},
5414 /* PASID based dev TLBs */
5415 {-EINVAL, -EINVAL, QI_DEV_IOTLB_GRAN_PASID_SEL},
5416 /* PASID cache */
5417 {-EINVAL, -EINVAL, -EINVAL}
5418};
5419
5420static inline int to_vtd_granularity(int type, int granu)
5421{
5422 return inv_type_granu_table[type][granu];
5423}
5424
5425static inline u64 to_vtd_size(u64 granu_size, u64 nr_granules)
5426{
5427 u64 nr_pages = (granu_size * nr_granules) >> VTD_PAGE_SHIFT;
5428
5429 /* VT-d size is encoded as 2^size of 4K pages, 0 for 4k, 9 for 2MB, etc.
5430 * IOMMU cache invalidate API passes granu_size in bytes, and number of
5431 * granu size in contiguous memory.
5432 */
5433 return order_base_2(nr_pages);
5434}
5435
5436#ifdef CONFIG_INTEL_IOMMU_SVM
5437static int
5438intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
5439 struct iommu_cache_invalidate_info *inv_info)
5440{
5441 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5442 struct device_domain_info *info;
5443 struct intel_iommu *iommu;
5444 unsigned long flags;
5445 int cache_type;
5446 u8 bus, devfn;
5447 u16 did, sid;
5448 int ret = 0;
5449 u64 size = 0;
5450
Jacob Pan6278eec2020-09-25 09:32:47 -07005451 if (!inv_info || !dmar_domain)
Jacob Pan6ee1b772020-05-16 14:20:49 +08005452 return -EINVAL;
5453
5454 if (!dev || !dev_is_pci(dev))
5455 return -ENODEV;
5456
5457 iommu = device_to_iommu(dev, &bus, &devfn);
5458 if (!iommu)
5459 return -ENODEV;
5460
5461 if (!(dmar_domain->flags & DOMAIN_FLAG_NESTING_MODE))
5462 return -EINVAL;
5463
5464 spin_lock_irqsave(&device_domain_lock, flags);
5465 spin_lock(&iommu->lock);
Lu Baolue85bb992020-05-16 14:20:52 +08005466 info = get_domain_info(dev);
Jacob Pan6ee1b772020-05-16 14:20:49 +08005467 if (!info) {
5468 ret = -EINVAL;
5469 goto out_unlock;
5470 }
5471 did = dmar_domain->iommu_did[iommu->seq_id];
5472 sid = PCI_DEVID(bus, devfn);
5473
5474 /* Size is only valid in address selective invalidation */
Liu Yi L0fa1a152020-07-24 09:49:18 +08005475 if (inv_info->granularity == IOMMU_INV_GRANU_ADDR)
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005476 size = to_vtd_size(inv_info->granu.addr_info.granule_size,
5477 inv_info->granu.addr_info.nb_granules);
Jacob Pan6ee1b772020-05-16 14:20:49 +08005478
5479 for_each_set_bit(cache_type,
5480 (unsigned long *)&inv_info->cache,
5481 IOMMU_CACHE_INV_TYPE_NR) {
5482 int granu = 0;
5483 u64 pasid = 0;
Liu Yi L0fa1a152020-07-24 09:49:18 +08005484 u64 addr = 0;
Jacob Pan6ee1b772020-05-16 14:20:49 +08005485
5486 granu = to_vtd_granularity(cache_type, inv_info->granularity);
5487 if (granu == -EINVAL) {
5488 pr_err_ratelimited("Invalid cache type and granu combination %d/%d\n",
5489 cache_type, inv_info->granularity);
5490 break;
5491 }
5492
5493 /*
5494 * PASID is stored in different locations based on the
5495 * granularity.
5496 */
5497 if (inv_info->granularity == IOMMU_INV_GRANU_PASID &&
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005498 (inv_info->granu.pasid_info.flags & IOMMU_INV_PASID_FLAGS_PASID))
5499 pasid = inv_info->granu.pasid_info.pasid;
Jacob Pan6ee1b772020-05-16 14:20:49 +08005500 else if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005501 (inv_info->granu.addr_info.flags & IOMMU_INV_ADDR_FLAGS_PASID))
5502 pasid = inv_info->granu.addr_info.pasid;
Jacob Pan6ee1b772020-05-16 14:20:49 +08005503
5504 switch (BIT(cache_type)) {
5505 case IOMMU_CACHE_INV_TYPE_IOTLB:
Jacob Pan1ff00272020-07-24 09:49:19 +08005506 /* HW will ignore LSB bits based on address mask */
Jacob Pan6ee1b772020-05-16 14:20:49 +08005507 if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
5508 size &&
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005509 (inv_info->granu.addr_info.addr & ((BIT(VTD_PAGE_SHIFT + size)) - 1))) {
Jacob Pan1ff00272020-07-24 09:49:19 +08005510 pr_err_ratelimited("User address not aligned, 0x%llx, size order %llu\n",
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005511 inv_info->granu.addr_info.addr, size);
Jacob Pan6ee1b772020-05-16 14:20:49 +08005512 }
5513
5514 /*
5515 * If granu is PASID-selective, address is ignored.
5516 * We use npages = -1 to indicate that.
5517 */
5518 qi_flush_piotlb(iommu, did, pasid,
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005519 mm_to_dma_pfn(inv_info->granu.addr_info.addr),
Jacob Pan6ee1b772020-05-16 14:20:49 +08005520 (granu == QI_GRAN_NONG_PASID) ? -1 : 1 << size,
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005521 inv_info->granu.addr_info.flags & IOMMU_INV_ADDR_FLAGS_LEAF);
Jacob Pan6ee1b772020-05-16 14:20:49 +08005522
Liu Yi L0fa1a152020-07-24 09:49:18 +08005523 if (!info->ats_enabled)
5524 break;
Jacob Pan6ee1b772020-05-16 14:20:49 +08005525 /*
5526 * Always flush device IOTLB if ATS is enabled. vIOMMU
5527 * in the guest may assume IOTLB flush is inclusive,
5528 * which is more efficient.
5529 */
Liu Yi L0fa1a152020-07-24 09:49:18 +08005530 fallthrough;
Jacob Pan6ee1b772020-05-16 14:20:49 +08005531 case IOMMU_CACHE_INV_TYPE_DEV_IOTLB:
Liu Yi L0fa1a152020-07-24 09:49:18 +08005532 /*
5533 * PASID based device TLB invalidation does not support
5534 * IOMMU_INV_GRANU_PASID granularity but only supports
5535 * IOMMU_INV_GRANU_ADDR.
5536 * The equivalent of that is we set the size to be the
5537 * entire range of 64 bit. User only provides PASID info
5538 * without address info. So we set addr to 0.
5539 */
5540 if (inv_info->granularity == IOMMU_INV_GRANU_PASID) {
5541 size = 64 - VTD_PAGE_SHIFT;
5542 addr = 0;
5543 } else if (inv_info->granularity == IOMMU_INV_GRANU_ADDR) {
Jacob Pan8d3bb3b2020-09-25 09:32:44 -07005544 addr = inv_info->granu.addr_info.addr;
Liu Yi L0fa1a152020-07-24 09:49:18 +08005545 }
5546
Jacob Pan6ee1b772020-05-16 14:20:49 +08005547 if (info->ats_enabled)
5548 qi_flush_dev_iotlb_pasid(iommu, sid,
5549 info->pfsid, pasid,
Liu Yi L0fa1a152020-07-24 09:49:18 +08005550 info->ats_qdep, addr,
Jacob Pan78df6c82020-07-24 09:49:15 +08005551 size);
Jacob Pan6ee1b772020-05-16 14:20:49 +08005552 else
5553 pr_warn_ratelimited("Passdown device IOTLB flush w/o ATS!\n");
5554 break;
5555 default:
5556 dev_err_ratelimited(dev, "Unsupported IOMMU invalidation type %d\n",
5557 cache_type);
5558 ret = -EINVAL;
5559 }
5560 }
5561out_unlock:
5562 spin_unlock(&iommu->lock);
5563 spin_unlock_irqrestore(&device_domain_lock, flags);
5564
5565 return ret;
5566}
5567#endif
5568
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005569static int intel_iommu_map(struct iommu_domain *domain,
5570 unsigned long iova, phys_addr_t hpa,
Tom Murphy781ca2d2019-09-08 09:56:38 -07005571 size_t size, int iommu_prot, gfp_t gfp)
Kay, Allen M38717942008-09-09 18:37:29 +03005572{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005573 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005574 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005575 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005576 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005577
Joerg Roedeldde57a22008-12-03 15:04:09 +01005578 if (iommu_prot & IOMMU_READ)
5579 prot |= DMA_PTE_READ;
5580 if (iommu_prot & IOMMU_WRITE)
5581 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005582 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5583 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005584
David Woodhouse163cc522009-06-28 00:51:17 +01005585 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005586 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005587 u64 end;
5588
5589 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005590 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005591 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005592 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005593 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005594 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005595 return -EFAULT;
5596 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005597 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005598 }
David Woodhousead051222009-06-28 14:22:28 +01005599 /* Round up size to next multiple of PAGE_SIZE, if it and
5600 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005601 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005602 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5603 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005604 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005605}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005606
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005607static size_t intel_iommu_unmap(struct iommu_domain *domain,
Will Deacon56f8af52019-07-02 16:44:06 +01005608 unsigned long iova, size_t size,
5609 struct iommu_iotlb_gather *gather)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005610{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005611 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005612 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005613 unsigned long start_pfn, last_pfn;
5614 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005615 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005616
David Woodhouse5cf0a762014-03-19 16:07:49 +00005617 /* Cope with horrid API which requires us to unmap more than the
5618 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005619 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005620
5621 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5622 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5623
David Woodhouseea8ea462014-03-05 17:09:32 +00005624 start_pfn = iova >> VTD_PAGE_SHIFT;
5625 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5626
5627 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5628
5629 npages = last_pfn - start_pfn + 1;
5630
Shaokun Zhangf746a022018-03-22 18:18:06 +08005631 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005632 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5633 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005634
5635 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005636
David Woodhouse163cc522009-06-28 00:51:17 +01005637 if (dmar_domain->max_addr == iova + size)
5638 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005639
David Woodhouse5cf0a762014-03-19 16:07:49 +00005640 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005641}
Kay, Allen M38717942008-09-09 18:37:29 +03005642
Joerg Roedeld14d6572008-12-03 15:06:57 +01005643static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305644 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005645{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005646 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005647 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005648 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005649 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005650
David Woodhouse5cf0a762014-03-19 16:07:49 +00005651 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Yonghyun Hwang77a1bce2020-02-26 12:30:06 -08005652 if (pte && dma_pte_present(pte))
5653 phys = dma_pte_addr(pte) +
5654 (iova & (BIT_MASK(level_to_offset_bits(level) +
5655 VTD_PAGE_SHIFT) - 1));
Kay, Allen M38717942008-09-09 18:37:29 +03005656
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005657 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005658}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005659
Lu Baolu95587a72019-03-25 09:30:30 +08005660static inline bool scalable_mode_support(void)
5661{
5662 struct dmar_drhd_unit *drhd;
5663 struct intel_iommu *iommu;
5664 bool ret = true;
5665
5666 rcu_read_lock();
5667 for_each_active_iommu(iommu, drhd) {
5668 if (!sm_supported(iommu)) {
5669 ret = false;
5670 break;
5671 }
5672 }
5673 rcu_read_unlock();
5674
5675 return ret;
5676}
5677
5678static inline bool iommu_pasid_support(void)
5679{
5680 struct dmar_drhd_unit *drhd;
5681 struct intel_iommu *iommu;
5682 bool ret = true;
5683
5684 rcu_read_lock();
5685 for_each_active_iommu(iommu, drhd) {
5686 if (!pasid_supported(iommu)) {
5687 ret = false;
5688 break;
5689 }
5690 }
5691 rcu_read_unlock();
5692
5693 return ret;
5694}
5695
Lu Baolu2cd13112020-01-02 08:18:15 +08005696static inline bool nested_mode_support(void)
5697{
5698 struct dmar_drhd_unit *drhd;
5699 struct intel_iommu *iommu;
5700 bool ret = true;
5701
5702 rcu_read_lock();
5703 for_each_active_iommu(iommu, drhd) {
5704 if (!sm_supported(iommu) || !ecap_nest(iommu->ecap)) {
5705 ret = false;
5706 break;
5707 }
5708 }
5709 rcu_read_unlock();
5710
5711 return ret;
5712}
5713
Joerg Roedel5d587b82014-09-05 10:50:45 +02005714static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005715{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005716 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005717 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005718 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005719 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005720
Joerg Roedel5d587b82014-09-05 10:50:45 +02005721 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005722}
5723
Joerg Roedele5d18412020-04-29 15:36:54 +02005724static struct iommu_device *intel_iommu_probe_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005725{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005726 struct intel_iommu *iommu;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005727
Lu Baoludd6692f2020-07-24 09:49:21 +08005728 iommu = device_to_iommu(dev, NULL, NULL);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005729 if (!iommu)
Joerg Roedele5d18412020-04-29 15:36:54 +02005730 return ERR_PTR(-ENODEV);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005731
Lu Baolu8af46c72019-05-25 13:41:32 +08005732 if (translation_pre_enabled(iommu))
Joerg Roedel01b9d4e2020-06-25 15:08:25 +02005733 dev_iommu_priv_set(dev, DEFER_DEVICE_DOMAIN_INFO);
Lu Baolu8af46c72019-05-25 13:41:32 +08005734
Joerg Roedele5d18412020-04-29 15:36:54 +02005735 return &iommu->iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005736}
5737
Joerg Roedele5d18412020-04-29 15:36:54 +02005738static void intel_iommu_release_device(struct device *dev)
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005739{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005740 struct intel_iommu *iommu;
Alex Williamsona5459cf2014-06-12 16:12:31 -06005741
Lu Baoludd6692f2020-07-24 09:49:21 +08005742 iommu = device_to_iommu(dev, NULL, NULL);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005743 if (!iommu)
5744 return;
5745
Lu Baolu458b7c82019-08-01 11:14:58 +08005746 dmar_remove_one_dev_info(dev);
5747
Lu Baolu6fc70202020-05-06 09:59:47 +08005748 set_dma_ops(dev, NULL);
5749}
Alex Williamsona5459cf2014-06-12 16:12:31 -06005750
Lu Baolu6fc70202020-05-06 09:59:47 +08005751static void intel_iommu_probe_finalize(struct device *dev)
5752{
5753 struct iommu_domain *domain;
Lu Baolucfb94a32019-09-06 14:14:52 +08005754
Lu Baolu6fc70202020-05-06 09:59:47 +08005755 domain = iommu_get_domain_for_dev(dev);
Lu Baolucfb94a32019-09-06 14:14:52 +08005756 if (device_needs_bounce(dev))
Lu Baolu6fc70202020-05-06 09:59:47 +08005757 set_dma_ops(dev, &bounce_dma_ops);
5758 else if (domain && domain->type == IOMMU_DOMAIN_DMA)
5759 set_dma_ops(dev, &intel_dma_ops);
5760 else
Lu Baolucfb94a32019-09-06 14:14:52 +08005761 set_dma_ops(dev, NULL);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005762}
5763
Eric Auger0659b8d2017-01-19 20:57:53 +00005764static void intel_iommu_get_resv_regions(struct device *device,
5765 struct list_head *head)
5766{
Eric Auger5f64ce52019-06-03 08:53:31 +02005767 int prot = DMA_PTE_READ | DMA_PTE_WRITE;
Eric Auger0659b8d2017-01-19 20:57:53 +00005768 struct iommu_resv_region *reg;
5769 struct dmar_rmrr_unit *rmrr;
5770 struct device *i_dev;
5771 int i;
5772
Eric Auger5f64ce52019-06-03 08:53:31 +02005773 down_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005774 for_each_rmrr_units(rmrr) {
5775 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5776 i, i_dev) {
Eric Auger5f64ce52019-06-03 08:53:31 +02005777 struct iommu_resv_region *resv;
Eric Auger1c5c59f2019-06-03 08:53:36 +02005778 enum iommu_resv_type type;
Eric Auger5f64ce52019-06-03 08:53:31 +02005779 size_t length;
5780
Eric Auger3855ba22019-06-03 08:53:34 +02005781 if (i_dev != device &&
5782 !is_downstream_to_pci_bridge(device, i_dev))
Eric Auger0659b8d2017-01-19 20:57:53 +00005783 continue;
5784
Eric Auger5f64ce52019-06-03 08:53:31 +02005785 length = rmrr->end_address - rmrr->base_address + 1;
Eric Auger1c5c59f2019-06-03 08:53:36 +02005786
5787 type = device_rmrr_is_relaxable(device) ?
5788 IOMMU_RESV_DIRECT_RELAXABLE : IOMMU_RESV_DIRECT;
5789
Eric Auger5f64ce52019-06-03 08:53:31 +02005790 resv = iommu_alloc_resv_region(rmrr->base_address,
Eric Auger1c5c59f2019-06-03 08:53:36 +02005791 length, prot, type);
Eric Auger5f64ce52019-06-03 08:53:31 +02005792 if (!resv)
5793 break;
5794
5795 list_add_tail(&resv->list, head);
Eric Auger0659b8d2017-01-19 20:57:53 +00005796 }
5797 }
Eric Auger5f64ce52019-06-03 08:53:31 +02005798 up_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005799
Lu Baolud850c2e2019-05-25 13:41:24 +08005800#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
5801 if (dev_is_pci(device)) {
5802 struct pci_dev *pdev = to_pci_dev(device);
5803
5804 if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
Jerry Snitselaarcde93192019-12-12 22:36:42 -07005805 reg = iommu_alloc_resv_region(0, 1UL << 24, prot,
Alex Williamsond8018a02019-12-11 13:28:29 -07005806 IOMMU_RESV_DIRECT_RELAXABLE);
Lu Baolud850c2e2019-05-25 13:41:24 +08005807 if (reg)
5808 list_add_tail(&reg->list, head);
5809 }
5810 }
5811#endif /* CONFIG_INTEL_IOMMU_FLOPPY_WA */
5812
Eric Auger0659b8d2017-01-19 20:57:53 +00005813 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5814 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005815 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005816 if (!reg)
5817 return;
5818 list_add_tail(&reg->list, head);
5819}
5820
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005821int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005822{
5823 struct device_domain_info *info;
5824 struct context_entry *context;
5825 struct dmar_domain *domain;
5826 unsigned long flags;
5827 u64 ctx_lo;
5828 int ret;
5829
Lu Baolu4ec066c2019-05-25 13:41:33 +08005830 domain = find_domain(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005831 if (!domain)
5832 return -EINVAL;
5833
5834 spin_lock_irqsave(&device_domain_lock, flags);
5835 spin_lock(&iommu->lock);
5836
5837 ret = -EINVAL;
Lu Baolue85bb992020-05-16 14:20:52 +08005838 info = get_domain_info(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005839 if (!info || !info->pasid_supported)
5840 goto out;
5841
5842 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5843 if (WARN_ON(!context))
5844 goto out;
5845
5846 ctx_lo = context[0].lo;
5847
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005848 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005849 ctx_lo |= CONTEXT_PASIDE;
5850 context[0].lo = ctx_lo;
5851 wmb();
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005852 iommu->flush.flush_context(iommu,
5853 domain->iommu_did[iommu->seq_id],
5854 PCI_DEVID(info->bus, info->devfn),
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005855 DMA_CCMD_MASK_NOBIT,
5856 DMA_CCMD_DEVICE_INVL);
5857 }
5858
5859 /* Enable PASID support in the device, if it wasn't already */
5860 if (!info->pasid_enabled)
5861 iommu_enable_dev_iotlb(info);
5862
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005863 ret = 0;
5864
5865 out:
5866 spin_unlock(&iommu->lock);
5867 spin_unlock_irqrestore(&device_domain_lock, flags);
5868
5869 return ret;
5870}
5871
James Sewart73bcbdc2019-05-25 13:41:23 +08005872static void intel_iommu_apply_resv_region(struct device *dev,
5873 struct iommu_domain *domain,
5874 struct iommu_resv_region *region)
5875{
5876 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5877 unsigned long start, end;
5878
5879 start = IOVA_PFN(region->start);
5880 end = IOVA_PFN(region->start + region->length - 1);
5881
5882 WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
5883}
5884
Patrick Steinhardt4a350a02019-12-27 00:56:18 +01005885static struct iommu_group *intel_iommu_device_group(struct device *dev)
5886{
5887 if (dev_is_pci(dev))
5888 return pci_device_group(dev);
5889 return generic_device_group(dev);
5890}
5891
Lu Baolu95587a72019-03-25 09:30:30 +08005892static int intel_iommu_enable_auxd(struct device *dev)
5893{
5894 struct device_domain_info *info;
5895 struct intel_iommu *iommu;
5896 unsigned long flags;
Lu Baolu95587a72019-03-25 09:30:30 +08005897 int ret;
5898
Lu Baoludd6692f2020-07-24 09:49:21 +08005899 iommu = device_to_iommu(dev, NULL, NULL);
Lu Baolu95587a72019-03-25 09:30:30 +08005900 if (!iommu || dmar_disabled)
5901 return -EINVAL;
5902
5903 if (!sm_supported(iommu) || !pasid_supported(iommu))
5904 return -EINVAL;
5905
5906 ret = intel_iommu_enable_pasid(iommu, dev);
5907 if (ret)
5908 return -ENODEV;
5909
5910 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolue85bb992020-05-16 14:20:52 +08005911 info = get_domain_info(dev);
Lu Baolu95587a72019-03-25 09:30:30 +08005912 info->auxd_enabled = 1;
5913 spin_unlock_irqrestore(&device_domain_lock, flags);
5914
5915 return 0;
5916}
5917
5918static int intel_iommu_disable_auxd(struct device *dev)
5919{
5920 struct device_domain_info *info;
5921 unsigned long flags;
5922
5923 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolue85bb992020-05-16 14:20:52 +08005924 info = get_domain_info(dev);
Lu Baolu95587a72019-03-25 09:30:30 +08005925 if (!WARN_ON(!info))
5926 info->auxd_enabled = 0;
5927 spin_unlock_irqrestore(&device_domain_lock, flags);
5928
5929 return 0;
5930}
5931
5932/*
5933 * A PCI express designated vendor specific extended capability is defined
5934 * in the section 3.7 of Intel scalable I/O virtualization technical spec
5935 * for system software and tools to detect endpoint devices supporting the
5936 * Intel scalable IO virtualization without host driver dependency.
5937 *
5938 * Returns the address of the matching extended capability structure within
5939 * the device's PCI configuration space or 0 if the device does not support
5940 * it.
5941 */
5942static int siov_find_pci_dvsec(struct pci_dev *pdev)
5943{
5944 int pos;
5945 u16 vendor, id;
5946
5947 pos = pci_find_next_ext_capability(pdev, 0, 0x23);
5948 while (pos) {
5949 pci_read_config_word(pdev, pos + 4, &vendor);
5950 pci_read_config_word(pdev, pos + 8, &id);
5951 if (vendor == PCI_VENDOR_ID_INTEL && id == 5)
5952 return pos;
5953
5954 pos = pci_find_next_ext_capability(pdev, pos, 0x23);
5955 }
5956
5957 return 0;
5958}
5959
5960static bool
5961intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat)
5962{
5963 if (feat == IOMMU_DEV_FEAT_AUX) {
5964 int ret;
5965
5966 if (!dev_is_pci(dev) || dmar_disabled ||
5967 !scalable_mode_support() || !iommu_pasid_support())
5968 return false;
5969
5970 ret = pci_pasid_features(to_pci_dev(dev));
5971 if (ret < 0)
5972 return false;
5973
5974 return !!siov_find_pci_dvsec(to_pci_dev(dev));
5975 }
5976
Jacob Pan76fdd6c2020-05-16 14:20:53 +08005977 if (feat == IOMMU_DEV_FEAT_SVA) {
5978 struct device_domain_info *info = get_domain_info(dev);
5979
5980 return info && (info->iommu->flags & VTD_FLAG_SVM_CAPABLE) &&
5981 info->pasid_supported && info->pri_supported &&
5982 info->ats_supported;
5983 }
5984
Lu Baolu95587a72019-03-25 09:30:30 +08005985 return false;
5986}
5987
5988static int
5989intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
5990{
5991 if (feat == IOMMU_DEV_FEAT_AUX)
5992 return intel_iommu_enable_auxd(dev);
5993
Jacob Pan76fdd6c2020-05-16 14:20:53 +08005994 if (feat == IOMMU_DEV_FEAT_SVA) {
5995 struct device_domain_info *info = get_domain_info(dev);
5996
5997 if (!info)
5998 return -EINVAL;
5999
6000 if (info->iommu->flags & VTD_FLAG_SVM_CAPABLE)
6001 return 0;
6002 }
6003
Lu Baolu95587a72019-03-25 09:30:30 +08006004 return -ENODEV;
6005}
6006
6007static int
6008intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
6009{
6010 if (feat == IOMMU_DEV_FEAT_AUX)
6011 return intel_iommu_disable_auxd(dev);
6012
6013 return -ENODEV;
6014}
6015
6016static bool
6017intel_iommu_dev_feat_enabled(struct device *dev, enum iommu_dev_features feat)
6018{
Lu Baolue85bb992020-05-16 14:20:52 +08006019 struct device_domain_info *info = get_domain_info(dev);
Lu Baolu95587a72019-03-25 09:30:30 +08006020
6021 if (feat == IOMMU_DEV_FEAT_AUX)
6022 return scalable_mode_support() && info && info->auxd_enabled;
6023
6024 return false;
6025}
6026
Lu Baolu0e8000f2019-03-25 09:30:33 +08006027static int
6028intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
6029{
6030 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
6031
6032 return dmar_domain->default_pasid > 0 ?
6033 dmar_domain->default_pasid : -EINVAL;
6034}
6035
Lu Baolu8af46c72019-05-25 13:41:32 +08006036static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
6037 struct device *dev)
6038{
Joerg Roedel1d46159782020-02-17 17:12:37 +01006039 return attach_deferred(dev);
Lu Baolu8af46c72019-05-25 13:41:32 +08006040}
6041
Lu Baolu2cd13112020-01-02 08:18:15 +08006042static int
6043intel_iommu_domain_set_attr(struct iommu_domain *domain,
6044 enum iommu_attr attr, void *data)
6045{
6046 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
6047 unsigned long flags;
6048 int ret = 0;
6049
6050 if (domain->type != IOMMU_DOMAIN_UNMANAGED)
6051 return -EINVAL;
6052
6053 switch (attr) {
6054 case DOMAIN_ATTR_NESTING:
6055 spin_lock_irqsave(&device_domain_lock, flags);
6056 if (nested_mode_support() &&
6057 list_empty(&dmar_domain->devices)) {
6058 dmar_domain->flags |= DOMAIN_FLAG_NESTING_MODE;
6059 dmar_domain->flags &= ~DOMAIN_FLAG_USE_FIRST_LEVEL;
6060 } else {
6061 ret = -ENODEV;
6062 }
6063 spin_unlock_irqrestore(&device_domain_lock, flags);
6064 break;
6065 default:
6066 ret = -EINVAL;
6067 break;
6068 }
6069
6070 return ret;
6071}
6072
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006073/*
6074 * Check that the device does not live on an external facing PCI port that is
6075 * marked as untrusted. Such devices should not be able to apply quirks and
6076 * thus not be able to bypass the IOMMU restrictions.
6077 */
6078static bool risky_device(struct pci_dev *pdev)
6079{
6080 if (pdev->untrusted) {
6081 pci_info(pdev,
6082 "Skipping IOMMU quirk for dev [%04X:%04X] on untrusted PCI link\n",
6083 pdev->vendor, pdev->device);
6084 pci_info(pdev, "Please check with your BIOS/Platform vendor about this\n");
6085 return true;
6086 }
6087 return false;
6088}
6089
Joerg Roedelb0119e82017-02-01 13:23:08 +01006090const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00006091 .capable = intel_iommu_capable,
6092 .domain_alloc = intel_iommu_domain_alloc,
6093 .domain_free = intel_iommu_domain_free,
Lu Baolu2cd13112020-01-02 08:18:15 +08006094 .domain_set_attr = intel_iommu_domain_set_attr,
Eric Auger0659b8d2017-01-19 20:57:53 +00006095 .attach_dev = intel_iommu_attach_device,
6096 .detach_dev = intel_iommu_detach_device,
Lu Baolu67b8e022019-03-25 09:30:32 +08006097 .aux_attach_dev = intel_iommu_aux_attach_device,
6098 .aux_detach_dev = intel_iommu_aux_detach_device,
Lu Baolu0e8000f2019-03-25 09:30:33 +08006099 .aux_get_pasid = intel_iommu_aux_get_pasid,
Eric Auger0659b8d2017-01-19 20:57:53 +00006100 .map = intel_iommu_map,
6101 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00006102 .iova_to_phys = intel_iommu_iova_to_phys,
Joerg Roedele5d18412020-04-29 15:36:54 +02006103 .probe_device = intel_iommu_probe_device,
Lu Baolu6fc70202020-05-06 09:59:47 +08006104 .probe_finalize = intel_iommu_probe_finalize,
Joerg Roedele5d18412020-04-29 15:36:54 +02006105 .release_device = intel_iommu_release_device,
Eric Auger0659b8d2017-01-19 20:57:53 +00006106 .get_resv_regions = intel_iommu_get_resv_regions,
Thierry Reding0ecdebb2019-12-18 14:42:04 +01006107 .put_resv_regions = generic_iommu_put_resv_regions,
James Sewart73bcbdc2019-05-25 13:41:23 +08006108 .apply_resv_region = intel_iommu_apply_resv_region,
Patrick Steinhardt4a350a02019-12-27 00:56:18 +01006109 .device_group = intel_iommu_device_group,
Lu Baolu95587a72019-03-25 09:30:30 +08006110 .dev_has_feat = intel_iommu_dev_has_feat,
6111 .dev_feat_enabled = intel_iommu_dev_feat_enabled,
6112 .dev_enable_feat = intel_iommu_dev_enable_feat,
6113 .dev_disable_feat = intel_iommu_dev_disable_feat,
Lu Baolu8af46c72019-05-25 13:41:32 +08006114 .is_attach_deferred = intel_iommu_is_attach_deferred,
Joerg Roedel7039d112020-04-29 15:36:42 +02006115 .def_domain_type = device_def_domain_type,
Eric Auger0659b8d2017-01-19 20:57:53 +00006116 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Jacob Pan56722a42020-05-16 14:20:47 +08006117#ifdef CONFIG_INTEL_IOMMU_SVM
Jacob Pan6ee1b772020-05-16 14:20:49 +08006118 .cache_invalidate = intel_iommu_sva_invalidate,
Jacob Pan56722a42020-05-16 14:20:47 +08006119 .sva_bind_gpasid = intel_svm_bind_gpasid,
6120 .sva_unbind_gpasid = intel_svm_unbind_gpasid,
Jacob Pan064a57d2020-05-16 14:20:54 +08006121 .sva_bind = intel_svm_bind,
6122 .sva_unbind = intel_svm_unbind,
6123 .sva_get_pasid = intel_svm_get_pasid,
Lu Baolu8b737122020-07-24 09:49:24 +08006124 .page_response = intel_svm_page_response,
Jacob Pan56722a42020-05-16 14:20:47 +08006125#endif
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01006126};
David Woodhouse9af88142009-02-13 23:18:03 +00006127
Chris Wilson1f762492019-09-09 12:00:10 +01006128static void quirk_iommu_igfx(struct pci_dev *dev)
Daniel Vetter94526182013-01-20 23:50:13 +01006129{
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006130 if (risky_device(dev))
6131 return;
6132
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006133 pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01006134 dmar_map_gfx = 0;
6135}
6136
Chris Wilson1f762492019-09-09 12:00:10 +01006137/* G4x/GM45 integrated gfx dmar support is totally busted. */
6138DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
6139DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
6140DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_igfx);
6141DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_igfx);
6142DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_igfx);
6143DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_igfx);
6144DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_igfx);
6145
6146/* Broadwell igfx malfunctions with dmar */
6147DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1606, quirk_iommu_igfx);
6148DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160B, quirk_iommu_igfx);
6149DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160E, quirk_iommu_igfx);
6150DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1602, quirk_iommu_igfx);
6151DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160A, quirk_iommu_igfx);
6152DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160D, quirk_iommu_igfx);
6153DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1616, quirk_iommu_igfx);
6154DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161B, quirk_iommu_igfx);
6155DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161E, quirk_iommu_igfx);
6156DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1612, quirk_iommu_igfx);
6157DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161A, quirk_iommu_igfx);
6158DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161D, quirk_iommu_igfx);
6159DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1626, quirk_iommu_igfx);
6160DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162B, quirk_iommu_igfx);
6161DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162E, quirk_iommu_igfx);
6162DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1622, quirk_iommu_igfx);
6163DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162A, quirk_iommu_igfx);
6164DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162D, quirk_iommu_igfx);
6165DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1636, quirk_iommu_igfx);
6166DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163B, quirk_iommu_igfx);
6167DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163E, quirk_iommu_igfx);
6168DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
6169DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
6170DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
Daniel Vetter94526182013-01-20 23:50:13 +01006171
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08006172static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00006173{
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006174 if (risky_device(dev))
6175 return;
6176
David Woodhouse9af88142009-02-13 23:18:03 +00006177 /*
6178 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01006179 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00006180 */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006181 pci_info(dev, "Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00006182 rwbf_quirk = 1;
6183}
6184
6185DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01006186DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
6187DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
6188DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
6189DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
6190DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
6191DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07006192
Adam Jacksoneecfd572010-08-25 21:17:34 +01006193#define GGC 0x52
6194#define GGC_MEMORY_SIZE_MASK (0xf << 8)
6195#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
6196#define GGC_MEMORY_SIZE_1M (0x1 << 8)
6197#define GGC_MEMORY_SIZE_2M (0x3 << 8)
6198#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
6199#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
6200#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
6201#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
6202
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08006203static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01006204{
6205 unsigned short ggc;
6206
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006207 if (risky_device(dev))
6208 return;
6209
Adam Jacksoneecfd572010-08-25 21:17:34 +01006210 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01006211 return;
6212
Adam Jacksoneecfd572010-08-25 21:17:34 +01006213 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006214 pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01006215 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07006216 } else if (dmar_map_gfx) {
6217 /* we have to ensure the gfx device is idle before we flush */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006218 pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07006219 intel_iommu_strict = 1;
6220 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01006221}
6222DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
6223DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
6224DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
6225DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
6226
Lu Baolub1012ca2020-07-23 09:34:37 +08006227static void quirk_igfx_skip_te_disable(struct pci_dev *dev)
6228{
6229 unsigned short ver;
6230
6231 if (!IS_GFX_DEVICE(dev))
6232 return;
6233
6234 ver = (dev->device >> 8) & 0xff;
6235 if (ver != 0x45 && ver != 0x46 && ver != 0x4c &&
6236 ver != 0x4e && ver != 0x8a && ver != 0x98 &&
6237 ver != 0x9a)
6238 return;
6239
6240 if (risky_device(dev))
6241 return;
6242
6243 pci_info(dev, "Skip IOMMU disabling for graphics\n");
6244 iommu_skip_te_disable = 1;
6245}
6246DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_igfx_skip_te_disable);
6247
David Woodhousee0fc7e02009-09-30 09:12:17 -07006248/* On Tylersburg chipsets, some BIOSes have been known to enable the
6249 ISOCH DMAR unit for the Azalia sound device, but not give it any
6250 TLB entries, which causes it to deadlock. Check for that. We do
6251 this in a function called from init_dmars(), instead of in a PCI
6252 quirk, because we don't want to print the obnoxious "BIOS broken"
6253 message if VT-d is actually disabled.
6254*/
6255static void __init check_tylersburg_isoch(void)
6256{
6257 struct pci_dev *pdev;
6258 uint32_t vtisochctrl;
6259
6260 /* If there's no Azalia in the system anyway, forget it. */
6261 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
6262 if (!pdev)
6263 return;
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006264
6265 if (risky_device(pdev)) {
6266 pci_dev_put(pdev);
6267 return;
6268 }
6269
David Woodhousee0fc7e02009-09-30 09:12:17 -07006270 pci_dev_put(pdev);
6271
6272 /* System Management Registers. Might be hidden, in which case
6273 we can't do the sanity check. But that's OK, because the
6274 known-broken BIOSes _don't_ actually hide it, so far. */
6275 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
6276 if (!pdev)
6277 return;
6278
Rajat Jain67e8a5b2020-06-23 07:13:42 +08006279 if (risky_device(pdev)) {
6280 pci_dev_put(pdev);
6281 return;
6282 }
6283
David Woodhousee0fc7e02009-09-30 09:12:17 -07006284 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
6285 pci_dev_put(pdev);
6286 return;
6287 }
6288
6289 pci_dev_put(pdev);
6290
6291 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
6292 if (vtisochctrl & 1)
6293 return;
6294
6295 /* Drop all bits other than the number of TLB entries */
6296 vtisochctrl &= 0x1c;
6297
6298 /* If we have the recommended number of TLB entries (16), fine. */
6299 if (vtisochctrl == 0x10)
6300 return;
6301
6302 /* Zero TLB entries? You get to ride the short bus to school. */
6303 if (!vtisochctrl) {
6304 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
6305 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
6306 dmi_get_system_info(DMI_BIOS_VENDOR),
6307 dmi_get_system_info(DMI_BIOS_VERSION),
6308 dmi_get_system_info(DMI_PRODUCT_VERSION));
6309 iommu_identity_mapping |= IDENTMAP_AZALIA;
6310 return;
6311 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02006312
6313 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07006314 vtisochctrl);
6315}