blob: 56297298d6eeef1de4c96d3db0ee3efba7629312 [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>
26#include <linux/dma-mapping.h>
27#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>
Akinobu Mita36746432014-06-04 16:06:51 -070040#include <linux/dma-contiguous.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>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070044#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070045#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090046#include <asm/iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070047
Joerg Roedel078e1ee2012-09-26 12:44:43 +020048#include "irq_remapping.h"
Lu Baolu56283172018-07-14 15:46:54 +080049#include "intel-pasid.h"
Joerg Roedel078e1ee2012-09-26 12:44:43 +020050
Fenghua Yu5b6985c2008-10-16 18:02:32 -070051#define ROOT_SIZE VTD_PAGE_SIZE
52#define CONTEXT_SIZE VTD_PAGE_SIZE
53
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070054#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000055#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070056#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070057#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070058
59#define IOAPIC_RANGE_START (0xfee00000)
60#define IOAPIC_RANGE_END (0xfeefffff)
61#define IOVA_START_ADDR (0x1000)
62
Sohil Mehta5e3b4a12017-12-20 11:59:24 -080063#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070064
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070065#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080066#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070067
David Woodhouse2ebe3152009-09-19 07:34:04 -070068#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
69#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
70
71/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
72 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
73#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
74 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
75#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070076
Robin Murphy1b722502015-01-12 17:51:15 +000077/* IO virtual address start page frame number */
78#define IOVA_START_PFN (1)
79
Mark McLoughlinf27be032008-11-20 15:49:43 +000080#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
mark gross5e0d2a62008-03-04 15:22:08 -080081
Andrew Mortondf08cdc2010-09-22 13:05:11 -070082/* page table handling */
83#define LEVEL_STRIDE (9)
84#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
85
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020086/*
87 * This bitmap is used to advertise the page sizes our hardware support
88 * to the IOMMU core, which will then use this information to split
89 * physically contiguous memory regions it is mapping into page sizes
90 * that we support.
91 *
92 * Traditionally the IOMMU core just handed us the mappings directly,
93 * after making sure the size is an order of a 4KiB page and that the
94 * mapping has natural alignment.
95 *
96 * To retain this behavior, we currently advertise that we support
97 * all page sizes that are an order of 4KiB.
98 *
99 * If at some point we'd like to utilize the IOMMU core's new behavior,
100 * we could change this to advertise the real page sizes we support.
101 */
102#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
103
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700104static inline int agaw_to_level(int agaw)
105{
106 return agaw + 2;
107}
108
109static inline int agaw_to_width(int agaw)
110{
Jiang Liu5c645b32014-01-06 14:18:12 +0800111 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700112}
113
114static inline int width_to_agaw(int width)
115{
Jiang Liu5c645b32014-01-06 14:18:12 +0800116 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700117}
118
119static inline unsigned int level_to_offset_bits(int level)
120{
121 return (level - 1) * LEVEL_STRIDE;
122}
123
124static inline int pfn_level_offset(unsigned long pfn, int level)
125{
126 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
127}
128
129static inline unsigned long level_mask(int level)
130{
131 return -1UL << level_to_offset_bits(level);
132}
133
134static inline unsigned long level_size(int level)
135{
136 return 1UL << level_to_offset_bits(level);
137}
138
139static inline unsigned long align_to_level(unsigned long pfn, int level)
140{
141 return (pfn + level_size(level) - 1) & level_mask(level);
142}
David Woodhousefd18de52009-05-10 23:57:41 +0100143
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100144static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
145{
Jiang Liu5c645b32014-01-06 14:18:12 +0800146 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100147}
148
David Woodhousedd4e8312009-06-27 16:21:20 +0100149/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
150 are never going to work. */
151static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
152{
153 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
154}
155
156static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
157{
158 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
159}
160static inline unsigned long page_to_dma_pfn(struct page *pg)
161{
162 return mm_to_dma_pfn(page_to_pfn(pg));
163}
164static inline unsigned long virt_to_dma_pfn(void *p)
165{
166 return page_to_dma_pfn(virt_to_page(p));
167}
168
Weidong Hand9630fe2008-12-08 11:06:32 +0800169/* global iommu list, set NULL for ignored DMAR units */
170static struct intel_iommu **g_iommus;
171
David Woodhousee0fc7e02009-09-30 09:12:17 -0700172static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000173static int rwbf_quirk;
174
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000175/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700176 * set to 1 to panic kernel if can't successfully enable VT-d
177 * (used when kernel is launched w/ TXT)
178 */
179static int force_on = 0;
Shaohua Libfd20f12017-04-26 09:18:35 -0700180int intel_iommu_tboot_noforce;
Lu Baolu89a60792018-10-23 15:45:01 +0800181static int no_platform_optin;
Joseph Cihulab7792602011-05-03 00:08:37 -0700182
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000183#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000184
Joerg Roedel091d42e2015-06-12 11:56:10 +0200185/*
186 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
187 * if marked present.
188 */
189static phys_addr_t root_entry_lctp(struct root_entry *re)
190{
191 if (!(re->lo & 1))
192 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000193
Joerg Roedel091d42e2015-06-12 11:56:10 +0200194 return re->lo & VTD_PAGE_MASK;
195}
196
197/*
198 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
199 * if marked present.
200 */
201static phys_addr_t root_entry_uctp(struct root_entry *re)
202{
203 if (!(re->hi & 1))
204 return 0;
205
206 return re->hi & VTD_PAGE_MASK;
207}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000208
Joerg Roedelcf484d02015-06-12 12:21:46 +0200209static inline void context_clear_pasid_enable(struct context_entry *context)
210{
211 context->lo &= ~(1ULL << 11);
212}
213
214static inline bool context_pasid_enabled(struct context_entry *context)
215{
216 return !!(context->lo & (1ULL << 11));
217}
218
219static inline void context_set_copied(struct context_entry *context)
220{
221 context->hi |= (1ull << 3);
222}
223
224static inline bool context_copied(struct context_entry *context)
225{
226 return !!(context->hi & (1ULL << 3));
227}
228
229static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000230{
231 return (context->lo & 1);
232}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200233
Sohil Mehta26b86092018-09-11 17:11:36 -0700234bool context_present(struct context_entry *context)
Joerg Roedelcf484d02015-06-12 12:21:46 +0200235{
236 return context_pasid_enabled(context) ?
237 __context_present(context) :
238 __context_present(context) && !context_copied(context);
239}
240
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000241static inline void context_set_present(struct context_entry *context)
242{
243 context->lo |= 1;
244}
245
246static inline void context_set_fault_enable(struct context_entry *context)
247{
248 context->lo &= (((u64)-1) << 2) | 1;
249}
250
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000251static inline void context_set_translation_type(struct context_entry *context,
252 unsigned long value)
253{
254 context->lo &= (((u64)-1) << 4) | 3;
255 context->lo |= (value & 3) << 2;
256}
257
258static inline void context_set_address_root(struct context_entry *context,
259 unsigned long value)
260{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800261 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000262 context->lo |= value & VTD_PAGE_MASK;
263}
264
265static inline void context_set_address_width(struct context_entry *context,
266 unsigned long value)
267{
268 context->hi |= value & 7;
269}
270
271static inline void context_set_domain_id(struct context_entry *context,
272 unsigned long value)
273{
274 context->hi |= (value & ((1 << 16) - 1)) << 8;
275}
276
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200277static inline int context_domain_id(struct context_entry *c)
278{
279 return((c->hi >> 8) & 0xffff);
280}
281
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000282static inline void context_clear_entry(struct context_entry *context)
283{
284 context->lo = 0;
285 context->hi = 0;
286}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000287
Mark McLoughlin622ba122008-11-20 15:49:46 +0000288/*
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700289 * This domain is a statically identity mapping domain.
290 * 1. This domain creats a static 1:1 mapping to all usable memory.
291 * 2. It maps to each iommu if successful.
292 * 3. Each iommu mapps to this domain if successful.
293 */
David Woodhouse19943b02009-08-04 16:19:20 +0100294static struct dmar_domain *si_domain;
295static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700296
Joerg Roedel28ccce02015-07-21 14:45:31 +0200297/*
298 * Domain represents a virtual machine, more than one devices
Weidong Han1ce28fe2008-12-08 16:35:39 +0800299 * across iommus may be owned in one domain, e.g. kvm guest.
300 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800301#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800302
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700303/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800304#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700305
Joerg Roedel29a27712015-07-21 17:17:12 +0200306#define for_each_domain_iommu(idx, domain) \
307 for (idx = 0; idx < g_num_of_iommus; idx++) \
308 if (domain->iommu_refcnt[idx])
309
Jiang Liub94e4112014-02-19 14:07:25 +0800310struct dmar_rmrr_unit {
311 struct list_head list; /* list of rmrr units */
312 struct acpi_dmar_header *hdr; /* ACPI header */
313 u64 base_address; /* reserved base address*/
314 u64 end_address; /* reserved end address */
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 */
Eric Auger0659b8d2017-01-19 20:57:53 +0000317 struct iommu_resv_region *resv; /* reserved region handle */
Jiang Liub94e4112014-02-19 14:07:25 +0800318};
319
320struct dmar_atsr_unit {
321 struct list_head list; /* list of ATSR units */
322 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000323 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800324 int devices_cnt; /* target device count */
325 u8 include_all:1; /* include all ports */
326};
327
328static LIST_HEAD(dmar_atsr_units);
329static LIST_HEAD(dmar_rmrr_units);
330
331#define for_each_rmrr_units(rmrr) \
332 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
333
mark gross5e0d2a62008-03-04 15:22:08 -0800334/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800335static int g_num_of_iommus;
336
Jiang Liu92d03cc2014-02-19 14:07:28 +0800337static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700338static void domain_remove_dev_info(struct dmar_domain *domain);
Bjorn Helgaas71753232019-02-08 16:06:15 -0600339static void dmar_remove_one_dev_info(struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200340static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Joerg Roedel2452d9d2015-07-23 16:20:14 +0200341static void domain_context_clear(struct intel_iommu *iommu,
342 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800343static int domain_detach_iommu(struct dmar_domain *domain,
344 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700345
Suresh Siddhad3f13812011-08-23 17:05:25 -0700346#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800347int dmar_disabled = 0;
348#else
349int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700350#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800351
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200352int intel_iommu_enabled = 0;
353EXPORT_SYMBOL_GPL(intel_iommu_enabled);
354
David Woodhouse2d9e6672010-06-15 10:57:57 +0100355static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700356static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800357static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100358static int intel_iommu_superpage = 1;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800359static int intel_iommu_sm;
David Woodhouseae853dd2015-09-09 11:58:59 +0100360static int iommu_identity_mapping;
David Woodhousec83b2f22015-06-12 10:15:49 +0100361
David Woodhouseae853dd2015-09-09 11:58:59 +0100362#define IDENTMAP_ALL 1
363#define IDENTMAP_GFX 2
364#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100365
Lu Baolu765b6a92018-12-10 09:58:55 +0800366#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))
367#define pasid_supported(iommu) (sm_supported(iommu) && \
368 ecap_pasid((iommu)->ecap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700369
David Woodhousec0771df2011-10-14 20:59:46 +0100370int intel_iommu_gfx_mapped;
371EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
372
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700373#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
374static DEFINE_SPINLOCK(device_domain_lock);
375static LIST_HEAD(device_domain_list);
376
Lu Baolu85319dc2018-07-14 15:46:58 +0800377/*
378 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800379 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800380 */
381int for_each_device_domain(int (*fn)(struct device_domain_info *info,
382 void *data), void *data)
383{
384 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800385 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800386 struct device_domain_info *info;
387
Lu Baolu0bbeb012018-12-10 09:58:56 +0800388 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800389 list_for_each_entry(info, &device_domain_list, global) {
390 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800391 if (ret) {
392 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800393 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800394 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800395 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800396 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800397
398 return 0;
399}
400
Joerg Roedelb0119e82017-02-01 13:23:08 +0100401const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100402
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200403static bool translation_pre_enabled(struct intel_iommu *iommu)
404{
405 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
406}
407
Joerg Roedel091d42e2015-06-12 11:56:10 +0200408static void clear_translation_pre_enabled(struct intel_iommu *iommu)
409{
410 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
411}
412
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200413static void init_translation_status(struct intel_iommu *iommu)
414{
415 u32 gsts;
416
417 gsts = readl(iommu->reg + DMAR_GSTS_REG);
418 if (gsts & DMA_GSTS_TES)
419 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
420}
421
Joerg Roedel00a77de2015-03-26 13:43:08 +0100422/* Convert generic 'struct iommu_domain to private struct dmar_domain */
423static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
424{
425 return container_of(dom, struct dmar_domain, domain);
426}
427
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700428static int __init intel_iommu_setup(char *str)
429{
430 if (!str)
431 return -EINVAL;
432 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800433 if (!strncmp(str, "on", 2)) {
434 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200435 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800436 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700437 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800438 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200439 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700440 } else if (!strncmp(str, "igfx_off", 8)) {
441 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200442 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700443 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200444 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700445 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800446 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200447 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800448 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100449 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200450 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100451 intel_iommu_superpage = 0;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800452 } else if (!strncmp(str, "sm_on", 5)) {
453 pr_info("Intel-IOMMU: scalable mode supported\n");
454 intel_iommu_sm = 1;
Shaohua Libfd20f12017-04-26 09:18:35 -0700455 } else if (!strncmp(str, "tboot_noforce", 13)) {
456 printk(KERN_INFO
457 "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
458 intel_iommu_tboot_noforce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700459 }
460
461 str += strcspn(str, ",");
462 while (*str == ',')
463 str++;
464 }
465 return 0;
466}
467__setup("intel_iommu=", intel_iommu_setup);
468
469static struct kmem_cache *iommu_domain_cache;
470static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700471
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200472static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
473{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200474 struct dmar_domain **domains;
475 int idx = did >> 8;
476
477 domains = iommu->domains[idx];
478 if (!domains)
479 return NULL;
480
481 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200482}
483
484static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
485 struct dmar_domain *domain)
486{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200487 struct dmar_domain **domains;
488 int idx = did >> 8;
489
490 if (!iommu->domains[idx]) {
491 size_t size = 256 * sizeof(struct dmar_domain *);
492 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
493 }
494
495 domains = iommu->domains[idx];
496 if (WARN_ON(!domains))
497 return;
498 else
499 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200500}
501
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800502void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700503{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700504 struct page *page;
505 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700506
Suresh Siddha4c923d42009-10-02 11:01:24 -0700507 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
508 if (page)
509 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700510 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700511}
512
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800513void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700514{
515 free_page((unsigned long)vaddr);
516}
517
518static inline void *alloc_domain_mem(void)
519{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900520 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700521}
522
Kay, Allen M38717942008-09-09 18:37:29 +0300523static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700524{
525 kmem_cache_free(iommu_domain_cache, vaddr);
526}
527
528static inline void * alloc_devinfo_mem(void)
529{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900530 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700531}
532
533static inline void free_devinfo_mem(void *vaddr)
534{
535 kmem_cache_free(iommu_devinfo_cache, vaddr);
536}
537
Jiang Liuab8dfe22014-07-11 14:19:27 +0800538static inline int domain_type_is_vm(struct dmar_domain *domain)
539{
540 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
541}
542
Joerg Roedel28ccce02015-07-21 14:45:31 +0200543static inline int domain_type_is_si(struct dmar_domain *domain)
544{
545 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
546}
547
Jiang Liuab8dfe22014-07-11 14:19:27 +0800548static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
549{
550 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
551 DOMAIN_FLAG_STATIC_IDENTITY);
552}
Weidong Han1b573682008-12-08 15:34:06 +0800553
Jiang Liu162d1b12014-07-11 14:19:35 +0800554static inline int domain_pfn_supported(struct dmar_domain *domain,
555 unsigned long pfn)
556{
557 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
558
559 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
560}
561
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700562static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800563{
564 unsigned long sagaw;
565 int agaw = -1;
566
567 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700568 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800569 agaw >= 0; agaw--) {
570 if (test_bit(agaw, &sagaw))
571 break;
572 }
573
574 return agaw;
575}
576
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700577/*
578 * Calculate max SAGAW for each iommu.
579 */
580int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
581{
582 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
583}
584
585/*
586 * calculate agaw for each iommu.
587 * "SAGAW" may be different across iommus, use a default agaw, and
588 * get a supported less agaw for iommus that don't support the default agaw.
589 */
590int iommu_calculate_agaw(struct intel_iommu *iommu)
591{
592 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
593}
594
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700595/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800596struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800597{
598 int iommu_id;
599
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700600 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800601 BUG_ON(domain_type_is_vm_or_si(domain));
Joerg Roedel29a27712015-07-21 17:17:12 +0200602 for_each_domain_iommu(iommu_id, domain)
603 break;
604
Weidong Han8c11e792008-12-08 15:29:22 +0800605 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
606 return NULL;
607
608 return g_iommus[iommu_id];
609}
610
Weidong Han8e6040972008-12-08 15:49:06 +0800611static void domain_update_iommu_coherency(struct dmar_domain *domain)
612{
David Woodhoused0501962014-03-11 17:10:29 -0700613 struct dmar_drhd_unit *drhd;
614 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100615 bool found = false;
616 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800617
David Woodhoused0501962014-03-11 17:10:29 -0700618 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800619
Joerg Roedel29a27712015-07-21 17:17:12 +0200620 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100621 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800622 if (!ecap_coherent(g_iommus[i]->ecap)) {
623 domain->iommu_coherency = 0;
624 break;
625 }
Weidong Han8e6040972008-12-08 15:49:06 +0800626 }
David Woodhoused0501962014-03-11 17:10:29 -0700627 if (found)
628 return;
629
630 /* No hardware attached; use lowest common denominator */
631 rcu_read_lock();
632 for_each_active_iommu(iommu, drhd) {
633 if (!ecap_coherent(iommu->ecap)) {
634 domain->iommu_coherency = 0;
635 break;
636 }
637 }
638 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800639}
640
Jiang Liu161f6932014-07-11 14:19:37 +0800641static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100642{
Allen Kay8140a952011-10-14 12:32:17 -0700643 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800644 struct intel_iommu *iommu;
645 int ret = 1;
646
647 rcu_read_lock();
648 for_each_active_iommu(iommu, drhd) {
649 if (iommu != skip) {
650 if (!ecap_sc_support(iommu->ecap)) {
651 ret = 0;
652 break;
653 }
654 }
655 }
656 rcu_read_unlock();
657
658 return ret;
659}
660
661static int domain_update_iommu_superpage(struct intel_iommu *skip)
662{
663 struct dmar_drhd_unit *drhd;
664 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700665 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100666
667 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800668 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100669 }
670
Allen Kay8140a952011-10-14 12:32:17 -0700671 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800672 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700673 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800674 if (iommu != skip) {
675 mask &= cap_super_page_val(iommu->cap);
676 if (!mask)
677 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100678 }
679 }
Jiang Liu0e242612014-02-19 14:07:34 +0800680 rcu_read_unlock();
681
Jiang Liu161f6932014-07-11 14:19:37 +0800682 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100683}
684
Sheng Yang58c610b2009-03-18 15:33:05 +0800685/* Some capabilities may be different across iommus */
686static void domain_update_iommu_cap(struct dmar_domain *domain)
687{
688 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800689 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
690 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800691}
692
Sohil Mehta26b86092018-09-11 17:11:36 -0700693struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
694 u8 devfn, int alloc)
David Woodhouse03ecc322015-02-13 14:35:21 +0000695{
696 struct root_entry *root = &iommu->root_entry[bus];
697 struct context_entry *context;
698 u64 *entry;
699
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200700 entry = &root->lo;
Lu Baolu765b6a92018-12-10 09:58:55 +0800701 if (sm_supported(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000702 if (devfn >= 0x80) {
703 devfn -= 0x80;
704 entry = &root->hi;
705 }
706 devfn *= 2;
707 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000708 if (*entry & 1)
709 context = phys_to_virt(*entry & VTD_PAGE_MASK);
710 else {
711 unsigned long phy_addr;
712 if (!alloc)
713 return NULL;
714
715 context = alloc_pgtable_page(iommu->node);
716 if (!context)
717 return NULL;
718
719 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
720 phy_addr = virt_to_phys((void *)context);
721 *entry = phy_addr | 1;
722 __iommu_flush_cache(iommu, entry, sizeof(*entry));
723 }
724 return &context[devfn];
725}
726
David Woodhouse4ed6a542015-05-11 14:59:20 +0100727static int iommu_dummy(struct device *dev)
728{
729 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
730}
731
David Woodhouse156baca2014-03-09 14:00:57 -0700732static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800733{
734 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800735 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700736 struct device *tmp;
737 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800738 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800739 int i;
740
David Woodhouse4ed6a542015-05-11 14:59:20 +0100741 if (iommu_dummy(dev))
742 return NULL;
743
David Woodhouse156baca2014-03-09 14:00:57 -0700744 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700745 struct pci_dev *pf_pdev;
746
David Woodhouse156baca2014-03-09 14:00:57 -0700747 pdev = to_pci_dev(dev);
Jon Derrick5823e332017-08-30 15:05:59 -0600748
749#ifdef CONFIG_X86
750 /* VMD child devices currently cannot be handled individually */
751 if (is_vmd(pdev->bus))
752 return NULL;
753#endif
754
Ashok Raj1c387182016-10-21 15:32:05 -0700755 /* VFs aren't listed in scope tables; we need to look up
756 * the PF instead to find the IOMMU. */
757 pf_pdev = pci_physfn(pdev);
758 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700759 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100760 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700761 dev = &ACPI_COMPANION(dev)->dev;
762
Jiang Liu0e242612014-02-19 14:07:34 +0800763 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800764 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700765 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100766 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800767
Jiang Liub683b232014-02-19 14:07:32 +0800768 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700769 drhd->devices_cnt, i, tmp) {
770 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700771 /* For a VF use its original BDF# not that of the PF
772 * which we used for the IOMMU lookup. Strictly speaking
773 * we could do this for all PCI devices; we only need to
774 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100775 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700776 goto got_pdev;
777
David Woodhouse156baca2014-03-09 14:00:57 -0700778 *bus = drhd->devices[i].bus;
779 *devfn = drhd->devices[i].devfn;
780 goto out;
781 }
782
783 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000784 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700785
786 ptmp = to_pci_dev(tmp);
787 if (ptmp->subordinate &&
788 ptmp->subordinate->number <= pdev->bus->number &&
789 ptmp->subordinate->busn_res.end >= pdev->bus->number)
790 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100791 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800792
David Woodhouse156baca2014-03-09 14:00:57 -0700793 if (pdev && drhd->include_all) {
794 got_pdev:
795 *bus = pdev->bus->number;
796 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800797 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700798 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800799 }
Jiang Liub683b232014-02-19 14:07:32 +0800800 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700801 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800802 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800803
Jiang Liub683b232014-02-19 14:07:32 +0800804 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800805}
806
Weidong Han5331fe62008-12-08 23:00:00 +0800807static void domain_flush_cache(struct dmar_domain *domain,
808 void *addr, int size)
809{
810 if (!domain->iommu_coherency)
811 clflush_cache_range(addr, size);
812}
813
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700814static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
815{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700816 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000817 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700818 unsigned long flags;
819
820 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000821 context = iommu_context_addr(iommu, bus, devfn, 0);
822 if (context)
823 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700824 spin_unlock_irqrestore(&iommu->lock, flags);
825 return ret;
826}
827
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700828static void free_context_table(struct intel_iommu *iommu)
829{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700830 int i;
831 unsigned long flags;
832 struct context_entry *context;
833
834 spin_lock_irqsave(&iommu->lock, flags);
835 if (!iommu->root_entry) {
836 goto out;
837 }
838 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000839 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700840 if (context)
841 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000842
Lu Baolu765b6a92018-12-10 09:58:55 +0800843 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000844 continue;
845
846 context = iommu_context_addr(iommu, i, 0x80, 0);
847 if (context)
848 free_pgtable_page(context);
849
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700850 }
851 free_pgtable_page(iommu->root_entry);
852 iommu->root_entry = NULL;
853out:
854 spin_unlock_irqrestore(&iommu->lock, flags);
855}
856
David Woodhouseb026fd22009-06-28 10:37:25 +0100857static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000858 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700859{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600860 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700861 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700862 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700863
864 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200865
Jiang Liu162d1b12014-07-11 14:19:35 +0800866 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200867 /* Address beyond IOMMU's addressing capabilities. */
868 return NULL;
869
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700870 parent = domain->pgd;
871
David Woodhouse5cf0a762014-03-19 16:07:49 +0000872 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700873 void *tmp_page;
874
David Woodhouseb026fd22009-06-28 10:37:25 +0100875 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700876 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000877 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100878 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000879 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700880 break;
881
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000882 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100883 uint64_t pteval;
884
Suresh Siddha4c923d42009-10-02 11:01:24 -0700885 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700886
David Woodhouse206a73c2009-07-01 19:30:28 +0100887 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700888 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100889
David Woodhousec85994e2009-07-01 19:21:24 +0100890 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400891 pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
Yijing Wangeffad4b2014-05-26 20:13:47 +0800892 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100893 /* Someone else set it while we were thinking; use theirs. */
894 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800895 else
David Woodhousec85994e2009-07-01 19:21:24 +0100896 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700897 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000898 if (level == 1)
899 break;
900
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000901 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700902 level--;
903 }
904
David Woodhouse5cf0a762014-03-19 16:07:49 +0000905 if (!*target_level)
906 *target_level = level;
907
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700908 return pte;
909}
910
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100911
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700912/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100913static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
914 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100915 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700916{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600917 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700918 int total = agaw_to_level(domain->agaw);
919 int offset;
920
921 parent = domain->pgd;
922 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100923 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700924 pte = &parent[offset];
925 if (level == total)
926 return pte;
927
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100928 if (!dma_pte_present(pte)) {
929 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700930 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100931 }
932
Yijing Wange16922a2014-05-20 20:37:51 +0800933 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100934 *large_page = total;
935 return pte;
936 }
937
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000938 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700939 total--;
940 }
941 return NULL;
942}
943
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700944/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000945static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +0100946 unsigned long start_pfn,
947 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700948{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600949 unsigned int large_page;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100950 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700951
Jiang Liu162d1b12014-07-11 14:19:35 +0800952 BUG_ON(!domain_pfn_supported(domain, start_pfn));
953 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700954 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100955
David Woodhouse04b18e62009-06-27 19:15:01 +0100956 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700957 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100958 large_page = 1;
959 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100960 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100961 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100962 continue;
963 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100964 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100965 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100966 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100967 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100968 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
969
David Woodhouse310a5ab2009-06-28 18:52:20 +0100970 domain_flush_cache(domain, first_pte,
971 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700972
973 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700974}
975
Alex Williamson3269ee02013-06-15 10:27:19 -0600976static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -0700977 int retain_level, struct dma_pte *pte,
978 unsigned long pfn, unsigned long start_pfn,
979 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -0600980{
981 pfn = max(start_pfn, pfn);
982 pte = &pte[pfn_level_offset(pfn, level)];
983
984 do {
985 unsigned long level_pfn;
986 struct dma_pte *level_pte;
987
988 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
989 goto next;
990
David Dillowf7116e12017-01-30 19:11:11 -0800991 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -0600992 level_pte = phys_to_virt(dma_pte_addr(pte));
993
David Dillowbc24c572017-06-28 19:42:23 -0700994 if (level > 2) {
995 dma_pte_free_level(domain, level - 1, retain_level,
996 level_pte, level_pfn, start_pfn,
997 last_pfn);
998 }
Alex Williamson3269ee02013-06-15 10:27:19 -0600999
David Dillowbc24c572017-06-28 19:42:23 -07001000 /*
1001 * Free the page table if we're below the level we want to
1002 * retain and the range covers the entire table.
1003 */
1004 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001005 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001006 dma_clear_pte(pte);
1007 domain_flush_cache(domain, pte, sizeof(*pte));
1008 free_pgtable_page(level_pte);
1009 }
1010next:
1011 pfn += level_size(level);
1012 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1013}
1014
David Dillowbc24c572017-06-28 19:42:23 -07001015/*
1016 * clear last level (leaf) ptes and free page table pages below the
1017 * level we wish to keep intact.
1018 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001019static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001020 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001021 unsigned long last_pfn,
1022 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001023{
Jiang Liu162d1b12014-07-11 14:19:35 +08001024 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1025 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001026 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001027
Jiang Liud41a4ad2014-07-11 14:19:34 +08001028 dma_pte_clear_range(domain, start_pfn, last_pfn);
1029
David Woodhousef3a0a522009-06-30 03:40:07 +01001030 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001031 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001032 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001033
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001034 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001035 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001036 free_pgtable_page(domain->pgd);
1037 domain->pgd = NULL;
1038 }
1039}
1040
David Woodhouseea8ea462014-03-05 17:09:32 +00001041/* When a page at a given level is being unlinked from its parent, we don't
1042 need to *modify* it at all. All we need to do is make a list of all the
1043 pages which can be freed just as soon as we've flushed the IOTLB and we
1044 know the hardware page-walk will no longer touch them.
1045 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1046 be freed. */
1047static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1048 int level, struct dma_pte *pte,
1049 struct page *freelist)
1050{
1051 struct page *pg;
1052
1053 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1054 pg->freelist = freelist;
1055 freelist = pg;
1056
1057 if (level == 1)
1058 return freelist;
1059
Jiang Liuadeb2592014-04-09 10:20:39 +08001060 pte = page_address(pg);
1061 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001062 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1063 freelist = dma_pte_list_pagetables(domain, level - 1,
1064 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001065 pte++;
1066 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001067
1068 return freelist;
1069}
1070
1071static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1072 struct dma_pte *pte, unsigned long pfn,
1073 unsigned long start_pfn,
1074 unsigned long last_pfn,
1075 struct page *freelist)
1076{
1077 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1078
1079 pfn = max(start_pfn, pfn);
1080 pte = &pte[pfn_level_offset(pfn, level)];
1081
1082 do {
1083 unsigned long level_pfn;
1084
1085 if (!dma_pte_present(pte))
1086 goto next;
1087
1088 level_pfn = pfn & level_mask(level);
1089
1090 /* If range covers entire pagetable, free it */
1091 if (start_pfn <= level_pfn &&
1092 last_pfn >= level_pfn + level_size(level) - 1) {
1093 /* These suborbinate page tables are going away entirely. Don't
1094 bother to clear them; we're just going to *free* them. */
1095 if (level > 1 && !dma_pte_superpage(pte))
1096 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1097
1098 dma_clear_pte(pte);
1099 if (!first_pte)
1100 first_pte = pte;
1101 last_pte = pte;
1102 } else if (level > 1) {
1103 /* Recurse down into a level that isn't *entirely* obsolete */
1104 freelist = dma_pte_clear_level(domain, level - 1,
1105 phys_to_virt(dma_pte_addr(pte)),
1106 level_pfn, start_pfn, last_pfn,
1107 freelist);
1108 }
1109next:
1110 pfn += level_size(level);
1111 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1112
1113 if (first_pte)
1114 domain_flush_cache(domain, first_pte,
1115 (void *)++last_pte - (void *)first_pte);
1116
1117 return freelist;
1118}
1119
1120/* We can't just free the pages because the IOMMU may still be walking
1121 the page tables, and may have cached the intermediate levels. The
1122 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001123static struct page *domain_unmap(struct dmar_domain *domain,
1124 unsigned long start_pfn,
1125 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001126{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001127 struct page *freelist;
David Woodhouseea8ea462014-03-05 17:09:32 +00001128
Jiang Liu162d1b12014-07-11 14:19:35 +08001129 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1130 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001131 BUG_ON(start_pfn > last_pfn);
1132
1133 /* we don't need lock here; nobody else touches the iova range */
1134 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1135 domain->pgd, 0, start_pfn, last_pfn, NULL);
1136
1137 /* free pgd */
1138 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1139 struct page *pgd_page = virt_to_page(domain->pgd);
1140 pgd_page->freelist = freelist;
1141 freelist = pgd_page;
1142
1143 domain->pgd = NULL;
1144 }
1145
1146 return freelist;
1147}
1148
Joerg Roedelb6904202015-08-13 11:32:18 +02001149static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001150{
1151 struct page *pg;
1152
1153 while ((pg = freelist)) {
1154 freelist = pg->freelist;
1155 free_pgtable_page(page_address(pg));
1156 }
1157}
1158
Joerg Roedel13cf0172017-08-11 11:40:10 +02001159static void iova_entry_free(unsigned long data)
1160{
1161 struct page *freelist = (struct page *)data;
1162
1163 dma_free_pagelist(freelist);
1164}
1165
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001166/* iommu handling */
1167static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1168{
1169 struct root_entry *root;
1170 unsigned long flags;
1171
Suresh Siddha4c923d42009-10-02 11:01:24 -07001172 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001173 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001174 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001175 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001176 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001177 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001178
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001179 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001180
1181 spin_lock_irqsave(&iommu->lock, flags);
1182 iommu->root_entry = root;
1183 spin_unlock_irqrestore(&iommu->lock, flags);
1184
1185 return 0;
1186}
1187
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001188static void iommu_set_root_entry(struct intel_iommu *iommu)
1189{
David Woodhouse03ecc322015-02-13 14:35:21 +00001190 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001191 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001192 unsigned long flag;
1193
David Woodhouse03ecc322015-02-13 14:35:21 +00001194 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001195 if (sm_supported(iommu))
1196 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001197
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001198 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001199 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001200
David Woodhousec416daa2009-05-10 20:30:58 +01001201 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001202
1203 /* Make sure hardware complete it */
1204 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001205 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001206
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001207 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001208}
1209
Lu Baolu6f7db752018-12-10 09:59:00 +08001210void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001211{
1212 u32 val;
1213 unsigned long flag;
1214
David Woodhouse9af88142009-02-13 23:18:03 +00001215 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001216 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001217
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001218 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001219 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001220
1221 /* Make sure hardware complete it */
1222 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001223 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001224
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001225 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001226}
1227
1228/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001229static void __iommu_flush_context(struct intel_iommu *iommu,
1230 u16 did, u16 source_id, u8 function_mask,
1231 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001232{
1233 u64 val = 0;
1234 unsigned long flag;
1235
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001236 switch (type) {
1237 case DMA_CCMD_GLOBAL_INVL:
1238 val = DMA_CCMD_GLOBAL_INVL;
1239 break;
1240 case DMA_CCMD_DOMAIN_INVL:
1241 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1242 break;
1243 case DMA_CCMD_DEVICE_INVL:
1244 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1245 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1246 break;
1247 default:
1248 BUG();
1249 }
1250 val |= DMA_CCMD_ICC;
1251
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001252 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001253 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1254
1255 /* Make sure hardware complete it */
1256 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1257 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1258
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001259 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001260}
1261
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001262/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001263static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1264 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001265{
1266 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1267 u64 val = 0, val_iva = 0;
1268 unsigned long flag;
1269
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001270 switch (type) {
1271 case DMA_TLB_GLOBAL_FLUSH:
1272 /* global flush doesn't need set IVA_REG */
1273 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1274 break;
1275 case DMA_TLB_DSI_FLUSH:
1276 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1277 break;
1278 case DMA_TLB_PSI_FLUSH:
1279 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001280 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001281 val_iva = size_order | addr;
1282 break;
1283 default:
1284 BUG();
1285 }
1286 /* Note: set drain read/write */
1287#if 0
1288 /*
1289 * This is probably to be super secure.. Looks like we can
1290 * ignore it without any impact.
1291 */
1292 if (cap_read_drain(iommu->cap))
1293 val |= DMA_TLB_READ_DRAIN;
1294#endif
1295 if (cap_write_drain(iommu->cap))
1296 val |= DMA_TLB_WRITE_DRAIN;
1297
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001298 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001299 /* Note: Only uses first TLB reg currently */
1300 if (val_iva)
1301 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1302 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1303
1304 /* Make sure hardware complete it */
1305 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1306 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1307
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001308 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001309
1310 /* check IOTLB invalidation granularity */
1311 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001312 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001313 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001314 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001315 (unsigned long long)DMA_TLB_IIRG(type),
1316 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001317}
1318
David Woodhouse64ae8922014-03-09 12:52:30 -07001319static struct device_domain_info *
1320iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1321 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001322{
Yu Zhao93a23a72009-05-18 13:51:37 +08001323 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001324
Joerg Roedel55d94042015-07-22 16:50:40 +02001325 assert_spin_locked(&device_domain_lock);
1326
Yu Zhao93a23a72009-05-18 13:51:37 +08001327 if (!iommu->qi)
1328 return NULL;
1329
Yu Zhao93a23a72009-05-18 13:51:37 +08001330 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001331 if (info->iommu == iommu && info->bus == bus &&
1332 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001333 if (info->ats_supported && info->dev)
1334 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001335 break;
1336 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001337
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001338 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001339}
1340
Omer Peleg0824c592016-04-20 19:03:35 +03001341static void domain_update_iotlb(struct dmar_domain *domain)
1342{
1343 struct device_domain_info *info;
1344 bool has_iotlb_device = false;
1345
1346 assert_spin_locked(&device_domain_lock);
1347
1348 list_for_each_entry(info, &domain->devices, link) {
1349 struct pci_dev *pdev;
1350
1351 if (!info->dev || !dev_is_pci(info->dev))
1352 continue;
1353
1354 pdev = to_pci_dev(info->dev);
1355 if (pdev->ats_enabled) {
1356 has_iotlb_device = true;
1357 break;
1358 }
1359 }
1360
1361 domain->has_iotlb_device = has_iotlb_device;
1362}
1363
Yu Zhao93a23a72009-05-18 13:51:37 +08001364static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1365{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001366 struct pci_dev *pdev;
1367
Omer Peleg0824c592016-04-20 19:03:35 +03001368 assert_spin_locked(&device_domain_lock);
1369
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001370 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001371 return;
1372
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001373 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001374 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1375 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1376 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1377 * reserved, which should be set to 0.
1378 */
1379 if (!ecap_dit(info->iommu->ecap))
1380 info->pfsid = 0;
1381 else {
1382 struct pci_dev *pf_pdev;
1383
1384 /* pdev will be returned if device is not a vf */
1385 pf_pdev = pci_physfn(pdev);
Heiner Kallweitcc49baa2019-04-24 21:16:10 +02001386 info->pfsid = pci_dev_id(pf_pdev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001387 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001388
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001389#ifdef CONFIG_INTEL_IOMMU_SVM
1390 /* The PCIe spec, in its wisdom, declares that the behaviour of
1391 the device if you enable PASID support after ATS support is
1392 undefined. So always enable PASID support on devices which
1393 have it, even if we can't yet know if we're ever going to
1394 use it. */
1395 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1396 info->pasid_enabled = 1;
1397
Kuppuswamy Sathyanarayanan1b84778a2019-02-19 11:04:52 -08001398 if (info->pri_supported &&
1399 (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
1400 !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001401 info->pri_enabled = 1;
1402#endif
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001403 if (!pdev->untrusted && info->ats_supported &&
Kuppuswamy Sathyanarayanan61363c12019-02-19 11:06:10 -08001404 pci_ats_page_aligned(pdev) &&
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001405 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001406 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001407 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001408 info->ats_qdep = pci_ats_queue_depth(pdev);
1409 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001410}
1411
1412static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1413{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001414 struct pci_dev *pdev;
1415
Omer Peleg0824c592016-04-20 19:03:35 +03001416 assert_spin_locked(&device_domain_lock);
1417
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001418 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001419 return;
1420
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001421 pdev = to_pci_dev(info->dev);
1422
1423 if (info->ats_enabled) {
1424 pci_disable_ats(pdev);
1425 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001426 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001427 }
1428#ifdef CONFIG_INTEL_IOMMU_SVM
1429 if (info->pri_enabled) {
1430 pci_disable_pri(pdev);
1431 info->pri_enabled = 0;
1432 }
1433 if (info->pasid_enabled) {
1434 pci_disable_pasid(pdev);
1435 info->pasid_enabled = 0;
1436 }
1437#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001438}
1439
1440static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1441 u64 addr, unsigned mask)
1442{
1443 u16 sid, qdep;
1444 unsigned long flags;
1445 struct device_domain_info *info;
1446
Omer Peleg0824c592016-04-20 19:03:35 +03001447 if (!domain->has_iotlb_device)
1448 return;
1449
Yu Zhao93a23a72009-05-18 13:51:37 +08001450 spin_lock_irqsave(&device_domain_lock, flags);
1451 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001452 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001453 continue;
1454
1455 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001456 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001457 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1458 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001459 }
1460 spin_unlock_irqrestore(&device_domain_lock, flags);
1461}
1462
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001463static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1464 struct dmar_domain *domain,
1465 unsigned long pfn, unsigned int pages,
1466 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001467{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001468 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001469 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001470 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001471
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001472 BUG_ON(pages == 0);
1473
David Woodhouseea8ea462014-03-05 17:09:32 +00001474 if (ih)
1475 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001476 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001477 * Fallback to domain selective flush if no PSI support or the size is
1478 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001479 * PSI requires page size to be 2 ^ x, and the base address is naturally
1480 * aligned to the size
1481 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001482 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1483 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001484 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001485 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001486 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001487 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001488
1489 /*
Nadav Amit82653632010-04-01 13:24:40 +03001490 * In caching mode, changes of pages from non-present to present require
1491 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001492 */
Nadav Amit82653632010-04-01 13:24:40 +03001493 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001494 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001495}
1496
Peter Xueed91a02018-05-04 10:34:52 +08001497/* Notification for newly created mappings */
1498static inline void __mapping_notify_one(struct intel_iommu *iommu,
1499 struct dmar_domain *domain,
1500 unsigned long pfn, unsigned int pages)
1501{
1502 /* It's a non-present to present mapping. Only flush if caching mode */
1503 if (cap_caching_mode(iommu->cap))
1504 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1505 else
1506 iommu_flush_write_buffer(iommu);
1507}
1508
Joerg Roedel13cf0172017-08-11 11:40:10 +02001509static void iommu_flush_iova(struct iova_domain *iovad)
1510{
1511 struct dmar_domain *domain;
1512 int idx;
1513
1514 domain = container_of(iovad, struct dmar_domain, iovad);
1515
1516 for_each_domain_iommu(idx, domain) {
1517 struct intel_iommu *iommu = g_iommus[idx];
1518 u16 did = domain->iommu_did[iommu->seq_id];
1519
1520 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
1521
1522 if (!cap_caching_mode(iommu->cap))
1523 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1524 0, MAX_AGAW_PFN_WIDTH);
1525 }
1526}
1527
mark grossf8bab732008-02-08 04:18:38 -08001528static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1529{
1530 u32 pmen;
1531 unsigned long flags;
1532
Lu Baolu5bb71fc72019-03-20 09:58:33 +08001533 if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
1534 return;
1535
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001536 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001537 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1538 pmen &= ~DMA_PMEN_EPM;
1539 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1540
1541 /* wait for the protected region status bit to clear */
1542 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1543 readl, !(pmen & DMA_PMEN_PRS), pmen);
1544
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001545 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001546}
1547
Jiang Liu2a41cce2014-07-11 14:19:33 +08001548static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001549{
1550 u32 sts;
1551 unsigned long flags;
1552
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001553 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001554 iommu->gcmd |= DMA_GCMD_TE;
1555 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001556
1557 /* Make sure hardware complete it */
1558 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001559 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001560
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001561 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001562}
1563
Jiang Liu2a41cce2014-07-11 14:19:33 +08001564static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001565{
1566 u32 sts;
1567 unsigned long flag;
1568
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001569 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001570 iommu->gcmd &= ~DMA_GCMD_TE;
1571 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1572
1573 /* Make sure hardware complete it */
1574 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001575 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001576
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001577 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001578}
1579
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001580
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001581static int iommu_init_domains(struct intel_iommu *iommu)
1582{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001583 u32 ndomains, nlongs;
1584 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001585
1586 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001587 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001588 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001589 nlongs = BITS_TO_LONGS(ndomains);
1590
Donald Dutile94a91b502009-08-20 16:51:34 -04001591 spin_lock_init(&iommu->lock);
1592
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001593 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1594 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001595 pr_err("%s: Allocating domain id array failed\n",
1596 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001597 return -ENOMEM;
1598 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001599
Wei Yang86f004c2016-05-21 02:41:51 +00001600 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001601 iommu->domains = kzalloc(size, GFP_KERNEL);
1602
1603 if (iommu->domains) {
1604 size = 256 * sizeof(struct dmar_domain *);
1605 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1606 }
1607
1608 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001609 pr_err("%s: Allocating domain array failed\n",
1610 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001611 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001612 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001613 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001614 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001615 return -ENOMEM;
1616 }
1617
Joerg Roedel8bf47812015-07-21 10:41:21 +02001618
1619
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001620 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001621 * If Caching mode is set, then invalid translations are tagged
1622 * with domain-id 0, hence we need to pre-allocate it. We also
1623 * use domain-id 0 as a marker for non-allocated domain-id, so
1624 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001625 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001626 set_bit(0, iommu->domain_ids);
1627
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001628 /*
1629 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1630 * entry for first-level or pass-through translation modes should
1631 * be programmed with a domain id different from those used for
1632 * second-level or nested translation. We reserve a domain id for
1633 * this purpose.
1634 */
1635 if (sm_supported(iommu))
1636 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1637
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001638 return 0;
1639}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001640
Jiang Liuffebeb42014-11-09 22:48:02 +08001641static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001642{
Joerg Roedel29a27712015-07-21 17:17:12 +02001643 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001644 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001645
Joerg Roedel29a27712015-07-21 17:17:12 +02001646 if (!iommu->domains || !iommu->domain_ids)
1647 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001648
Joerg Roedelbea64032016-11-08 15:08:26 +01001649again:
Joerg Roedel55d94042015-07-22 16:50:40 +02001650 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001651 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
1652 struct dmar_domain *domain;
1653
1654 if (info->iommu != iommu)
1655 continue;
1656
1657 if (!info->dev || !info->domain)
1658 continue;
1659
1660 domain = info->domain;
1661
Joerg Roedelbea64032016-11-08 15:08:26 +01001662 __dmar_remove_one_dev_info(info);
Joerg Roedel29a27712015-07-21 17:17:12 +02001663
Joerg Roedelbea64032016-11-08 15:08:26 +01001664 if (!domain_type_is_vm_or_si(domain)) {
1665 /*
1666 * The domain_exit() function can't be called under
1667 * device_domain_lock, as it takes this lock itself.
1668 * So release the lock here and re-run the loop
1669 * afterwards.
1670 */
1671 spin_unlock_irqrestore(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001672 domain_exit(domain);
Joerg Roedelbea64032016-11-08 15:08:26 +01001673 goto again;
1674 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001675 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001676 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001677
1678 if (iommu->gcmd & DMA_GCMD_TE)
1679 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001680}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001681
Jiang Liuffebeb42014-11-09 22:48:02 +08001682static void free_dmar_iommu(struct intel_iommu *iommu)
1683{
1684 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001685 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001686 int i;
1687
1688 for (i = 0; i < elems; i++)
1689 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001690 kfree(iommu->domains);
1691 kfree(iommu->domain_ids);
1692 iommu->domains = NULL;
1693 iommu->domain_ids = NULL;
1694 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001695
Weidong Hand9630fe2008-12-08 11:06:32 +08001696 g_iommus[iommu->seq_id] = NULL;
1697
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001698 /* free context mapping */
1699 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001700
1701#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001702 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001703 if (ecap_prs(iommu->ecap))
1704 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001705 }
David Woodhouse8a94ade2015-03-24 14:54:56 +00001706#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001707}
1708
Jiang Liuab8dfe22014-07-11 14:19:27 +08001709static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001710{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001712
1713 domain = alloc_domain_mem();
1714 if (!domain)
1715 return NULL;
1716
Jiang Liuab8dfe22014-07-11 14:19:27 +08001717 memset(domain, 0, sizeof(*domain));
Anshuman Khandual98fa15f2019-03-05 15:42:58 -08001718 domain->nid = NUMA_NO_NODE;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001719 domain->flags = flags;
Omer Peleg0824c592016-04-20 19:03:35 +03001720 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001721 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001722
1723 return domain;
1724}
1725
Joerg Roedeld160aca2015-07-22 11:52:53 +02001726/* Must be called with iommu->lock */
1727static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001728 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001729{
Jiang Liu44bde612014-07-11 14:19:29 +08001730 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001731 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001732
Joerg Roedel55d94042015-07-22 16:50:40 +02001733 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001734 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001735
Joerg Roedel29a27712015-07-21 17:17:12 +02001736 domain->iommu_refcnt[iommu->seq_id] += 1;
1737 domain->iommu_count += 1;
1738 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001739 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001740 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1741
1742 if (num >= ndomains) {
1743 pr_err("%s: No free domain ids\n", iommu->name);
1744 domain->iommu_refcnt[iommu->seq_id] -= 1;
1745 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001746 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001747 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001748
Joerg Roedeld160aca2015-07-22 11:52:53 +02001749 set_bit(num, iommu->domain_ids);
1750 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001751
Joerg Roedeld160aca2015-07-22 11:52:53 +02001752 domain->iommu_did[iommu->seq_id] = num;
1753 domain->nid = iommu->node;
1754
Jiang Liufb170fb2014-07-11 14:19:28 +08001755 domain_update_iommu_cap(domain);
1756 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001757
Joerg Roedel55d94042015-07-22 16:50:40 +02001758 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001759}
1760
1761static int domain_detach_iommu(struct dmar_domain *domain,
1762 struct intel_iommu *iommu)
1763{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001764 int num, count;
Jiang Liufb170fb2014-07-11 14:19:28 +08001765
Joerg Roedel55d94042015-07-22 16:50:40 +02001766 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001767 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001768
Joerg Roedel29a27712015-07-21 17:17:12 +02001769 domain->iommu_refcnt[iommu->seq_id] -= 1;
1770 count = --domain->iommu_count;
1771 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001772 num = domain->iommu_did[iommu->seq_id];
1773 clear_bit(num, iommu->domain_ids);
1774 set_iommu_domain(iommu, num, NULL);
1775
Jiang Liufb170fb2014-07-11 14:19:28 +08001776 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001777 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001778 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001779
1780 return count;
1781}
1782
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001783static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001784static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001785
Joseph Cihula51a63e62011-03-21 11:04:24 -07001786static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001787{
1788 struct pci_dev *pdev = NULL;
1789 struct iova *iova;
1790 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001791
Zhen Leiaa3ac942017-09-21 16:52:45 +01001792 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001793
Mark Gross8a443df2008-03-04 14:59:31 -08001794 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1795 &reserved_rbtree_key);
1796
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001797 /* IOAPIC ranges shouldn't be accessed by DMA */
1798 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1799 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001800 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001801 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001802 return -ENODEV;
1803 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001804
1805 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1806 for_each_pci_dev(pdev) {
1807 struct resource *r;
1808
1809 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1810 r = &pdev->resource[i];
1811 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1812 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001813 iova = reserve_iova(&reserved_iova_list,
1814 IOVA_PFN(r->start),
1815 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001816 if (!iova) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06001817 pci_err(pdev, "Reserve iova for %pR failed\n", r);
Joseph Cihula51a63e62011-03-21 11:04:24 -07001818 return -ENODEV;
1819 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001820 }
1821 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001822 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001823}
1824
1825static void domain_reserve_special_ranges(struct dmar_domain *domain)
1826{
1827 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1828}
1829
1830static inline int guestwidth_to_adjustwidth(int gaw)
1831{
1832 int agaw;
1833 int r = (gaw - 12) % 9;
1834
1835 if (r == 0)
1836 agaw = gaw;
1837 else
1838 agaw = gaw + 9 - r;
1839 if (agaw > 64)
1840 agaw = 64;
1841 return agaw;
1842}
1843
Joerg Roedeldc534b22015-07-22 12:44:02 +02001844static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1845 int guest_width)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001846{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001847 int adjust_width, agaw;
1848 unsigned long sagaw;
Joerg Roedel13cf0172017-08-11 11:40:10 +02001849 int err;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001850
Zhen Leiaa3ac942017-09-21 16:52:45 +01001851 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001852
1853 err = init_iova_flush_queue(&domain->iovad,
1854 iommu_flush_iova, iova_entry_free);
1855 if (err)
1856 return err;
1857
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001858 domain_reserve_special_ranges(domain);
1859
1860 /* calculate AGAW */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001861 if (guest_width > cap_mgaw(iommu->cap))
1862 guest_width = cap_mgaw(iommu->cap);
1863 domain->gaw = guest_width;
1864 adjust_width = guestwidth_to_adjustwidth(guest_width);
1865 agaw = width_to_agaw(adjust_width);
1866 sagaw = cap_sagaw(iommu->cap);
1867 if (!test_bit(agaw, &sagaw)) {
1868 /* hardware doesn't support it, choose a bigger one */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001869 pr_debug("Hardware doesn't support agaw %d\n", agaw);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001870 agaw = find_next_bit(&sagaw, 5, agaw);
1871 if (agaw >= 5)
1872 return -ENODEV;
1873 }
1874 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001875
Weidong Han8e6040972008-12-08 15:49:06 +08001876 if (ecap_coherent(iommu->ecap))
1877 domain->iommu_coherency = 1;
1878 else
1879 domain->iommu_coherency = 0;
1880
Sheng Yang58c610b2009-03-18 15:33:05 +08001881 if (ecap_sc_support(iommu->ecap))
1882 domain->iommu_snooping = 1;
1883 else
1884 domain->iommu_snooping = 0;
1885
David Woodhouse214e39a2014-03-19 10:38:49 +00001886 if (intel_iommu_superpage)
1887 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1888 else
1889 domain->iommu_superpage = 0;
1890
Suresh Siddha4c923d42009-10-02 11:01:24 -07001891 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001892
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001893 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001894 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001895 if (!domain->pgd)
1896 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001897 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001898 return 0;
1899}
1900
1901static void domain_exit(struct dmar_domain *domain)
1902{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001903 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001904
Joerg Roedeld160aca2015-07-22 11:52:53 +02001905 /* Remove associated devices and clear attached or cached domains */
1906 rcu_read_lock();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001907 domain_remove_dev_info(domain);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001908 rcu_read_unlock();
Jiang Liu92d03cc2014-02-19 14:07:28 +08001909
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001910 /* destroy iovas */
1911 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001912
David Woodhouseea8ea462014-03-05 17:09:32 +00001913 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001914
David Woodhouseea8ea462014-03-05 17:09:32 +00001915 dma_free_pagelist(freelist);
1916
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001917 free_domain_mem(domain);
1918}
1919
Lu Baolu7373a8c2018-12-10 09:59:03 +08001920/*
1921 * Get the PASID directory size for scalable mode context entry.
1922 * Value of X in the PDTS field of a scalable mode context entry
1923 * indicates PASID directory with 2^(X + 7) entries.
1924 */
1925static inline unsigned long context_get_sm_pds(struct pasid_table *table)
1926{
1927 int pds, max_pde;
1928
1929 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
1930 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
1931 if (pds < 7)
1932 return 0;
1933
1934 return pds - 7;
1935}
1936
1937/*
1938 * Set the RID_PASID field of a scalable mode context entry. The
1939 * IOMMU hardware will use the PASID value set in this field for
1940 * DMA translations of DMA requests without PASID.
1941 */
1942static inline void
1943context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
1944{
1945 context->hi |= pasid & ((1 << 20) - 1);
1946 context->hi |= (1 << 20);
1947}
1948
1949/*
1950 * Set the DTE(Device-TLB Enable) field of a scalable mode context
1951 * entry.
1952 */
1953static inline void context_set_sm_dte(struct context_entry *context)
1954{
1955 context->lo |= (1 << 2);
1956}
1957
1958/*
1959 * Set the PRE(Page Request Enable) field of a scalable mode context
1960 * entry.
1961 */
1962static inline void context_set_sm_pre(struct context_entry *context)
1963{
1964 context->lo |= (1 << 4);
1965}
1966
1967/* Convert value to context PASID directory size field coding. */
1968#define context_pdts(pds) (((pds) & 0x7) << 9)
1969
David Woodhouse64ae8922014-03-09 12:52:30 -07001970static int domain_context_mapping_one(struct dmar_domain *domain,
1971 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08001972 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001973 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001974{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001975 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02001976 int translation = CONTEXT_TT_MULTI_LEVEL;
1977 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001978 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001979 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08001980 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02001981
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001982 WARN_ON(did == 0);
1983
Joerg Roedel28ccce02015-07-21 14:45:31 +02001984 if (hw_pass_through && domain_type_is_si(domain))
1985 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001986
1987 pr_debug("Set context mapping for %02x:%02x.%d\n",
1988 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001989
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001990 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08001991
Joerg Roedel55d94042015-07-22 16:50:40 +02001992 spin_lock_irqsave(&device_domain_lock, flags);
1993 spin_lock(&iommu->lock);
1994
1995 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00001996 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001997 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02001998 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001999
Joerg Roedel55d94042015-07-22 16:50:40 +02002000 ret = 0;
2001 if (context_present(context))
2002 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002003
Xunlei Pangaec0e862016-12-05 20:09:07 +08002004 /*
2005 * For kdump cases, old valid entries may be cached due to the
2006 * in-flight DMA and copied pgtable, but there is no unmapping
2007 * behaviour for them, thus we need an explicit cache flush for
2008 * the newly-mapped device. For kdump, at this point, the device
2009 * is supposed to finish reset at its driver probe stage, so no
2010 * in-flight DMA will exist, and we don't need to worry anymore
2011 * hereafter.
2012 */
2013 if (context_copied(context)) {
2014 u16 did_old = context_domain_id(context);
2015
Christos Gkekasb117e032017-10-08 23:33:31 +01002016 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002017 iommu->flush.flush_context(iommu, did_old,
2018 (((u16)bus) << 8) | devfn,
2019 DMA_CCMD_MASK_NOBIT,
2020 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002021 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2022 DMA_TLB_DSI_FLUSH);
2023 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002024 }
2025
Joerg Roedelde24e552015-07-21 14:53:04 +02002026 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002027
Lu Baolu7373a8c2018-12-10 09:59:03 +08002028 if (sm_supported(iommu)) {
2029 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002030
Lu Baolu7373a8c2018-12-10 09:59:03 +08002031 WARN_ON(!table);
2032
2033 /* Setup the PASID DIR pointer: */
2034 pds = context_get_sm_pds(table);
2035 context->lo = (u64)virt_to_phys(table->table) |
2036 context_pdts(pds);
2037
2038 /* Setup the RID_PASID field: */
2039 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2040
2041 /*
2042 * Setup the Device-TLB enable bit and Page request
2043 * Enable bit:
2044 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002045 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002046 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002047 context_set_sm_dte(context);
2048 if (info && info->pri_supported)
2049 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002050 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002051 struct dma_pte *pgd = domain->pgd;
2052 int agaw;
2053
2054 context_set_domain_id(context, did);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002055
2056 if (translation != CONTEXT_TT_PASS_THROUGH) {
2057 /*
2058 * Skip top levels of page tables for iommu which has
2059 * less agaw than default. Unnecessary for PT mode.
2060 */
2061 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2062 ret = -ENOMEM;
2063 pgd = phys_to_virt(dma_pte_addr(pgd));
2064 if (!dma_pte_present(pgd))
2065 goto out_unlock;
2066 }
2067
2068 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2069 if (info && info->ats_supported)
2070 translation = CONTEXT_TT_DEV_IOTLB;
2071 else
2072 translation = CONTEXT_TT_MULTI_LEVEL;
2073
2074 context_set_address_root(context, virt_to_phys(pgd));
2075 context_set_address_width(context, agaw);
2076 } else {
2077 /*
2078 * In pass through mode, AW must be programmed to
2079 * indicate the largest AGAW value supported by
2080 * hardware. And ASR is ignored by hardware.
2081 */
2082 context_set_address_width(context, iommu->msagaw);
2083 }
Lu Baolu41b80db2019-03-01 11:23:11 +08002084
2085 context_set_translation_type(context, translation);
Yu Zhao93a23a72009-05-18 13:51:37 +08002086 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002087
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002088 context_set_fault_enable(context);
2089 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08002090 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002091
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002092 /*
2093 * It's a non-present to present mapping. If hardware doesn't cache
2094 * non-present entry we only need to flush the write-buffer. If the
2095 * _does_ cache non-present entries, then it does so in the special
2096 * domain #0, which we have to flush:
2097 */
2098 if (cap_caching_mode(iommu->cap)) {
2099 iommu->flush.flush_context(iommu, 0,
2100 (((u16)bus) << 8) | devfn,
2101 DMA_CCMD_MASK_NOBIT,
2102 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002103 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002104 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002105 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002106 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002107 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002108
Joerg Roedel55d94042015-07-22 16:50:40 +02002109 ret = 0;
2110
2111out_unlock:
2112 spin_unlock(&iommu->lock);
2113 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002114
Wei Yang5c365d12016-07-13 13:53:21 +00002115 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002116}
2117
Alex Williamson579305f2014-07-03 09:51:43 -06002118struct domain_context_mapping_data {
2119 struct dmar_domain *domain;
2120 struct intel_iommu *iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002121 struct pasid_table *table;
Alex Williamson579305f2014-07-03 09:51:43 -06002122};
2123
2124static int domain_context_mapping_cb(struct pci_dev *pdev,
2125 u16 alias, void *opaque)
2126{
2127 struct domain_context_mapping_data *data = opaque;
2128
2129 return domain_context_mapping_one(data->domain, data->iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002130 data->table, PCI_BUS_NUM(alias),
2131 alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06002132}
2133
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002134static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002135domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002136{
Lu Baoluca6e3222018-12-10 09:59:02 +08002137 struct domain_context_mapping_data data;
2138 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002139 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002140 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002141
David Woodhousee1f167f2014-03-09 15:24:46 -07002142 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002143 if (!iommu)
2144 return -ENODEV;
2145
Lu Baoluca6e3222018-12-10 09:59:02 +08002146 table = intel_pasid_get_table(dev);
2147
Alex Williamson579305f2014-07-03 09:51:43 -06002148 if (!dev_is_pci(dev))
Lu Baoluca6e3222018-12-10 09:59:02 +08002149 return domain_context_mapping_one(domain, iommu, table,
2150 bus, devfn);
Alex Williamson579305f2014-07-03 09:51:43 -06002151
2152 data.domain = domain;
2153 data.iommu = iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002154 data.table = table;
Alex Williamson579305f2014-07-03 09:51:43 -06002155
2156 return pci_for_each_dma_alias(to_pci_dev(dev),
2157 &domain_context_mapping_cb, &data);
2158}
2159
2160static int domain_context_mapped_cb(struct pci_dev *pdev,
2161 u16 alias, void *opaque)
2162{
2163 struct intel_iommu *iommu = opaque;
2164
2165 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002166}
2167
David Woodhousee1f167f2014-03-09 15:24:46 -07002168static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002169{
Weidong Han5331fe62008-12-08 23:00:00 +08002170 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002171 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002172
David Woodhousee1f167f2014-03-09 15:24:46 -07002173 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002174 if (!iommu)
2175 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002176
Alex Williamson579305f2014-07-03 09:51:43 -06002177 if (!dev_is_pci(dev))
2178 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002179
Alex Williamson579305f2014-07-03 09:51:43 -06002180 return !pci_for_each_dma_alias(to_pci_dev(dev),
2181 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002182}
2183
Fenghua Yuf5329592009-08-04 15:09:37 -07002184/* Returns a number of VTD pages, but aligned to MM page size */
2185static inline unsigned long aligned_nrpages(unsigned long host_addr,
2186 size_t size)
2187{
2188 host_addr &= ~PAGE_MASK;
2189 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2190}
2191
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002192/* Return largest possible superpage level for a given mapping */
2193static inline int hardware_largepage_caps(struct dmar_domain *domain,
2194 unsigned long iov_pfn,
2195 unsigned long phy_pfn,
2196 unsigned long pages)
2197{
2198 int support, level = 1;
2199 unsigned long pfnmerge;
2200
2201 support = domain->iommu_superpage;
2202
2203 /* To use a large page, the virtual *and* physical addresses
2204 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2205 of them will mean we have to use smaller pages. So just
2206 merge them and check both at once. */
2207 pfnmerge = iov_pfn | phy_pfn;
2208
2209 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2210 pages >>= VTD_STRIDE_SHIFT;
2211 if (!pages)
2212 break;
2213 pfnmerge >>= VTD_STRIDE_SHIFT;
2214 level++;
2215 support--;
2216 }
2217 return level;
2218}
2219
David Woodhouse9051aa02009-06-29 12:30:54 +01002220static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2221 struct scatterlist *sg, unsigned long phys_pfn,
2222 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002223{
2224 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002225 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002226 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002227 unsigned int largepage_lvl = 0;
2228 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01002229
Jiang Liu162d1b12014-07-11 14:19:35 +08002230 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002231
2232 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2233 return -EINVAL;
2234
2235 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
2236
Jiang Liucc4f14a2014-11-26 09:42:10 +08002237 if (!sg) {
2238 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01002239 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
2240 }
2241
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002242 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002243 uint64_t tmp;
2244
David Woodhousee1605492009-06-29 11:17:38 +01002245 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002246 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2247
Fenghua Yuf5329592009-08-04 15:09:37 -07002248 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002249 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002250 sg->dma_length = sg->length;
Robin Murphy29a90b72017-09-28 15:14:01 +01002251 pteval = (sg_phys(sg) - pgoff) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002252 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002253 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002254
David Woodhousee1605492009-06-29 11:17:38 +01002255 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002256 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2257
David Woodhouse5cf0a762014-03-19 16:07:49 +00002258 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002259 if (!pte)
2260 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002261 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002262 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002263 unsigned long nr_superpages, end_pfn;
2264
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002265 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002266 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002267
2268 nr_superpages = sg_res / lvl_pages;
2269 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2270
Jiang Liud41a4ad2014-07-11 14:19:34 +08002271 /*
2272 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002273 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002274 * We're adding new large pages, so make sure
2275 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002276 */
David Dillowbc24c572017-06-28 19:42:23 -07002277 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2278 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002279 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002280 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002281 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002282
David Woodhousee1605492009-06-29 11:17:38 +01002283 }
2284 /* We don't need lock here, nobody else
2285 * touches the iova range
2286 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002287 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002288 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002289 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002290 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2291 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002292 if (dumps) {
2293 dumps--;
2294 debug_dma_dump_mappings(NULL);
2295 }
2296 WARN_ON(1);
2297 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002298
2299 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2300
2301 BUG_ON(nr_pages < lvl_pages);
2302 BUG_ON(sg_res < lvl_pages);
2303
2304 nr_pages -= lvl_pages;
2305 iov_pfn += lvl_pages;
2306 phys_pfn += lvl_pages;
2307 pteval += lvl_pages * VTD_PAGE_SIZE;
2308 sg_res -= lvl_pages;
2309
2310 /* If the next PTE would be the first in a new page, then we
2311 need to flush the cache on the entries we've just written.
2312 And then we'll need to recalculate 'pte', so clear it and
2313 let it get set again in the if (!pte) block above.
2314
2315 If we're done (!nr_pages) we need to flush the cache too.
2316
2317 Also if we've been setting superpages, we may need to
2318 recalculate 'pte' and switch back to smaller pages for the
2319 end of the mapping, if the trailing size is not enough to
2320 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002321 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002322 if (!nr_pages || first_pte_in_page(pte) ||
2323 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002324 domain_flush_cache(domain, first_pte,
2325 (void *)pte - (void *)first_pte);
2326 pte = NULL;
2327 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002328
2329 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002330 sg = sg_next(sg);
2331 }
2332 return 0;
2333}
2334
Peter Xu87684fd2018-05-04 10:34:53 +08002335static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
Lu Baolu095303e2019-04-29 09:16:02 +08002336 struct scatterlist *sg, unsigned long phys_pfn,
2337 unsigned long nr_pages, int prot)
Peter Xu87684fd2018-05-04 10:34:53 +08002338{
Lu Baolu095303e2019-04-29 09:16:02 +08002339 int ret;
2340 struct intel_iommu *iommu;
Peter Xu87684fd2018-05-04 10:34:53 +08002341
Lu Baolu095303e2019-04-29 09:16:02 +08002342 /* Do the real mapping first */
2343 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2344 if (ret)
2345 return ret;
Peter Xu87684fd2018-05-04 10:34:53 +08002346
Lu Baolu095303e2019-04-29 09:16:02 +08002347 /* Notify about the new mapping */
2348 if (domain_type_is_vm(domain)) {
2349 /* VM typed domains can have more than one IOMMUs */
2350 int iommu_id;
Peter Xu87684fd2018-05-04 10:34:53 +08002351
Lu Baolu095303e2019-04-29 09:16:02 +08002352 for_each_domain_iommu(iommu_id, domain) {
2353 iommu = g_iommus[iommu_id];
2354 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2355 }
2356 } else {
2357 /* General domains only have one IOMMU */
2358 iommu = domain_get_iommu(domain);
2359 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2360 }
2361
2362 return 0;
Peter Xu87684fd2018-05-04 10:34:53 +08002363}
2364
David Woodhouse9051aa02009-06-29 12:30:54 +01002365static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2366 struct scatterlist *sg, unsigned long nr_pages,
2367 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002368{
Peter Xu87684fd2018-05-04 10:34:53 +08002369 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002370}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002371
David Woodhouse9051aa02009-06-29 12:30:54 +01002372static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2373 unsigned long phys_pfn, unsigned long nr_pages,
2374 int prot)
2375{
Peter Xu87684fd2018-05-04 10:34:53 +08002376 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002377}
2378
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002379static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002380{
Filippo Sironi50822192017-08-31 10:58:11 +02002381 unsigned long flags;
2382 struct context_entry *context;
2383 u16 did_old;
2384
Weidong Hanc7151a82008-12-08 22:51:37 +08002385 if (!iommu)
2386 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002387
Filippo Sironi50822192017-08-31 10:58:11 +02002388 spin_lock_irqsave(&iommu->lock, flags);
2389 context = iommu_context_addr(iommu, bus, devfn, 0);
2390 if (!context) {
2391 spin_unlock_irqrestore(&iommu->lock, flags);
2392 return;
2393 }
2394 did_old = context_domain_id(context);
2395 context_clear_entry(context);
2396 __iommu_flush_cache(iommu, context, sizeof(*context));
2397 spin_unlock_irqrestore(&iommu->lock, flags);
2398 iommu->flush.flush_context(iommu,
2399 did_old,
2400 (((u16)bus) << 8) | devfn,
2401 DMA_CCMD_MASK_NOBIT,
2402 DMA_CCMD_DEVICE_INVL);
2403 iommu->flush.flush_iotlb(iommu,
2404 did_old,
2405 0,
2406 0,
2407 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002408}
2409
David Woodhouse109b9b02012-05-25 17:43:02 +01002410static inline void unlink_domain_info(struct device_domain_info *info)
2411{
2412 assert_spin_locked(&device_domain_lock);
2413 list_del(&info->link);
2414 list_del(&info->global);
2415 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002416 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002417}
2418
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002419static void domain_remove_dev_info(struct dmar_domain *domain)
2420{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002421 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002422 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002423
2424 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002425 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002426 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002427 spin_unlock_irqrestore(&device_domain_lock, flags);
2428}
2429
2430/*
2431 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002432 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002433 */
David Woodhouse1525a292014-03-06 16:19:30 +00002434static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002435{
2436 struct device_domain_info *info;
2437
2438 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002439 info = dev->archdata.iommu;
Peter Xub316d022017-05-22 18:28:51 +08002440 if (likely(info))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002441 return info->domain;
2442 return NULL;
2443}
2444
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002445static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002446dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2447{
2448 struct device_domain_info *info;
2449
2450 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002451 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002452 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002453 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002454
2455 return NULL;
2456}
2457
Joerg Roedel5db31562015-07-22 12:40:43 +02002458static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2459 int bus, int devfn,
2460 struct device *dev,
2461 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002462{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002463 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002464 struct device_domain_info *info;
2465 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002466 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002467
2468 info = alloc_devinfo_mem();
2469 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002470 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002471
Jiang Liu745f2582014-02-19 14:07:26 +08002472 info->bus = bus;
2473 info->devfn = devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002474 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2475 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2476 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002477 info->dev = dev;
2478 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002479 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002480 info->pasid_table = NULL;
Lu Baolu95587a72019-03-25 09:30:30 +08002481 info->auxd_enabled = 0;
Lu Baolu67b8e022019-03-25 09:30:32 +08002482 INIT_LIST_HEAD(&info->auxiliary_domains);
Jiang Liu745f2582014-02-19 14:07:26 +08002483
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002484 if (dev && dev_is_pci(dev)) {
2485 struct pci_dev *pdev = to_pci_dev(info->dev);
2486
Lu Baolud8b85912019-03-01 11:23:10 +08002487 if (!pdev->untrusted &&
2488 !pci_ats_disabled() &&
Gil Kupfercef74402018-05-10 17:56:02 -05002489 ecap_dev_iotlb_support(iommu->ecap) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002490 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
2491 dmar_find_matched_atsr_unit(pdev))
2492 info->ats_supported = 1;
2493
Lu Baolu765b6a92018-12-10 09:58:55 +08002494 if (sm_supported(iommu)) {
2495 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002496 int features = pci_pasid_features(pdev);
2497 if (features >= 0)
2498 info->pasid_supported = features | 1;
2499 }
2500
2501 if (info->ats_supported && ecap_prs(iommu->ecap) &&
2502 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
2503 info->pri_supported = 1;
2504 }
2505 }
2506
Dave Jiang7560cc32019-05-21 15:30:15 +08002507 spin_lock(&iommu->lock);
Jiang Liu745f2582014-02-19 14:07:26 +08002508 spin_lock_irqsave(&device_domain_lock, flags);
2509 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002510 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002511
2512 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002513 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002514 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002515 if (info2) {
2516 found = info2->domain;
2517 info2->dev = dev;
2518 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002519 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002520
Jiang Liu745f2582014-02-19 14:07:26 +08002521 if (found) {
2522 spin_unlock_irqrestore(&device_domain_lock, flags);
Dave Jiang7560cc32019-05-21 15:30:15 +08002523 spin_unlock(&iommu->lock);
Jiang Liu745f2582014-02-19 14:07:26 +08002524 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002525 /* Caller must free the original domain */
2526 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002527 }
2528
Joerg Roedeld160aca2015-07-22 11:52:53 +02002529 ret = domain_attach_iommu(domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02002530 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002531 spin_unlock_irqrestore(&device_domain_lock, flags);
Dave Jiang7560cc32019-05-21 15:30:15 +08002532 spin_unlock(&iommu->lock);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302533 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002534 return NULL;
2535 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002536
David Woodhouseb718cd32014-03-09 13:11:33 -07002537 list_add(&info->link, &domain->devices);
2538 list_add(&info->global, &device_domain_list);
2539 if (dev)
2540 dev->archdata.iommu = info;
Lu Baolu0bbeb012018-12-10 09:58:56 +08002541 spin_unlock_irqrestore(&device_domain_lock, flags);
Dave Jiang7560cc32019-05-21 15:30:15 +08002542 spin_unlock(&iommu->lock);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002543
Lu Baolu0bbeb012018-12-10 09:58:56 +08002544 /* PASID table is mandatory for a PCI device in scalable mode. */
2545 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002546 ret = intel_pasid_alloc_table(dev);
2547 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002548 dev_err(dev, "PASID table allocation failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002549 dmar_remove_one_dev_info(dev);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002550 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002551 }
Lu Baoluef848b72018-12-10 09:59:01 +08002552
2553 /* Setup the PASID entry for requests without PASID: */
2554 spin_lock(&iommu->lock);
2555 if (hw_pass_through && domain_type_is_si(domain))
2556 ret = intel_pasid_setup_pass_through(iommu, domain,
2557 dev, PASID_RID2PASID);
2558 else
2559 ret = intel_pasid_setup_second_level(iommu, domain,
2560 dev, PASID_RID2PASID);
2561 spin_unlock(&iommu->lock);
2562 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002563 dev_err(dev, "Setup RID2PASID failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002564 dmar_remove_one_dev_info(dev);
Lu Baoluef848b72018-12-10 09:59:01 +08002565 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002566 }
2567 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002568
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002569 if (dev && domain_context_mapping(domain, dev)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002570 dev_err(dev, "Domain context map failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002571 dmar_remove_one_dev_info(dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002572 return NULL;
2573 }
2574
David Woodhouseb718cd32014-03-09 13:11:33 -07002575 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002576}
2577
Alex Williamson579305f2014-07-03 09:51:43 -06002578static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2579{
2580 *(u16 *)opaque = alias;
2581 return 0;
2582}
2583
Joerg Roedel76208352016-08-25 14:25:12 +02002584static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002585{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002586 struct device_domain_info *info;
Joerg Roedel76208352016-08-25 14:25:12 +02002587 struct dmar_domain *domain = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002588 struct intel_iommu *iommu;
Lu Baolufcc35c62018-05-04 13:08:17 +08002589 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002590 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002591 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002592
David Woodhouse146922e2014-03-09 15:44:17 -07002593 iommu = device_to_iommu(dev, &bus, &devfn);
2594 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002595 return NULL;
2596
2597 if (dev_is_pci(dev)) {
2598 struct pci_dev *pdev = to_pci_dev(dev);
2599
2600 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2601
2602 spin_lock_irqsave(&device_domain_lock, flags);
2603 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2604 PCI_BUS_NUM(dma_alias),
2605 dma_alias & 0xff);
2606 if (info) {
2607 iommu = info->iommu;
2608 domain = info->domain;
2609 }
2610 spin_unlock_irqrestore(&device_domain_lock, flags);
2611
Joerg Roedel76208352016-08-25 14:25:12 +02002612 /* DMA alias already has a domain, use it */
Alex Williamson579305f2014-07-03 09:51:43 -06002613 if (info)
Joerg Roedel76208352016-08-25 14:25:12 +02002614 goto out;
Alex Williamson579305f2014-07-03 09:51:43 -06002615 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002616
David Woodhouse146922e2014-03-09 15:44:17 -07002617 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002618 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002619 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002620 return NULL;
Joerg Roedeldc534b22015-07-22 12:44:02 +02002621 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002622 domain_exit(domain);
2623 return NULL;
2624 }
2625
Joerg Roedel76208352016-08-25 14:25:12 +02002626out:
Alex Williamson579305f2014-07-03 09:51:43 -06002627
Joerg Roedel76208352016-08-25 14:25:12 +02002628 return domain;
2629}
2630
2631static struct dmar_domain *set_domain_for_dev(struct device *dev,
2632 struct dmar_domain *domain)
2633{
2634 struct intel_iommu *iommu;
2635 struct dmar_domain *tmp;
2636 u16 req_id, dma_alias;
2637 u8 bus, devfn;
2638
2639 iommu = device_to_iommu(dev, &bus, &devfn);
2640 if (!iommu)
2641 return NULL;
2642
2643 req_id = ((u16)bus << 8) | devfn;
2644
2645 if (dev_is_pci(dev)) {
2646 struct pci_dev *pdev = to_pci_dev(dev);
2647
2648 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2649
2650 /* register PCI DMA alias device */
2651 if (req_id != dma_alias) {
2652 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2653 dma_alias & 0xff, NULL, domain);
2654
2655 if (!tmp || tmp != domain)
2656 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002657 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002658 }
2659
Joerg Roedel5db31562015-07-22 12:40:43 +02002660 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
Joerg Roedel76208352016-08-25 14:25:12 +02002661 if (!tmp || tmp != domain)
2662 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002663
Joerg Roedel76208352016-08-25 14:25:12 +02002664 return domain;
2665}
2666
2667static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2668{
2669 struct dmar_domain *domain, *tmp;
2670
2671 domain = find_domain(dev);
2672 if (domain)
2673 goto out;
2674
2675 domain = find_or_alloc_domain(dev, gaw);
2676 if (!domain)
2677 goto out;
2678
2679 tmp = set_domain_for_dev(dev, domain);
2680 if (!tmp || domain != tmp) {
Alex Williamson579305f2014-07-03 09:51:43 -06002681 domain_exit(domain);
2682 domain = tmp;
2683 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002684
Joerg Roedel76208352016-08-25 14:25:12 +02002685out:
2686
David Woodhouseb718cd32014-03-09 13:11:33 -07002687 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002688}
2689
David Woodhouseb2132032009-06-26 18:50:28 +01002690static int iommu_domain_identity_map(struct dmar_domain *domain,
2691 unsigned long long start,
2692 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002693{
David Woodhousec5395d52009-06-28 16:35:56 +01002694 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2695 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002696
David Woodhousec5395d52009-06-28 16:35:56 +01002697 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2698 dma_to_mm_pfn(last_vpfn))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002699 pr_err("Reserving iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002700 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002701 }
2702
Joerg Roedelaf1089c2015-07-21 15:45:19 +02002703 pr_debug("Mapping reserved region %llx-%llx\n", start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002704 /*
2705 * RMRR range might have overlap with physical memory range,
2706 * clear it first
2707 */
David Woodhousec5395d52009-06-28 16:35:56 +01002708 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002709
Peter Xu87684fd2018-05-04 10:34:53 +08002710 return __domain_mapping(domain, first_vpfn, NULL,
2711 first_vpfn, last_vpfn - first_vpfn + 1,
2712 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002713}
2714
Joerg Roedeld66ce542015-09-23 19:00:10 +02002715static int domain_prepare_identity_map(struct device *dev,
2716 struct dmar_domain *domain,
2717 unsigned long long start,
2718 unsigned long long end)
David Woodhouseb2132032009-06-26 18:50:28 +01002719{
David Woodhouse19943b02009-08-04 16:19:20 +01002720 /* For _hardware_ passthrough, don't bother. But for software
2721 passthrough, we do it anyway -- it may indicate a memory
2722 range which is reserved in E820, so which didn't get set
2723 up to start with in si_domain */
2724 if (domain == si_domain && hw_pass_through) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002725 dev_warn(dev, "Ignoring identity map for HW passthrough [0x%Lx - 0x%Lx]\n",
2726 start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002727 return 0;
2728 }
2729
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002730 dev_info(dev, "Setting identity map [0x%Lx - 0x%Lx]\n", start, end);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002731
David Woodhouse5595b522009-12-02 09:21:55 +00002732 if (end < start) {
2733 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2734 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2735 dmi_get_system_info(DMI_BIOS_VENDOR),
2736 dmi_get_system_info(DMI_BIOS_VERSION),
2737 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002738 return -EIO;
David Woodhouse5595b522009-12-02 09:21:55 +00002739 }
2740
David Woodhouse2ff729f2009-08-26 14:25:41 +01002741 if (end >> agaw_to_width(domain->agaw)) {
2742 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2743 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2744 agaw_to_width(domain->agaw),
2745 dmi_get_system_info(DMI_BIOS_VENDOR),
2746 dmi_get_system_info(DMI_BIOS_VERSION),
2747 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002748 return -EIO;
David Woodhouse2ff729f2009-08-26 14:25:41 +01002749 }
David Woodhouse19943b02009-08-04 16:19:20 +01002750
Joerg Roedeld66ce542015-09-23 19:00:10 +02002751 return iommu_domain_identity_map(domain, start, end);
2752}
2753
2754static int iommu_prepare_identity_map(struct device *dev,
2755 unsigned long long start,
2756 unsigned long long end)
2757{
2758 struct dmar_domain *domain;
2759 int ret;
2760
2761 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
2762 if (!domain)
2763 return -ENOMEM;
2764
2765 ret = domain_prepare_identity_map(dev, domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002766 if (ret)
Joerg Roedeld66ce542015-09-23 19:00:10 +02002767 domain_exit(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002768
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002769 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002770}
2771
2772static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002773 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002774{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002775 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002776 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002777 return iommu_prepare_identity_map(dev, rmrr->base_address,
2778 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002779}
2780
Suresh Siddhad3f13812011-08-23 17:05:25 -07002781#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002782static inline void iommu_prepare_isa(void)
2783{
2784 struct pci_dev *pdev;
2785 int ret;
2786
2787 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2788 if (!pdev)
2789 return;
2790
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002791 pr_info("Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002792 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002793
2794 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002795 pr_err("Failed to create 0-16MiB identity map - floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002796
Yijing Wang9b27e822014-05-20 20:37:52 +08002797 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002798}
2799#else
2800static inline void iommu_prepare_isa(void)
2801{
2802 return;
2803}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002804#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002805
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002806static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002807
Matt Kraai071e1372009-08-23 22:30:22 -07002808static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002809{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002810 int nid, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002811
Jiang Liuab8dfe22014-07-11 14:19:27 +08002812 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002813 if (!si_domain)
2814 return -EFAULT;
2815
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002816 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2817 domain_exit(si_domain);
2818 return -EFAULT;
2819 }
2820
Joerg Roedel0dc79712015-07-21 15:40:06 +02002821 pr_debug("Identity mapping domain allocated\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002822
David Woodhouse19943b02009-08-04 16:19:20 +01002823 if (hw)
2824 return 0;
2825
David Woodhousec7ab48d2009-06-26 19:10:36 +01002826 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002827 unsigned long start_pfn, end_pfn;
2828 int i;
2829
2830 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2831 ret = iommu_domain_identity_map(si_domain,
2832 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2833 if (ret)
2834 return ret;
2835 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002836 }
2837
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002838 return 0;
2839}
2840
David Woodhouse9b226622014-03-09 14:03:28 -07002841static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002842{
2843 struct device_domain_info *info;
2844
2845 if (likely(!iommu_identity_mapping))
2846 return 0;
2847
David Woodhouse9b226622014-03-09 14:03:28 -07002848 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002849 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2850 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002851
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002852 return 0;
2853}
2854
Joerg Roedel28ccce02015-07-21 14:45:31 +02002855static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002856{
David Woodhouse0ac72662014-03-09 13:19:22 -07002857 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002858 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002859 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002860
David Woodhouse5913c9b2014-03-09 16:27:31 -07002861 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002862 if (!iommu)
2863 return -ENODEV;
2864
Joerg Roedel5db31562015-07-22 12:40:43 +02002865 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002866 if (ndomain != domain)
2867 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002868
2869 return 0;
2870}
2871
David Woodhouse0b9d9752014-03-09 15:48:15 -07002872static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002873{
2874 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002875 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002876 int i;
2877
Jiang Liu0e242612014-02-19 14:07:34 +08002878 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002879 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002880 /*
2881 * Return TRUE if this RMRR contains the device that
2882 * is passed in.
2883 */
2884 for_each_active_dev_scope(rmrr->devices,
2885 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002886 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002887 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002888 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002889 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002890 }
Jiang Liu0e242612014-02-19 14:07:34 +08002891 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002892 return false;
2893}
2894
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002895/*
2896 * There are a couple cases where we need to restrict the functionality of
2897 * devices associated with RMRRs. The first is when evaluating a device for
2898 * identity mapping because problems exist when devices are moved in and out
2899 * of domains and their respective RMRR information is lost. This means that
2900 * a device with associated RMRRs will never be in a "passthrough" domain.
2901 * The second is use of the device through the IOMMU API. This interface
2902 * expects to have full control of the IOVA space for the device. We cannot
2903 * satisfy both the requirement that RMRR access is maintained and have an
2904 * unencumbered IOVA space. We also have no ability to quiesce the device's
2905 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2906 * We therefore prevent devices associated with an RMRR from participating in
2907 * the IOMMU API, which eliminates them from device assignment.
2908 *
2909 * In both cases we assume that PCI USB devices with RMRRs have them largely
2910 * for historical reasons and that the RMRR space is not actively used post
2911 * boot. This exclusion may change if vendors begin to abuse it.
David Woodhouse18436af2015-03-25 15:05:47 +00002912 *
2913 * The same exception is made for graphics devices, with the requirement that
2914 * any use of the RMRR regions will be torn down before assigning the device
2915 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002916 */
2917static bool device_is_rmrr_locked(struct device *dev)
2918{
2919 if (!device_has_rmrr(dev))
2920 return false;
2921
2922 if (dev_is_pci(dev)) {
2923 struct pci_dev *pdev = to_pci_dev(dev);
2924
David Woodhouse18436af2015-03-25 15:05:47 +00002925 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002926 return false;
2927 }
2928
2929 return true;
2930}
2931
David Woodhouse3bdb2592014-03-09 16:03:08 -07002932static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002933{
David Woodhouse3bdb2592014-03-09 16:03:08 -07002934 if (dev_is_pci(dev)) {
2935 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002936
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002937 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002938 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002939
Lu Baolu89a60792018-10-23 15:45:01 +08002940 /*
2941 * Prevent any device marked as untrusted from getting
2942 * placed into the statically identity mapping domain.
2943 */
2944 if (pdev->untrusted)
2945 return 0;
2946
David Woodhouse3bdb2592014-03-09 16:03:08 -07002947 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2948 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002949
David Woodhouse3bdb2592014-03-09 16:03:08 -07002950 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2951 return 1;
2952
2953 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2954 return 0;
2955
2956 /*
2957 * We want to start off with all devices in the 1:1 domain, and
2958 * take them out later if we find they can't access all of memory.
2959 *
2960 * However, we can't do this for PCI devices behind bridges,
2961 * because all PCI devices behind the same bridge will end up
2962 * with the same source-id on their transactions.
2963 *
2964 * Practically speaking, we can't change things around for these
2965 * devices at run-time, because we can't be sure there'll be no
2966 * DMA transactions in flight for any of their siblings.
2967 *
2968 * So PCI devices (unless they're on the root bus) as well as
2969 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2970 * the 1:1 domain, just in _case_ one of their siblings turns out
2971 * not to be able to map all of memory.
2972 */
2973 if (!pci_is_pcie(pdev)) {
2974 if (!pci_is_root_bus(pdev->bus))
2975 return 0;
2976 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2977 return 0;
2978 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2979 return 0;
2980 } else {
2981 if (device_has_rmrr(dev))
2982 return 0;
2983 }
David Woodhouse6941af22009-07-04 18:24:27 +01002984
David Woodhouse3dfc8132009-07-04 19:11:08 +01002985 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002986 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002987 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002988 * take them out of the 1:1 domain later.
2989 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002990 if (!startup) {
2991 /*
2992 * If the device's dma_mask is less than the system's memory
2993 * size then this is not a candidate for identity mapping.
2994 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002995 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002996
David Woodhouse3bdb2592014-03-09 16:03:08 -07002997 if (dev->coherent_dma_mask &&
2998 dev->coherent_dma_mask < dma_mask)
2999 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05003000
David Woodhouse3bdb2592014-03-09 16:03:08 -07003001 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05003002 }
David Woodhouse6941af22009-07-04 18:24:27 +01003003
3004 return 1;
3005}
3006
David Woodhousecf04eee2014-03-21 16:49:04 +00003007static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
3008{
3009 int ret;
3010
3011 if (!iommu_should_identity_map(dev, 1))
3012 return 0;
3013
Joerg Roedel28ccce02015-07-21 14:45:31 +02003014 ret = domain_add_dev_info(si_domain, dev);
David Woodhousecf04eee2014-03-21 16:49:04 +00003015 if (!ret)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003016 dev_info(dev, "%s identity mapping\n",
3017 hw ? "Hardware" : "Software");
David Woodhousecf04eee2014-03-21 16:49:04 +00003018 else if (ret == -ENODEV)
3019 /* device not associated with an iommu */
3020 ret = 0;
3021
3022 return ret;
3023}
3024
3025
Matt Kraai071e1372009-08-23 22:30:22 -07003026static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003027{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003028 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00003029 struct dmar_drhd_unit *drhd;
Qian Caid3ed71e2019-05-31 22:30:49 -07003030 /* To avoid a -Wunused-but-set-variable warning. */
3031 struct intel_iommu *iommu __maybe_unused;
David Woodhousecf04eee2014-03-21 16:49:04 +00003032 struct device *dev;
3033 int i;
3034 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003035
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003036 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00003037 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
3038 if (ret)
3039 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003040 }
3041
David Woodhousecf04eee2014-03-21 16:49:04 +00003042 for_each_active_iommu(iommu, drhd)
3043 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
3044 struct acpi_device_physical_node *pn;
3045 struct acpi_device *adev;
3046
3047 if (dev->bus != &acpi_bus_type)
3048 continue;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003049
David Woodhousecf04eee2014-03-21 16:49:04 +00003050 adev= to_acpi_device(dev);
3051 mutex_lock(&adev->physical_node_lock);
3052 list_for_each_entry(pn, &adev->physical_node_list, node) {
3053 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
3054 if (ret)
3055 break;
3056 }
3057 mutex_unlock(&adev->physical_node_lock);
3058 if (ret)
3059 return ret;
3060 }
3061
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003062 return 0;
3063}
3064
Jiang Liuffebeb42014-11-09 22:48:02 +08003065static void intel_iommu_init_qi(struct intel_iommu *iommu)
3066{
3067 /*
3068 * Start from the sane iommu hardware state.
3069 * If the queued invalidation is already initialized by us
3070 * (for example, while enabling interrupt-remapping) then
3071 * we got the things already rolling from a sane state.
3072 */
3073 if (!iommu->qi) {
3074 /*
3075 * Clear any previous faults.
3076 */
3077 dmar_fault(-1, iommu);
3078 /*
3079 * Disable queued invalidation if supported and already enabled
3080 * before OS handover.
3081 */
3082 dmar_disable_qi(iommu);
3083 }
3084
3085 if (dmar_enable_qi(iommu)) {
3086 /*
3087 * Queued Invalidate not enabled, use Register Based Invalidate
3088 */
3089 iommu->flush.flush_context = __iommu_flush_context;
3090 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003091 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08003092 iommu->name);
3093 } else {
3094 iommu->flush.flush_context = qi_flush_context;
3095 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003096 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08003097 }
3098}
3099
Joerg Roedel091d42e2015-06-12 11:56:10 +02003100static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04003101 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02003102 struct context_entry **tbl,
3103 int bus, bool ext)
3104{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003105 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003106 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04003107 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003108 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003109 phys_addr_t old_ce_phys;
3110
3111 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04003112 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003113
3114 for (devfn = 0; devfn < 256; devfn++) {
3115 /* First calculate the correct index */
3116 idx = (ext ? devfn * 2 : devfn) % 256;
3117
3118 if (idx == 0) {
3119 /* First save what we may have and clean up */
3120 if (new_ce) {
3121 tbl[tbl_idx] = new_ce;
3122 __iommu_flush_cache(iommu, new_ce,
3123 VTD_PAGE_SIZE);
3124 pos = 1;
3125 }
3126
3127 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08003128 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003129
3130 ret = 0;
3131 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003132 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003133 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003134 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003135
3136 if (!old_ce_phys) {
3137 if (ext && devfn == 0) {
3138 /* No LCTP, try UCTP */
3139 devfn = 0x7f;
3140 continue;
3141 } else {
3142 goto out;
3143 }
3144 }
3145
3146 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003147 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3148 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003149 if (!old_ce)
3150 goto out;
3151
3152 new_ce = alloc_pgtable_page(iommu->node);
3153 if (!new_ce)
3154 goto out_unmap;
3155
3156 ret = 0;
3157 }
3158
3159 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003160 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003161
Joerg Roedelcf484d02015-06-12 12:21:46 +02003162 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003163 continue;
3164
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003165 did = context_domain_id(&ce);
3166 if (did >= 0 && did < cap_ndoms(iommu->cap))
3167 set_bit(did, iommu->domain_ids);
3168
Joerg Roedelcf484d02015-06-12 12:21:46 +02003169 /*
3170 * We need a marker for copied context entries. This
3171 * marker needs to work for the old format as well as
3172 * for extended context entries.
3173 *
3174 * Bit 67 of the context entry is used. In the old
3175 * format this bit is available to software, in the
3176 * extended format it is the PGE bit, but PGE is ignored
3177 * by HW if PASIDs are disabled (and thus still
3178 * available).
3179 *
3180 * So disable PASIDs first and then mark the entry
3181 * copied. This means that we don't copy PASID
3182 * translations from the old kernel, but this is fine as
3183 * faults there are not fatal.
3184 */
3185 context_clear_pasid_enable(&ce);
3186 context_set_copied(&ce);
3187
Joerg Roedel091d42e2015-06-12 11:56:10 +02003188 new_ce[idx] = ce;
3189 }
3190
3191 tbl[tbl_idx + pos] = new_ce;
3192
3193 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3194
3195out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003196 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003197
3198out:
3199 return ret;
3200}
3201
3202static int copy_translation_tables(struct intel_iommu *iommu)
3203{
3204 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003205 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003206 phys_addr_t old_rt_phys;
3207 int ctxt_table_entries;
3208 unsigned long flags;
3209 u64 rtaddr_reg;
3210 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003211 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003212
3213 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3214 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003215 new_ext = !!ecap_ecs(iommu->ecap);
3216
3217 /*
3218 * The RTT bit can only be changed when translation is disabled,
3219 * but disabling translation means to open a window for data
3220 * corruption. So bail out and don't copy anything if we would
3221 * have to change the bit.
3222 */
3223 if (new_ext != ext)
3224 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003225
3226 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3227 if (!old_rt_phys)
3228 return -EINVAL;
3229
Dan Williamsdfddb962015-10-09 18:16:46 -04003230 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003231 if (!old_rt)
3232 return -ENOMEM;
3233
3234 /* This is too big for the stack - allocate it from slab */
3235 ctxt_table_entries = ext ? 512 : 256;
3236 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003237 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003238 if (!ctxt_tbls)
3239 goto out_unmap;
3240
3241 for (bus = 0; bus < 256; bus++) {
3242 ret = copy_context_table(iommu, &old_rt[bus],
3243 ctxt_tbls, bus, ext);
3244 if (ret) {
3245 pr_err("%s: Failed to copy context table for bus %d\n",
3246 iommu->name, bus);
3247 continue;
3248 }
3249 }
3250
3251 spin_lock_irqsave(&iommu->lock, flags);
3252
3253 /* Context tables are copied, now write them to the root_entry table */
3254 for (bus = 0; bus < 256; bus++) {
3255 int idx = ext ? bus * 2 : bus;
3256 u64 val;
3257
3258 if (ctxt_tbls[idx]) {
3259 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3260 iommu->root_entry[bus].lo = val;
3261 }
3262
3263 if (!ext || !ctxt_tbls[idx + 1])
3264 continue;
3265
3266 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3267 iommu->root_entry[bus].hi = val;
3268 }
3269
3270 spin_unlock_irqrestore(&iommu->lock, flags);
3271
3272 kfree(ctxt_tbls);
3273
3274 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3275
3276 ret = 0;
3277
3278out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003279 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003280
3281 return ret;
3282}
3283
Joseph Cihulab7792602011-05-03 00:08:37 -07003284static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003285{
3286 struct dmar_drhd_unit *drhd;
3287 struct dmar_rmrr_unit *rmrr;
Joerg Roedela87f4912015-06-12 12:32:54 +02003288 bool copied_tables = false;
David Woodhouse832bd852014-03-07 15:08:36 +00003289 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003290 struct intel_iommu *iommu;
Joerg Roedel13cf0172017-08-11 11:40:10 +02003291 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003292
3293 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003294 * for each drhd
3295 * allocate root
3296 * initialize and program root entry to not present
3297 * endfor
3298 */
3299 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003300 /*
3301 * lock not needed as this is only incremented in the single
3302 * threaded kernel __init code path all other access are read
3303 * only
3304 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003305 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003306 g_num_of_iommus++;
3307 continue;
3308 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003309 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003310 }
3311
Jiang Liuffebeb42014-11-09 22:48:02 +08003312 /* Preallocate enough resources for IOMMU hot-addition */
3313 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3314 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3315
Weidong Hand9630fe2008-12-08 11:06:32 +08003316 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3317 GFP_KERNEL);
3318 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003319 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003320 ret = -ENOMEM;
3321 goto error;
3322 }
3323
Jiang Liu7c919772014-01-06 14:18:18 +08003324 for_each_active_iommu(iommu, drhd) {
Lu Baolu56283172018-07-14 15:46:54 +08003325 /*
3326 * Find the max pasid size of all IOMMU's in the system.
3327 * We need to ensure the system pasid table is no bigger
3328 * than the smallest supported.
3329 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003330 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003331 u32 temp = 2 << ecap_pss(iommu->ecap);
3332
3333 intel_pasid_max_id = min_t(u32, temp,
3334 intel_pasid_max_id);
3335 }
3336
Weidong Hand9630fe2008-12-08 11:06:32 +08003337 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003338
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003339 intel_iommu_init_qi(iommu);
3340
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003341 ret = iommu_init_domains(iommu);
3342 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003343 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003344
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003345 init_translation_status(iommu);
3346
Joerg Roedel091d42e2015-06-12 11:56:10 +02003347 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3348 iommu_disable_translation(iommu);
3349 clear_translation_pre_enabled(iommu);
3350 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3351 iommu->name);
3352 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003353
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003354 /*
3355 * TBD:
3356 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003357 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003358 */
3359 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003360 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003361 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003362
Joerg Roedel091d42e2015-06-12 11:56:10 +02003363 if (translation_pre_enabled(iommu)) {
3364 pr_info("Translation already enabled - trying to copy translation structures\n");
3365
3366 ret = copy_translation_tables(iommu);
3367 if (ret) {
3368 /*
3369 * We found the IOMMU with translation
3370 * enabled - but failed to copy over the
3371 * old root-entry table. Try to proceed
3372 * by disabling translation now and
3373 * allocating a clean root-entry table.
3374 * This might cause DMAR faults, but
3375 * probably the dump will still succeed.
3376 */
3377 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3378 iommu->name);
3379 iommu_disable_translation(iommu);
3380 clear_translation_pre_enabled(iommu);
3381 } else {
3382 pr_info("Copied translation tables from previous kernel for %s\n",
3383 iommu->name);
Joerg Roedela87f4912015-06-12 12:32:54 +02003384 copied_tables = true;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003385 }
3386 }
3387
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003388 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003389 hw_pass_through = 0;
David Woodhouse8a94ade2015-03-24 14:54:56 +00003390#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003391 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08003392 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00003393#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003394 }
3395
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003396 /*
3397 * Now that qi is enabled on all iommus, set the root entry and flush
3398 * caches. This is required on some Intel X58 chipsets, otherwise the
3399 * flush_context function will loop forever and the boot hangs.
3400 */
3401 for_each_active_iommu(iommu, drhd) {
3402 iommu_flush_write_buffer(iommu);
3403 iommu_set_root_entry(iommu);
3404 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3405 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3406 }
3407
David Woodhouse19943b02009-08-04 16:19:20 +01003408 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07003409 iommu_identity_mapping |= IDENTMAP_ALL;
3410
Suresh Siddhad3f13812011-08-23 17:05:25 -07003411#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
Lu Baolu5daab582019-05-02 09:34:26 +08003412 dmar_map_gfx = 0;
David Woodhouse19943b02009-08-04 16:19:20 +01003413#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003414
Lu Baolu5daab582019-05-02 09:34:26 +08003415 if (!dmar_map_gfx)
3416 iommu_identity_mapping |= IDENTMAP_GFX;
3417
Ashok Raj21e722c2017-01-30 09:39:53 -08003418 check_tylersburg_isoch();
3419
Joerg Roedel86080cc2015-06-12 12:27:16 +02003420 if (iommu_identity_mapping) {
3421 ret = si_domain_init(hw_pass_through);
3422 if (ret)
3423 goto free_iommu;
3424 }
3425
David Woodhousee0fc7e02009-09-30 09:12:17 -07003426
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003427 /*
Joerg Roedela87f4912015-06-12 12:32:54 +02003428 * If we copied translations from a previous kernel in the kdump
3429 * case, we can not assign the devices to domains now, as that
3430 * would eliminate the old mappings. So skip this part and defer
3431 * the assignment to device driver initialization time.
3432 */
3433 if (copied_tables)
3434 goto domains_done;
3435
3436 /*
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003437 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003438 * identity mappings for rmrr, gfx, and isa and may fall back to static
3439 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003440 */
David Woodhouse19943b02009-08-04 16:19:20 +01003441 if (iommu_identity_mapping) {
3442 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
3443 if (ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003444 pr_crit("Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08003445 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003446 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003447 }
David Woodhouse19943b02009-08-04 16:19:20 +01003448 /*
3449 * For each rmrr
3450 * for each dev attached to rmrr
3451 * do
3452 * locate drhd for dev, alloc domain for dev
3453 * allocate free domain
3454 * allocate page table entries for rmrr
3455 * if context not allocated for bus
3456 * allocate and init context
3457 * set present in root table for this bus
3458 * init context with domain, translation etc
3459 * endfor
3460 * endfor
3461 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003462 pr_info("Setting RMRR:\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003463 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08003464 /* some BIOS lists non-exist devices in DMAR table. */
3465 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00003466 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07003467 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01003468 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003469 pr_err("Mapping reserved region failed\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003470 }
3471 }
3472
3473 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07003474
Joerg Roedela87f4912015-06-12 12:32:54 +02003475domains_done:
3476
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003477 /*
3478 * for each drhd
3479 * enable fault log
3480 * global invalidate context cache
3481 * global invalidate iotlb
3482 * enable translation
3483 */
Jiang Liu7c919772014-01-06 14:18:18 +08003484 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003485 if (drhd->ignored) {
3486 /*
3487 * we always have to disable PMRs or DMA may fail on
3488 * this device
3489 */
3490 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003491 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003492 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003493 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003494
3495 iommu_flush_write_buffer(iommu);
3496
David Woodhousea222a7f2015-10-07 23:35:18 +01003497#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003498 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
Lu Baolua7755c32019-04-19 14:43:29 +08003499 /*
3500 * Call dmar_alloc_hwirq() with dmar_global_lock held,
3501 * could cause possible lock race condition.
3502 */
3503 up_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003504 ret = intel_svm_enable_prq(iommu);
Lu Baolua7755c32019-04-19 14:43:29 +08003505 down_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003506 if (ret)
3507 goto free_iommu;
3508 }
3509#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003510 ret = dmar_set_interrupt(iommu);
3511 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003512 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003513
Joerg Roedel8939ddf2015-06-12 14:40:01 +02003514 if (!translation_pre_enabled(iommu))
3515 iommu_enable_translation(iommu);
3516
David Woodhouseb94996c2009-09-19 15:28:12 -07003517 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003518 }
3519
3520 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003521
3522free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003523 for_each_active_iommu(iommu, drhd) {
3524 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003525 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003526 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003527
Weidong Hand9630fe2008-12-08 11:06:32 +08003528 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003529
Jiang Liu989d51f2014-02-19 14:07:21 +08003530error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003531 return ret;
3532}
3533
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003534/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003535static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003536 struct dmar_domain *domain,
3537 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003538{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06003539 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003540
David Woodhouse875764d2009-06-28 21:20:51 +01003541 /* Restrict dma_mask to the width that the iommu can handle */
3542 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
Robin Murphy8f6429c2015-07-16 19:40:12 +01003543 /* Ensure we reserve the whole size-aligned region */
3544 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003545
3546 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003547 /*
3548 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003549 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003550 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003551 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003552 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003553 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003554 if (iova_pfn)
3555 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003556 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003557 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3558 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003559 if (unlikely(!iova_pfn)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003560 dev_err(dev, "Allocating %ld-page iova failed", nrpages);
Omer Peleg2aac6302016-04-20 11:33:57 +03003561 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003562 }
3563
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003564 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003565}
3566
Lu Baolu9ddbfb42018-07-14 15:46:57 +08003567struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003568{
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003569 struct dmar_domain *domain, *tmp;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003570 struct dmar_rmrr_unit *rmrr;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003571 struct device *i_dev;
3572 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003573
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003574 domain = find_domain(dev);
3575 if (domain)
3576 goto out;
3577
3578 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3579 if (!domain)
3580 goto out;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003581
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003582 /* We have a new domain - setup possible RMRRs for the device */
3583 rcu_read_lock();
3584 for_each_rmrr_units(rmrr) {
3585 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3586 i, i_dev) {
3587 if (i_dev != dev)
3588 continue;
3589
3590 ret = domain_prepare_identity_map(dev, domain,
3591 rmrr->base_address,
3592 rmrr->end_address);
3593 if (ret)
3594 dev_err(dev, "Mapping reserved region failed\n");
3595 }
3596 }
3597 rcu_read_unlock();
3598
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003599 tmp = set_domain_for_dev(dev, domain);
3600 if (!tmp || domain != tmp) {
3601 domain_exit(domain);
3602 domain = tmp;
3603 }
3604
3605out:
3606
3607 if (!domain)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003608 dev_err(dev, "Allocating domain failed\n");
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003609
3610
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003611 return domain;
3612}
3613
David Woodhouseecb509e2014-03-09 16:29:55 -07003614/* Check if the dev needs to go through non-identity map and unmap process.*/
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003615static bool iommu_need_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003616{
3617 int found;
3618
David Woodhouse3d891942014-03-06 15:59:26 +00003619 if (iommu_dummy(dev))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003620 return false;
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003621
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003622 if (!iommu_identity_mapping)
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003623 return true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003624
David Woodhouse9b226622014-03-09 14:03:28 -07003625 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003626 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07003627 if (iommu_should_identity_map(dev, 0))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003628 return false;
3629
3630 /*
3631 * 32 bit DMA is removed from si_domain and fall back to
3632 * non-identity mapping.
3633 */
3634 dmar_remove_one_dev_info(dev);
3635 dev_info(dev, "32bit DMA uses non-identity mapping\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003636 } else {
3637 /*
3638 * In case of a detached 64 bit DMA device from vm, the device
3639 * is put into si_domain for identity mapping.
3640 */
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003641 if (iommu_should_identity_map(dev, 0) &&
3642 !domain_add_dev_info(si_domain, dev)) {
3643 dev_info(dev, "64bit DMA uses identity mapping\n");
3644 return false;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003645 }
3646 }
3647
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003648 return true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003649}
3650
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003651static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3652 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003653{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003654 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003655 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003656 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003657 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003658 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003659 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003660 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003661
3662 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003663
David Woodhouse5040a912014-03-09 16:14:00 -07003664 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003665 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003666 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003667
Weidong Han8c11e792008-12-08 15:29:22 +08003668 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003669 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003670
Omer Peleg2aac6302016-04-20 11:33:57 +03003671 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3672 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003673 goto error;
3674
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003675 /*
3676 * Check if DMAR supports zero-length reads on write only
3677 * mappings..
3678 */
3679 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003680 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003681 prot |= DMA_PTE_READ;
3682 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3683 prot |= DMA_PTE_WRITE;
3684 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003685 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003686 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003687 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003688 * is not a big problem
3689 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003690 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003691 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003692 if (ret)
3693 goto error;
3694
Omer Peleg2aac6302016-04-20 11:33:57 +03003695 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003696 start_paddr += paddr & ~PAGE_MASK;
3697 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003698
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003699error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003700 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003701 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003702 dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n",
3703 size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003704 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003705}
3706
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003707static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3708 unsigned long offset, size_t size,
3709 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003710 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003711{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003712 if (iommu_need_mapping(dev))
3713 return __intel_map_single(dev, page_to_phys(page) + offset,
3714 size, dir, *dev->dma_mask);
3715 return dma_direct_map_page(dev, page, offset, size, dir, attrs);
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003716}
3717
3718static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3719 size_t size, enum dma_data_direction dir,
3720 unsigned long attrs)
3721{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003722 if (iommu_need_mapping(dev))
3723 return __intel_map_single(dev, phys_addr, size, dir,
3724 *dev->dma_mask);
3725 return dma_direct_map_resource(dev, phys_addr, size, dir, attrs);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003726}
3727
Omer Peleg769530e2016-04-20 11:33:25 +03003728static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003730 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003731 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003732 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003733 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003734 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003735 struct page *freelist;
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003736 struct pci_dev *pdev = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003737
David Woodhouse1525a292014-03-06 16:19:30 +00003738 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003739 BUG_ON(!domain);
3740
Weidong Han8c11e792008-12-08 15:29:22 +08003741 iommu = domain_get_iommu(domain);
3742
Omer Peleg2aac6302016-04-20 11:33:57 +03003743 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003744
Omer Peleg769530e2016-04-20 11:33:25 +03003745 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003746 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003747 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003748
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003749 if (dev_is_pci(dev))
3750 pdev = to_pci_dev(dev);
3751
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003752 dev_dbg(dev, "Device unmapping: pfn %lx-%lx\n", start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003753
David Woodhouseea8ea462014-03-05 17:09:32 +00003754 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003755
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003756 if (intel_iommu_strict || (pdev && pdev->untrusted)) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003757 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003758 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003759 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003760 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003761 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003762 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003763 queue_iova(&domain->iovad, iova_pfn, nrpages,
3764 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003765 /*
3766 * queue up the release of the unmap to save the 1/6th of the
3767 * cpu used up by the iotlb flush operation...
3768 */
mark gross5e0d2a62008-03-04 15:22:08 -08003769 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003770}
3771
Jiang Liud41a4ad2014-07-11 14:19:34 +08003772static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3773 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003774 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003775{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003776 if (iommu_need_mapping(dev))
3777 intel_unmap(dev, dev_addr, size);
3778 else
3779 dma_direct_unmap_page(dev, dev_addr, size, dir, attrs);
3780}
3781
3782static void intel_unmap_resource(struct device *dev, dma_addr_t dev_addr,
3783 size_t size, enum dma_data_direction dir, unsigned long attrs)
3784{
3785 if (iommu_need_mapping(dev))
3786 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003787}
3788
David Woodhouse5040a912014-03-09 16:14:00 -07003789static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003790 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003791 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003792{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003793 struct page *page = NULL;
3794 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003795
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003796 if (!iommu_need_mapping(dev))
3797 return dma_direct_alloc(dev, size, dma_handle, flags, attrs);
3798
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003799 size = PAGE_ALIGN(size);
3800 order = get_order(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003801
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003802 if (gfpflags_allow_blocking(flags)) {
3803 unsigned int count = size >> PAGE_SHIFT;
3804
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003805 page = dma_alloc_from_contiguous(dev, count, order,
3806 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003807 }
3808
3809 if (!page)
3810 page = alloc_pages(flags, order);
3811 if (!page)
3812 return NULL;
3813 memset(page_address(page), 0, size);
3814
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003815 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3816 DMA_BIDIRECTIONAL,
3817 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003818 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003819 return page_address(page);
3820 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3821 __free_pages(page, order);
3822
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003823 return NULL;
3824}
3825
David Woodhouse5040a912014-03-09 16:14:00 -07003826static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003827 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003828{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003829 int order;
3830 struct page *page = virt_to_page(vaddr);
3831
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003832 if (!iommu_need_mapping(dev))
3833 return dma_direct_free(dev, size, vaddr, dma_handle, attrs);
3834
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003835 size = PAGE_ALIGN(size);
3836 order = get_order(size);
3837
3838 intel_unmap(dev, dma_handle, size);
3839 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3840 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003841}
3842
David Woodhouse5040a912014-03-09 16:14:00 -07003843static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003844 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003845 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003846{
Omer Peleg769530e2016-04-20 11:33:25 +03003847 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3848 unsigned long nrpages = 0;
3849 struct scatterlist *sg;
3850 int i;
3851
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003852 if (!iommu_need_mapping(dev))
3853 return dma_direct_unmap_sg(dev, sglist, nelems, dir, attrs);
3854
Omer Peleg769530e2016-04-20 11:33:25 +03003855 for_each_sg(sglist, sg, nelems, i) {
3856 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3857 }
3858
3859 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003860}
3861
David Woodhouse5040a912014-03-09 16:14:00 -07003862static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003863 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003864{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003865 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003866 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003867 size_t size = 0;
3868 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003869 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003870 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003871 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003872 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003873 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003874
3875 BUG_ON(dir == DMA_NONE);
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003876 if (!iommu_need_mapping(dev))
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003877 return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003878
David Woodhouse5040a912014-03-09 16:14:00 -07003879 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003880 if (!domain)
3881 return 0;
3882
Weidong Han8c11e792008-12-08 15:29:22 +08003883 iommu = domain_get_iommu(domain);
3884
David Woodhouseb536d242009-06-28 14:49:31 +01003885 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003886 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003887
Omer Peleg2aac6302016-04-20 11:33:57 +03003888 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003889 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003890 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003891 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003892 return 0;
3893 }
3894
3895 /*
3896 * Check if DMAR supports zero-length reads on write only
3897 * mappings..
3898 */
3899 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003900 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003901 prot |= DMA_PTE_READ;
3902 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3903 prot |= DMA_PTE_WRITE;
3904
Omer Peleg2aac6302016-04-20 11:33:57 +03003905 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003906
Fenghua Yuf5329592009-08-04 15:09:37 -07003907 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003908 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003909 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003910 start_vpfn + size - 1,
3911 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003912 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003913 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003914 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003915
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003916 return nelems;
3917}
3918
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003919static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003920 .alloc = intel_alloc_coherent,
3921 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003922 .map_sg = intel_map_sg,
3923 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003924 .map_page = intel_map_page,
3925 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003926 .map_resource = intel_map_resource,
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003927 .unmap_resource = intel_unmap_resource,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003928 .dma_supported = dma_direct_supported,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003929};
3930
3931static inline int iommu_domain_cache_init(void)
3932{
3933 int ret = 0;
3934
3935 iommu_domain_cache = kmem_cache_create("iommu_domain",
3936 sizeof(struct dmar_domain),
3937 0,
3938 SLAB_HWCACHE_ALIGN,
3939
3940 NULL);
3941 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003942 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003943 ret = -ENOMEM;
3944 }
3945
3946 return ret;
3947}
3948
3949static inline int iommu_devinfo_cache_init(void)
3950{
3951 int ret = 0;
3952
3953 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3954 sizeof(struct device_domain_info),
3955 0,
3956 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003957 NULL);
3958 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003959 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003960 ret = -ENOMEM;
3961 }
3962
3963 return ret;
3964}
3965
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003966static int __init iommu_init_mempool(void)
3967{
3968 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003969 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003970 if (ret)
3971 return ret;
3972
3973 ret = iommu_domain_cache_init();
3974 if (ret)
3975 goto domain_error;
3976
3977 ret = iommu_devinfo_cache_init();
3978 if (!ret)
3979 return ret;
3980
3981 kmem_cache_destroy(iommu_domain_cache);
3982domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003983 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003984
3985 return -ENOMEM;
3986}
3987
3988static void __init iommu_exit_mempool(void)
3989{
3990 kmem_cache_destroy(iommu_devinfo_cache);
3991 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003992 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003993}
3994
Dan Williams556ab452010-07-23 15:47:56 -07003995static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3996{
3997 struct dmar_drhd_unit *drhd;
3998 u32 vtbar;
3999 int rc;
4000
4001 /* We know that this device on this chipset has its own IOMMU.
4002 * If we find it under a different IOMMU, then the BIOS is lying
4003 * to us. Hope that the IOMMU for this device is actually
4004 * disabled, and it needs no translation...
4005 */
4006 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
4007 if (rc) {
4008 /* "can't" happen */
4009 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
4010 return;
4011 }
4012 vtbar &= 0xffff0000;
4013
4014 /* we know that the this iommu should be at offset 0xa000 from vtbar */
4015 drhd = dmar_find_matched_drhd_unit(pdev);
4016 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
4017 TAINT_FIRMWARE_WORKAROUND,
4018 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
4019 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
4020}
4021DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
4022
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004023static void __init init_no_remapping_devices(void)
4024{
4025 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004026 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004027 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004028
4029 for_each_drhd_unit(drhd) {
4030 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004031 for_each_active_dev_scope(drhd->devices,
4032 drhd->devices_cnt, i, dev)
4033 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004034 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004035 if (i == drhd->devices_cnt)
4036 drhd->ignored = 1;
4037 }
4038 }
4039
Jiang Liu7c919772014-01-06 14:18:18 +08004040 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004041 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004042 continue;
4043
Jiang Liub683b232014-02-19 14:07:32 +08004044 for_each_active_dev_scope(drhd->devices,
4045 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004046 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004047 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004048 if (i < drhd->devices_cnt)
4049 continue;
4050
David Woodhousec0771df2011-10-14 20:59:46 +01004051 /* This IOMMU has *only* gfx devices. Either bypass it or
4052 set the gfx_mapped flag, as appropriate */
Lu Baolucf1ec452019-05-02 09:34:25 +08004053 if (!dmar_map_gfx) {
David Woodhousec0771df2011-10-14 20:59:46 +01004054 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08004055 for_each_active_dev_scope(drhd->devices,
4056 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004057 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004058 }
4059 }
4060}
4061
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004062#ifdef CONFIG_SUSPEND
4063static int init_iommu_hw(void)
4064{
4065 struct dmar_drhd_unit *drhd;
4066 struct intel_iommu *iommu = NULL;
4067
4068 for_each_active_iommu(iommu, drhd)
4069 if (iommu->qi)
4070 dmar_reenable_qi(iommu);
4071
Joseph Cihulab7792602011-05-03 00:08:37 -07004072 for_each_iommu(iommu, drhd) {
4073 if (drhd->ignored) {
4074 /*
4075 * we always have to disable PMRs or DMA may fail on
4076 * this device
4077 */
4078 if (force_on)
4079 iommu_disable_protect_mem_regions(iommu);
4080 continue;
4081 }
Lu Baolu095303e2019-04-29 09:16:02 +08004082
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004083 iommu_flush_write_buffer(iommu);
4084
4085 iommu_set_root_entry(iommu);
4086
4087 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004088 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004089 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4090 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004091 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004092 }
4093
4094 return 0;
4095}
4096
4097static void iommu_flush_all(void)
4098{
4099 struct dmar_drhd_unit *drhd;
4100 struct intel_iommu *iommu;
4101
4102 for_each_active_iommu(iommu, drhd) {
4103 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004104 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004105 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004106 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004107 }
4108}
4109
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004110static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004111{
4112 struct dmar_drhd_unit *drhd;
4113 struct intel_iommu *iommu = NULL;
4114 unsigned long flag;
4115
4116 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004117 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004118 GFP_ATOMIC);
4119 if (!iommu->iommu_state)
4120 goto nomem;
4121 }
4122
4123 iommu_flush_all();
4124
4125 for_each_active_iommu(iommu, drhd) {
4126 iommu_disable_translation(iommu);
4127
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004128 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004129
4130 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4131 readl(iommu->reg + DMAR_FECTL_REG);
4132 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4133 readl(iommu->reg + DMAR_FEDATA_REG);
4134 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4135 readl(iommu->reg + DMAR_FEADDR_REG);
4136 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4137 readl(iommu->reg + DMAR_FEUADDR_REG);
4138
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004139 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004140 }
4141 return 0;
4142
4143nomem:
4144 for_each_active_iommu(iommu, drhd)
4145 kfree(iommu->iommu_state);
4146
4147 return -ENOMEM;
4148}
4149
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004150static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004151{
4152 struct dmar_drhd_unit *drhd;
4153 struct intel_iommu *iommu = NULL;
4154 unsigned long flag;
4155
4156 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004157 if (force_on)
4158 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4159 else
4160 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004161 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004162 }
4163
4164 for_each_active_iommu(iommu, drhd) {
4165
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004166 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004167
4168 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4169 iommu->reg + DMAR_FECTL_REG);
4170 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4171 iommu->reg + DMAR_FEDATA_REG);
4172 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4173 iommu->reg + DMAR_FEADDR_REG);
4174 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4175 iommu->reg + DMAR_FEUADDR_REG);
4176
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004177 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004178 }
4179
4180 for_each_active_iommu(iommu, drhd)
4181 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004182}
4183
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004184static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004185 .resume = iommu_resume,
4186 .suspend = iommu_suspend,
4187};
4188
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004189static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004190{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004191 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004192}
4193
4194#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004195static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004196#endif /* CONFIG_PM */
4197
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004198
Jiang Liuc2a0b532014-11-09 22:47:56 +08004199int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004200{
4201 struct acpi_dmar_reserved_memory *rmrr;
Eric Auger0659b8d2017-01-19 20:57:53 +00004202 int prot = DMA_PTE_READ|DMA_PTE_WRITE;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004203 struct dmar_rmrr_unit *rmrru;
Eric Auger0659b8d2017-01-19 20:57:53 +00004204 size_t length;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004205
4206 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4207 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004208 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004209
4210 rmrru->hdr = header;
4211 rmrr = (struct acpi_dmar_reserved_memory *)header;
4212 rmrru->base_address = rmrr->base_address;
4213 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004214
4215 length = rmrr->end_address - rmrr->base_address + 1;
4216 rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
4217 IOMMU_RESV_DIRECT);
4218 if (!rmrru->resv)
4219 goto free_rmrru;
4220
Jiang Liu2e455282014-02-19 14:07:36 +08004221 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4222 ((void *)rmrr) + rmrr->header.length,
4223 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004224 if (rmrru->devices_cnt && rmrru->devices == NULL)
4225 goto free_all;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004226
Jiang Liu2e455282014-02-19 14:07:36 +08004227 list_add(&rmrru->list, &dmar_rmrr_units);
4228
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004229 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004230free_all:
4231 kfree(rmrru->resv);
4232free_rmrru:
4233 kfree(rmrru);
4234out:
4235 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004236}
4237
Jiang Liu6b197242014-11-09 22:47:58 +08004238static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4239{
4240 struct dmar_atsr_unit *atsru;
4241 struct acpi_dmar_atsr *tmp;
4242
4243 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4244 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4245 if (atsr->segment != tmp->segment)
4246 continue;
4247 if (atsr->header.length != tmp->header.length)
4248 continue;
4249 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4250 return atsru;
4251 }
4252
4253 return NULL;
4254}
4255
4256int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004257{
4258 struct acpi_dmar_atsr *atsr;
4259 struct dmar_atsr_unit *atsru;
4260
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004261 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004262 return 0;
4263
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004264 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004265 atsru = dmar_find_atsr(atsr);
4266 if (atsru)
4267 return 0;
4268
4269 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004270 if (!atsru)
4271 return -ENOMEM;
4272
Jiang Liu6b197242014-11-09 22:47:58 +08004273 /*
4274 * If memory is allocated from slab by ACPI _DSM method, we need to
4275 * copy the memory content because the memory buffer will be freed
4276 * on return.
4277 */
4278 atsru->hdr = (void *)(atsru + 1);
4279 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004280 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004281 if (!atsru->include_all) {
4282 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4283 (void *)atsr + atsr->header.length,
4284 &atsru->devices_cnt);
4285 if (atsru->devices_cnt && atsru->devices == NULL) {
4286 kfree(atsru);
4287 return -ENOMEM;
4288 }
4289 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004290
Jiang Liu0e242612014-02-19 14:07:34 +08004291 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004292
4293 return 0;
4294}
4295
Jiang Liu9bdc5312014-01-06 14:18:27 +08004296static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4297{
4298 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4299 kfree(atsru);
4300}
4301
Jiang Liu6b197242014-11-09 22:47:58 +08004302int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4303{
4304 struct acpi_dmar_atsr *atsr;
4305 struct dmar_atsr_unit *atsru;
4306
4307 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4308 atsru = dmar_find_atsr(atsr);
4309 if (atsru) {
4310 list_del_rcu(&atsru->list);
4311 synchronize_rcu();
4312 intel_iommu_free_atsr(atsru);
4313 }
4314
4315 return 0;
4316}
4317
4318int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4319{
4320 int i;
4321 struct device *dev;
4322 struct acpi_dmar_atsr *atsr;
4323 struct dmar_atsr_unit *atsru;
4324
4325 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4326 atsru = dmar_find_atsr(atsr);
4327 if (!atsru)
4328 return 0;
4329
Linus Torvalds194dc872016-07-27 20:03:31 -07004330 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004331 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4332 i, dev)
4333 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004334 }
Jiang Liu6b197242014-11-09 22:47:58 +08004335
4336 return 0;
4337}
4338
Jiang Liuffebeb42014-11-09 22:48:02 +08004339static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4340{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004341 int sp, ret;
Jiang Liuffebeb42014-11-09 22:48:02 +08004342 struct intel_iommu *iommu = dmaru->iommu;
4343
4344 if (g_iommus[iommu->seq_id])
4345 return 0;
4346
4347 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004348 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004349 iommu->name);
4350 return -ENXIO;
4351 }
4352 if (!ecap_sc_support(iommu->ecap) &&
4353 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004354 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004355 iommu->name);
4356 return -ENXIO;
4357 }
4358 sp = domain_update_iommu_superpage(iommu) - 1;
4359 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004360 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004361 iommu->name);
4362 return -ENXIO;
4363 }
4364
4365 /*
4366 * Disable translation if already enabled prior to OS handover.
4367 */
4368 if (iommu->gcmd & DMA_GCMD_TE)
4369 iommu_disable_translation(iommu);
4370
4371 g_iommus[iommu->seq_id] = iommu;
4372 ret = iommu_init_domains(iommu);
4373 if (ret == 0)
4374 ret = iommu_alloc_root_entry(iommu);
4375 if (ret)
4376 goto out;
4377
David Woodhouse8a94ade2015-03-24 14:54:56 +00004378#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004379 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08004380 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004381#endif
4382
Jiang Liuffebeb42014-11-09 22:48:02 +08004383 if (dmaru->ignored) {
4384 /*
4385 * we always have to disable PMRs or DMA may fail on this device
4386 */
4387 if (force_on)
4388 iommu_disable_protect_mem_regions(iommu);
4389 return 0;
4390 }
4391
4392 intel_iommu_init_qi(iommu);
4393 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004394
4395#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004396 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004397 ret = intel_svm_enable_prq(iommu);
4398 if (ret)
4399 goto disable_iommu;
4400 }
4401#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004402 ret = dmar_set_interrupt(iommu);
4403 if (ret)
4404 goto disable_iommu;
4405
4406 iommu_set_root_entry(iommu);
4407 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4408 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4409 iommu_enable_translation(iommu);
4410
Jiang Liuffebeb42014-11-09 22:48:02 +08004411 iommu_disable_protect_mem_regions(iommu);
4412 return 0;
4413
4414disable_iommu:
4415 disable_dmar_iommu(iommu);
4416out:
4417 free_dmar_iommu(iommu);
4418 return ret;
4419}
4420
Jiang Liu6b197242014-11-09 22:47:58 +08004421int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4422{
Jiang Liuffebeb42014-11-09 22:48:02 +08004423 int ret = 0;
4424 struct intel_iommu *iommu = dmaru->iommu;
4425
4426 if (!intel_iommu_enabled)
4427 return 0;
4428 if (iommu == NULL)
4429 return -EINVAL;
4430
4431 if (insert) {
4432 ret = intel_iommu_add(dmaru);
4433 } else {
4434 disable_dmar_iommu(iommu);
4435 free_dmar_iommu(iommu);
4436 }
4437
4438 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004439}
4440
Jiang Liu9bdc5312014-01-06 14:18:27 +08004441static void intel_iommu_free_dmars(void)
4442{
4443 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4444 struct dmar_atsr_unit *atsru, *atsr_n;
4445
4446 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4447 list_del(&rmrru->list);
4448 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004449 kfree(rmrru->resv);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004450 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004451 }
4452
Jiang Liu9bdc5312014-01-06 14:18:27 +08004453 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4454 list_del(&atsru->list);
4455 intel_iommu_free_atsr(atsru);
4456 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004457}
4458
4459int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4460{
Jiang Liub683b232014-02-19 14:07:32 +08004461 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004462 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004463 struct pci_dev *bridge = NULL;
4464 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004465 struct acpi_dmar_atsr *atsr;
4466 struct dmar_atsr_unit *atsru;
4467
4468 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004469 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004470 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004471 /* If it's an integrated device, allow ATS */
4472 if (!bridge)
4473 return 1;
4474 /* Connected via non-PCIe: no ATS */
4475 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004476 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004477 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004478 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004479 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004480 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004481 }
4482
Jiang Liu0e242612014-02-19 14:07:34 +08004483 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004484 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4485 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4486 if (atsr->segment != pci_domain_nr(dev->bus))
4487 continue;
4488
Jiang Liub683b232014-02-19 14:07:32 +08004489 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004490 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004491 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004492
4493 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004494 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004495 }
Jiang Liub683b232014-02-19 14:07:32 +08004496 ret = 0;
4497out:
Jiang Liu0e242612014-02-19 14:07:34 +08004498 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004499
Jiang Liub683b232014-02-19 14:07:32 +08004500 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004501}
4502
Jiang Liu59ce0512014-02-19 14:07:35 +08004503int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4504{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004505 int ret;
Jiang Liu59ce0512014-02-19 14:07:35 +08004506 struct dmar_rmrr_unit *rmrru;
4507 struct dmar_atsr_unit *atsru;
4508 struct acpi_dmar_atsr *atsr;
4509 struct acpi_dmar_reserved_memory *rmrr;
4510
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004511 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004512 return 0;
4513
4514 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4515 rmrr = container_of(rmrru->hdr,
4516 struct acpi_dmar_reserved_memory, header);
4517 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4518 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4519 ((void *)rmrr) + rmrr->header.length,
4520 rmrr->segment, rmrru->devices,
4521 rmrru->devices_cnt);
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004522 if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004523 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004524 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004525 dmar_remove_dev_scope(info, rmrr->segment,
4526 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004527 }
4528 }
4529
4530 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4531 if (atsru->include_all)
4532 continue;
4533
4534 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4535 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4536 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4537 (void *)atsr + atsr->header.length,
4538 atsr->segment, atsru->devices,
4539 atsru->devices_cnt);
4540 if (ret > 0)
4541 break;
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004542 else if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004543 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004544 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004545 if (dmar_remove_dev_scope(info, atsr->segment,
4546 atsru->devices, atsru->devices_cnt))
4547 break;
4548 }
4549 }
4550
4551 return 0;
4552}
4553
Fenghua Yu99dcade2009-11-11 07:23:06 -08004554/*
4555 * Here we only respond to action of unbound device from driver.
4556 *
4557 * Added device is not attached to its DMAR domain here yet. That will happen
4558 * when mapping the device to iova.
4559 */
4560static int device_notifier(struct notifier_block *nb,
4561 unsigned long action, void *data)
4562{
4563 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004564 struct dmar_domain *domain;
4565
David Woodhouse3d891942014-03-06 15:59:26 +00004566 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004567 return 0;
4568
Lu Baolu117266f2019-02-25 10:46:36 +08004569 if (action == BUS_NOTIFY_REMOVED_DEVICE) {
4570 domain = find_domain(dev);
4571 if (!domain)
4572 return 0;
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004573
Lu Baolu117266f2019-02-25 10:46:36 +08004574 dmar_remove_one_dev_info(dev);
4575 if (!domain_type_is_vm_or_si(domain) &&
4576 list_empty(&domain->devices))
4577 domain_exit(domain);
4578 } else if (action == BUS_NOTIFY_ADD_DEVICE) {
4579 if (iommu_should_identity_map(dev, 1))
4580 domain_add_dev_info(si_domain, dev);
4581 }
Alex Williamsona97590e2011-03-04 14:52:16 -07004582
Fenghua Yu99dcade2009-11-11 07:23:06 -08004583 return 0;
4584}
4585
4586static struct notifier_block device_nb = {
4587 .notifier_call = device_notifier,
4588};
4589
Jiang Liu75f05562014-02-19 14:07:37 +08004590static int intel_iommu_memory_notifier(struct notifier_block *nb,
4591 unsigned long val, void *v)
4592{
4593 struct memory_notify *mhp = v;
4594 unsigned long long start, end;
4595 unsigned long start_vpfn, last_vpfn;
4596
4597 switch (val) {
4598 case MEM_GOING_ONLINE:
4599 start = mhp->start_pfn << PAGE_SHIFT;
4600 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4601 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004602 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004603 start, end);
4604 return NOTIFY_BAD;
4605 }
4606 break;
4607
4608 case MEM_OFFLINE:
4609 case MEM_CANCEL_ONLINE:
4610 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4611 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4612 while (start_vpfn <= last_vpfn) {
4613 struct iova *iova;
4614 struct dmar_drhd_unit *drhd;
4615 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004616 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004617
4618 iova = find_iova(&si_domain->iovad, start_vpfn);
4619 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004620 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004621 start_vpfn);
4622 break;
4623 }
4624
4625 iova = split_and_remove_iova(&si_domain->iovad, iova,
4626 start_vpfn, last_vpfn);
4627 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004628 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004629 start_vpfn, last_vpfn);
4630 return NOTIFY_BAD;
4631 }
4632
David Woodhouseea8ea462014-03-05 17:09:32 +00004633 freelist = domain_unmap(si_domain, iova->pfn_lo,
4634 iova->pfn_hi);
4635
Jiang Liu75f05562014-02-19 14:07:37 +08004636 rcu_read_lock();
4637 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004638 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004639 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004640 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004641 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004642 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004643
4644 start_vpfn = iova->pfn_hi + 1;
4645 free_iova_mem(iova);
4646 }
4647 break;
4648 }
4649
4650 return NOTIFY_OK;
4651}
4652
4653static struct notifier_block intel_iommu_memory_nb = {
4654 .notifier_call = intel_iommu_memory_notifier,
4655 .priority = 0
4656};
4657
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004658static void free_all_cpu_cached_iovas(unsigned int cpu)
4659{
4660 int i;
4661
4662 for (i = 0; i < g_num_of_iommus; i++) {
4663 struct intel_iommu *iommu = g_iommus[i];
4664 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004665 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004666
4667 if (!iommu)
4668 continue;
4669
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004670 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004671 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004672
4673 if (!domain)
4674 continue;
4675 free_cpu_cached_iovas(cpu, &domain->iovad);
4676 }
4677 }
4678}
4679
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004680static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004681{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004682 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004683 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004684}
4685
Joerg Roedel161b28a2017-03-28 17:04:52 +02004686static void intel_disable_iommus(void)
4687{
4688 struct intel_iommu *iommu = NULL;
4689 struct dmar_drhd_unit *drhd;
4690
4691 for_each_iommu(iommu, drhd)
4692 iommu_disable_translation(iommu);
4693}
4694
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004695static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4696{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004697 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4698
4699 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004700}
4701
Alex Williamsona5459cf2014-06-12 16:12:31 -06004702static ssize_t intel_iommu_show_version(struct device *dev,
4703 struct device_attribute *attr,
4704 char *buf)
4705{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004706 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004707 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4708 return sprintf(buf, "%d:%d\n",
4709 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4710}
4711static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4712
4713static ssize_t intel_iommu_show_address(struct device *dev,
4714 struct device_attribute *attr,
4715 char *buf)
4716{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004717 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004718 return sprintf(buf, "%llx\n", iommu->reg_phys);
4719}
4720static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4721
4722static ssize_t intel_iommu_show_cap(struct device *dev,
4723 struct device_attribute *attr,
4724 char *buf)
4725{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004726 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004727 return sprintf(buf, "%llx\n", iommu->cap);
4728}
4729static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4730
4731static ssize_t intel_iommu_show_ecap(struct device *dev,
4732 struct device_attribute *attr,
4733 char *buf)
4734{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004735 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004736 return sprintf(buf, "%llx\n", iommu->ecap);
4737}
4738static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4739
Alex Williamson2238c082015-07-14 15:24:53 -06004740static ssize_t intel_iommu_show_ndoms(struct device *dev,
4741 struct device_attribute *attr,
4742 char *buf)
4743{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004744 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004745 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4746}
4747static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4748
4749static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4750 struct device_attribute *attr,
4751 char *buf)
4752{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004753 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004754 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4755 cap_ndoms(iommu->cap)));
4756}
4757static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4758
Alex Williamsona5459cf2014-06-12 16:12:31 -06004759static struct attribute *intel_iommu_attrs[] = {
4760 &dev_attr_version.attr,
4761 &dev_attr_address.attr,
4762 &dev_attr_cap.attr,
4763 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004764 &dev_attr_domains_supported.attr,
4765 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004766 NULL,
4767};
4768
4769static struct attribute_group intel_iommu_group = {
4770 .name = "intel-iommu",
4771 .attrs = intel_iommu_attrs,
4772};
4773
4774const struct attribute_group *intel_iommu_groups[] = {
4775 &intel_iommu_group,
4776 NULL,
4777};
4778
Lu Baolu89a60792018-10-23 15:45:01 +08004779static int __init platform_optin_force_iommu(void)
4780{
4781 struct pci_dev *pdev = NULL;
4782 bool has_untrusted_dev = false;
4783
4784 if (!dmar_platform_optin() || no_platform_optin)
4785 return 0;
4786
4787 for_each_pci_dev(pdev) {
4788 if (pdev->untrusted) {
4789 has_untrusted_dev = true;
4790 break;
4791 }
4792 }
4793
4794 if (!has_untrusted_dev)
4795 return 0;
4796
4797 if (no_iommu || dmar_disabled)
4798 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4799
4800 /*
4801 * If Intel-IOMMU is disabled by default, we will apply identity
4802 * map for all devices except those marked as being untrusted.
4803 */
4804 if (dmar_disabled)
4805 iommu_identity_mapping |= IDENTMAP_ALL;
4806
4807 dmar_disabled = 0;
4808#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
4809 swiotlb = 0;
4810#endif
4811 no_iommu = 0;
4812
4813 return 1;
4814}
4815
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004816int __init intel_iommu_init(void)
4817{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004818 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004819 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004820 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004821
Lu Baolu89a60792018-10-23 15:45:01 +08004822 /*
4823 * Intel IOMMU is required for a TXT/tboot launch or platform
4824 * opt in, so enforce that.
4825 */
4826 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004827
Jiang Liu3a5670e2014-02-19 14:07:33 +08004828 if (iommu_init_mempool()) {
4829 if (force_on)
4830 panic("tboot: Failed to initialize iommu memory\n");
4831 return -ENOMEM;
4832 }
4833
4834 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004835 if (dmar_table_init()) {
4836 if (force_on)
4837 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004838 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004839 }
4840
Suresh Siddhac2c72862011-08-23 17:05:19 -07004841 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004842 if (force_on)
4843 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004844 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004845 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004846
Joerg Roedelec154bf2017-10-06 15:00:53 +02004847 up_write(&dmar_global_lock);
4848
4849 /*
4850 * The bus notifier takes the dmar_global_lock, so lockdep will
4851 * complain later when we register it under the lock.
4852 */
4853 dmar_register_bus_notifier();
4854
4855 down_write(&dmar_global_lock);
4856
Joerg Roedel161b28a2017-03-28 17:04:52 +02004857 if (no_iommu || dmar_disabled) {
4858 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004859 * We exit the function here to ensure IOMMU's remapping and
4860 * mempool aren't setup, which means that the IOMMU's PMRs
4861 * won't be disabled via the call to init_dmars(). So disable
4862 * it explicitly here. The PMRs were setup by tboot prior to
4863 * calling SENTER, but the kernel is expected to reset/tear
4864 * down the PMRs.
4865 */
4866 if (intel_iommu_tboot_noforce) {
4867 for_each_iommu(iommu, drhd)
4868 iommu_disable_protect_mem_regions(iommu);
4869 }
4870
4871 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004872 * Make sure the IOMMUs are switched off, even when we
4873 * boot into a kexec kernel and the previous kernel left
4874 * them enabled
4875 */
4876 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004877 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004878 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004879
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004880 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004881 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004882
4883 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004884 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004885
Joseph Cihula51a63e62011-03-21 11:04:24 -07004886 if (dmar_init_reserved_ranges()) {
4887 if (force_on)
4888 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004889 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004890 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004891
Lu Baolucf1ec452019-05-02 09:34:25 +08004892 if (dmar_map_gfx)
4893 intel_iommu_gfx_mapped = 1;
4894
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004895 init_no_remapping_devices();
4896
Joseph Cihulab7792602011-05-03 00:08:37 -07004897 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004898 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004899 if (force_on)
4900 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004901 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004902 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004903 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004904 up_write(&dmar_global_lock);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004905 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004906
Christoph Hellwig4fac8072017-12-24 13:57:08 +01004907#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004908 swiotlb = 0;
4909#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004910 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004911
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004912 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004913
Joerg Roedel39ab9552017-02-01 16:56:46 +01004914 for_each_active_iommu(iommu, drhd) {
4915 iommu_device_sysfs_add(&iommu->iommu, NULL,
4916 intel_iommu_groups,
4917 "%s", iommu->name);
4918 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4919 iommu_device_register(&iommu->iommu);
4920 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06004921
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004922 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004923 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004924 if (si_domain && !hw_pass_through)
4925 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004926 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4927 intel_iommu_cpu_dead);
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004928 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07004929 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004930
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004931 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004932
4933out_free_reserved_range:
4934 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004935out_free_dmar:
4936 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004937 up_write(&dmar_global_lock);
4938 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004939 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004940}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004941
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004942static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004943{
4944 struct intel_iommu *iommu = opaque;
4945
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004946 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004947 return 0;
4948}
4949
4950/*
4951 * NB - intel-iommu lacks any sort of reference counting for the users of
4952 * dependent devices. If multiple endpoints have intersecting dependent
4953 * devices, unbinding the driver from any one of them will possibly leave
4954 * the others unable to operate.
4955 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004956static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004957{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004958 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004959 return;
4960
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004961 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004962}
4963
Joerg Roedel127c7612015-07-23 17:44:46 +02004964static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004965{
Weidong Hanc7151a82008-12-08 22:51:37 +08004966 struct intel_iommu *iommu;
4967 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004968
Joerg Roedel55d94042015-07-22 16:50:40 +02004969 assert_spin_locked(&device_domain_lock);
4970
Joerg Roedelb608ac32015-07-21 18:19:08 +02004971 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004972 return;
4973
Joerg Roedel127c7612015-07-23 17:44:46 +02004974 iommu = info->iommu;
4975
4976 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08004977 if (dev_is_pci(info->dev) && sm_supported(iommu))
4978 intel_pasid_tear_down_entry(iommu, info->dev,
4979 PASID_RID2PASID);
4980
Joerg Roedel127c7612015-07-23 17:44:46 +02004981 iommu_disable_dev_iotlb(info);
4982 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08004983 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02004984 }
4985
Joerg Roedelb608ac32015-07-21 18:19:08 +02004986 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004987
Joerg Roedeld160aca2015-07-22 11:52:53 +02004988 spin_lock_irqsave(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004989 domain_detach_iommu(info->domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004990 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004991
4992 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004993}
4994
Bjorn Helgaas71753232019-02-08 16:06:15 -06004995static void dmar_remove_one_dev_info(struct device *dev)
Joerg Roedel55d94042015-07-22 16:50:40 +02004996{
Joerg Roedel127c7612015-07-23 17:44:46 +02004997 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02004998 unsigned long flags;
4999
Weidong Hanc7151a82008-12-08 22:51:37 +08005000 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005001 info = dev->archdata.iommu;
5002 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005003 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005004}
5005
5006static int md_domain_init(struct dmar_domain *domain, int guest_width)
5007{
5008 int adjust_width;
5009
Zhen Leiaa3ac942017-09-21 16:52:45 +01005010 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005011 domain_reserve_special_ranges(domain);
5012
5013 /* calculate AGAW */
5014 domain->gaw = guest_width;
5015 adjust_width = guestwidth_to_adjustwidth(guest_width);
5016 domain->agaw = width_to_agaw(adjust_width);
5017
Weidong Han5e98c4b2008-12-08 23:03:27 +08005018 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08005019 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01005020 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005021 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08005022
5023 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07005024 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005025 if (!domain->pgd)
5026 return -ENOMEM;
5027 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5028 return 0;
5029}
5030
Joerg Roedel00a77de2015-03-26 13:43:08 +01005031static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005032{
Joerg Roedel5d450802008-12-03 14:52:32 +01005033 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005034 struct iommu_domain *domain;
5035
5036 if (type != IOMMU_DOMAIN_UNMANAGED)
5037 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005038
Jiang Liuab8dfe22014-07-11 14:19:27 +08005039 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01005040 if (!dmar_domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005041 pr_err("Can't allocate dmar_domain\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01005042 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005043 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07005044 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005045 pr_err("Domain initialization failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08005046 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01005047 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005048 }
Allen Kay8140a952011-10-14 12:32:17 -07005049 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005050
Joerg Roedel00a77de2015-03-26 13:43:08 +01005051 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01005052 domain->geometry.aperture_start = 0;
5053 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5054 domain->geometry.force_aperture = true;
5055
Joerg Roedel00a77de2015-03-26 13:43:08 +01005056 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03005057}
Kay, Allen M38717942008-09-09 18:37:29 +03005058
Joerg Roedel00a77de2015-03-26 13:43:08 +01005059static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005060{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005061 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005062}
Kay, Allen M38717942008-09-09 18:37:29 +03005063
Lu Baolu67b8e022019-03-25 09:30:32 +08005064/*
5065 * Check whether a @domain could be attached to the @dev through the
5066 * aux-domain attach/detach APIs.
5067 */
5068static inline bool
5069is_aux_domain(struct device *dev, struct iommu_domain *domain)
5070{
5071 struct device_domain_info *info = dev->archdata.iommu;
5072
5073 return info && info->auxd_enabled &&
5074 domain->type == IOMMU_DOMAIN_UNMANAGED;
5075}
5076
5077static void auxiliary_link_device(struct dmar_domain *domain,
5078 struct device *dev)
5079{
5080 struct device_domain_info *info = dev->archdata.iommu;
5081
5082 assert_spin_locked(&device_domain_lock);
5083 if (WARN_ON(!info))
5084 return;
5085
5086 domain->auxd_refcnt++;
5087 list_add(&domain->auxd, &info->auxiliary_domains);
5088}
5089
5090static void auxiliary_unlink_device(struct dmar_domain *domain,
5091 struct device *dev)
5092{
5093 struct device_domain_info *info = dev->archdata.iommu;
5094
5095 assert_spin_locked(&device_domain_lock);
5096 if (WARN_ON(!info))
5097 return;
5098
5099 list_del(&domain->auxd);
5100 domain->auxd_refcnt--;
5101
5102 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5103 intel_pasid_free_id(domain->default_pasid);
5104}
5105
5106static int aux_domain_add_dev(struct dmar_domain *domain,
5107 struct device *dev)
5108{
5109 int ret;
5110 u8 bus, devfn;
5111 unsigned long flags;
5112 struct intel_iommu *iommu;
5113
5114 iommu = device_to_iommu(dev, &bus, &devfn);
5115 if (!iommu)
5116 return -ENODEV;
5117
5118 if (domain->default_pasid <= 0) {
5119 int pasid;
5120
5121 pasid = intel_pasid_alloc_id(domain, PASID_MIN,
5122 pci_max_pasids(to_pci_dev(dev)),
5123 GFP_KERNEL);
5124 if (pasid <= 0) {
5125 pr_err("Can't allocate default pasid\n");
5126 return -ENODEV;
5127 }
5128 domain->default_pasid = pasid;
5129 }
5130
5131 spin_lock_irqsave(&device_domain_lock, flags);
5132 /*
5133 * iommu->lock must be held to attach domain to iommu and setup the
5134 * pasid entry for second level translation.
5135 */
5136 spin_lock(&iommu->lock);
5137 ret = domain_attach_iommu(domain, iommu);
5138 if (ret)
5139 goto attach_failed;
5140
5141 /* Setup the PASID entry for mediated devices: */
5142 ret = intel_pasid_setup_second_level(iommu, domain, dev,
5143 domain->default_pasid);
5144 if (ret)
5145 goto table_failed;
5146 spin_unlock(&iommu->lock);
5147
5148 auxiliary_link_device(domain, dev);
5149
5150 spin_unlock_irqrestore(&device_domain_lock, flags);
5151
5152 return 0;
5153
5154table_failed:
5155 domain_detach_iommu(domain, iommu);
5156attach_failed:
5157 spin_unlock(&iommu->lock);
5158 spin_unlock_irqrestore(&device_domain_lock, flags);
5159 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5160 intel_pasid_free_id(domain->default_pasid);
5161
5162 return ret;
5163}
5164
5165static void aux_domain_remove_dev(struct dmar_domain *domain,
5166 struct device *dev)
5167{
5168 struct device_domain_info *info;
5169 struct intel_iommu *iommu;
5170 unsigned long flags;
5171
5172 if (!is_aux_domain(dev, &domain->domain))
5173 return;
5174
5175 spin_lock_irqsave(&device_domain_lock, flags);
5176 info = dev->archdata.iommu;
5177 iommu = info->iommu;
5178
5179 auxiliary_unlink_device(domain, dev);
5180
5181 spin_lock(&iommu->lock);
5182 intel_pasid_tear_down_entry(iommu, dev, domain->default_pasid);
5183 domain_detach_iommu(domain, iommu);
5184 spin_unlock(&iommu->lock);
5185
5186 spin_unlock_irqrestore(&device_domain_lock, flags);
5187}
5188
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005189static int prepare_domain_attach_device(struct iommu_domain *domain,
5190 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005191{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005192 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005193 struct intel_iommu *iommu;
5194 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005195 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005196
David Woodhouse156baca2014-03-09 14:00:57 -07005197 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005198 if (!iommu)
5199 return -ENODEV;
5200
5201 /* check if this iommu agaw is sufficient for max mapped address */
5202 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005203 if (addr_width > cap_mgaw(iommu->cap))
5204 addr_width = cap_mgaw(iommu->cap);
5205
5206 if (dmar_domain->max_addr > (1LL << addr_width)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005207 dev_err(dev, "%s: iommu width (%d) is not "
5208 "sufficient for the mapped address (%llx)\n",
5209 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005210 return -EFAULT;
5211 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005212 dmar_domain->gaw = addr_width;
5213
5214 /*
5215 * Knock out extra levels of page tables if necessary
5216 */
5217 while (iommu->agaw < dmar_domain->agaw) {
5218 struct dma_pte *pte;
5219
5220 pte = dmar_domain->pgd;
5221 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005222 dmar_domain->pgd = (struct dma_pte *)
5223 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005224 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005225 }
5226 dmar_domain->agaw--;
5227 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005228
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005229 return 0;
5230}
5231
5232static int intel_iommu_attach_device(struct iommu_domain *domain,
5233 struct device *dev)
5234{
5235 int ret;
5236
5237 if (device_is_rmrr_locked(dev)) {
5238 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5239 return -EPERM;
5240 }
5241
Lu Baolu67b8e022019-03-25 09:30:32 +08005242 if (is_aux_domain(dev, domain))
5243 return -EPERM;
5244
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005245 /* normally dev is not mapped */
5246 if (unlikely(domain_context_mapped(dev))) {
5247 struct dmar_domain *old_domain;
5248
5249 old_domain = find_domain(dev);
5250 if (old_domain) {
5251 rcu_read_lock();
5252 dmar_remove_one_dev_info(dev);
5253 rcu_read_unlock();
5254
5255 if (!domain_type_is_vm_or_si(old_domain) &&
5256 list_empty(&old_domain->devices))
5257 domain_exit(old_domain);
5258 }
5259 }
5260
5261 ret = prepare_domain_attach_device(domain, dev);
5262 if (ret)
5263 return ret;
5264
5265 return domain_add_dev_info(to_dmar_domain(domain), dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005266}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005267
Lu Baolu67b8e022019-03-25 09:30:32 +08005268static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
5269 struct device *dev)
5270{
5271 int ret;
5272
5273 if (!is_aux_domain(dev, domain))
5274 return -EPERM;
5275
5276 ret = prepare_domain_attach_device(domain, dev);
5277 if (ret)
5278 return ret;
5279
5280 return aux_domain_add_dev(to_dmar_domain(domain), dev);
5281}
5282
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005283static void intel_iommu_detach_device(struct iommu_domain *domain,
5284 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005285{
Bjorn Helgaas71753232019-02-08 16:06:15 -06005286 dmar_remove_one_dev_info(dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005287}
Kay, Allen M38717942008-09-09 18:37:29 +03005288
Lu Baolu67b8e022019-03-25 09:30:32 +08005289static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
5290 struct device *dev)
5291{
5292 aux_domain_remove_dev(to_dmar_domain(domain), dev);
5293}
5294
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005295static int intel_iommu_map(struct iommu_domain *domain,
5296 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005297 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03005298{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005299 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005300 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005301 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005302 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005303
Joerg Roedeldde57a22008-12-03 15:04:09 +01005304 if (iommu_prot & IOMMU_READ)
5305 prot |= DMA_PTE_READ;
5306 if (iommu_prot & IOMMU_WRITE)
5307 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005308 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5309 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005310
David Woodhouse163cc522009-06-28 00:51:17 +01005311 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005312 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005313 u64 end;
5314
5315 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005316 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005317 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005318 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005319 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005320 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005321 return -EFAULT;
5322 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005323 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005324 }
David Woodhousead051222009-06-28 14:22:28 +01005325 /* Round up size to next multiple of PAGE_SIZE, if it and
5326 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005327 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005328 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5329 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005330 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005331}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005332
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005333static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00005334 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005335{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005336 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005337 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005338 unsigned long start_pfn, last_pfn;
5339 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005340 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005341
David Woodhouse5cf0a762014-03-19 16:07:49 +00005342 /* Cope with horrid API which requires us to unmap more than the
5343 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005344 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005345
5346 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5347 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5348
David Woodhouseea8ea462014-03-05 17:09:32 +00005349 start_pfn = iova >> VTD_PAGE_SHIFT;
5350 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5351
5352 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5353
5354 npages = last_pfn - start_pfn + 1;
5355
Shaokun Zhangf746a022018-03-22 18:18:06 +08005356 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005357 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5358 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005359
5360 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005361
David Woodhouse163cc522009-06-28 00:51:17 +01005362 if (dmar_domain->max_addr == iova + size)
5363 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005364
David Woodhouse5cf0a762014-03-19 16:07:49 +00005365 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005366}
Kay, Allen M38717942008-09-09 18:37:29 +03005367
Joerg Roedeld14d6572008-12-03 15:06:57 +01005368static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305369 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005370{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005371 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005372 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005373 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005374 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005375
David Woodhouse5cf0a762014-03-19 16:07:49 +00005376 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005377 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005378 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005379
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005380 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005381}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005382
Lu Baolu95587a72019-03-25 09:30:30 +08005383static inline bool scalable_mode_support(void)
5384{
5385 struct dmar_drhd_unit *drhd;
5386 struct intel_iommu *iommu;
5387 bool ret = true;
5388
5389 rcu_read_lock();
5390 for_each_active_iommu(iommu, drhd) {
5391 if (!sm_supported(iommu)) {
5392 ret = false;
5393 break;
5394 }
5395 }
5396 rcu_read_unlock();
5397
5398 return ret;
5399}
5400
5401static inline bool iommu_pasid_support(void)
5402{
5403 struct dmar_drhd_unit *drhd;
5404 struct intel_iommu *iommu;
5405 bool ret = true;
5406
5407 rcu_read_lock();
5408 for_each_active_iommu(iommu, drhd) {
5409 if (!pasid_supported(iommu)) {
5410 ret = false;
5411 break;
5412 }
5413 }
5414 rcu_read_unlock();
5415
5416 return ret;
5417}
5418
Joerg Roedel5d587b82014-09-05 10:50:45 +02005419static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005420{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005421 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005422 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005423 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005424 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005425
Joerg Roedel5d587b82014-09-05 10:50:45 +02005426 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005427}
5428
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005429static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005430{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005431 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005432 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005433 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005434
Alex Williamsona5459cf2014-06-12 16:12:31 -06005435 iommu = device_to_iommu(dev, &bus, &devfn);
5436 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005437 return -ENODEV;
5438
Joerg Roedele3d10af2017-02-01 17:23:22 +01005439 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005440
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005441 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005442
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005443 if (IS_ERR(group))
5444 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005445
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005446 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005447 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005448}
5449
5450static void intel_iommu_remove_device(struct device *dev)
5451{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005452 struct intel_iommu *iommu;
5453 u8 bus, devfn;
5454
5455 iommu = device_to_iommu(dev, &bus, &devfn);
5456 if (!iommu)
5457 return;
5458
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005459 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005460
Joerg Roedele3d10af2017-02-01 17:23:22 +01005461 iommu_device_unlink(&iommu->iommu, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005462}
5463
Eric Auger0659b8d2017-01-19 20:57:53 +00005464static void intel_iommu_get_resv_regions(struct device *device,
5465 struct list_head *head)
5466{
5467 struct iommu_resv_region *reg;
5468 struct dmar_rmrr_unit *rmrr;
5469 struct device *i_dev;
5470 int i;
5471
5472 rcu_read_lock();
5473 for_each_rmrr_units(rmrr) {
5474 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5475 i, i_dev) {
5476 if (i_dev != device)
5477 continue;
5478
5479 list_add_tail(&rmrr->resv->list, head);
5480 }
5481 }
5482 rcu_read_unlock();
5483
5484 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5485 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005486 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005487 if (!reg)
5488 return;
5489 list_add_tail(&reg->list, head);
5490}
5491
5492static void intel_iommu_put_resv_regions(struct device *dev,
5493 struct list_head *head)
5494{
5495 struct iommu_resv_region *entry, *next;
5496
5497 list_for_each_entry_safe(entry, next, head, list) {
Gerald Schaefer198bc322019-01-16 20:11:44 +01005498 if (entry->type == IOMMU_RESV_MSI)
Eric Auger0659b8d2017-01-19 20:57:53 +00005499 kfree(entry);
5500 }
Kay, Allen M38717942008-09-09 18:37:29 +03005501}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005502
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005503int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005504{
5505 struct device_domain_info *info;
5506 struct context_entry *context;
5507 struct dmar_domain *domain;
5508 unsigned long flags;
5509 u64 ctx_lo;
5510 int ret;
5511
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005512 domain = get_valid_domain_for_dev(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005513 if (!domain)
5514 return -EINVAL;
5515
5516 spin_lock_irqsave(&device_domain_lock, flags);
5517 spin_lock(&iommu->lock);
5518
5519 ret = -EINVAL;
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005520 info = dev->archdata.iommu;
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005521 if (!info || !info->pasid_supported)
5522 goto out;
5523
5524 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5525 if (WARN_ON(!context))
5526 goto out;
5527
5528 ctx_lo = context[0].lo;
5529
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005530 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005531 ctx_lo |= CONTEXT_PASIDE;
5532 context[0].lo = ctx_lo;
5533 wmb();
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005534 iommu->flush.flush_context(iommu,
5535 domain->iommu_did[iommu->seq_id],
5536 PCI_DEVID(info->bus, info->devfn),
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005537 DMA_CCMD_MASK_NOBIT,
5538 DMA_CCMD_DEVICE_INVL);
5539 }
5540
5541 /* Enable PASID support in the device, if it wasn't already */
5542 if (!info->pasid_enabled)
5543 iommu_enable_dev_iotlb(info);
5544
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005545 ret = 0;
5546
5547 out:
5548 spin_unlock(&iommu->lock);
5549 spin_unlock_irqrestore(&device_domain_lock, flags);
5550
5551 return ret;
5552}
5553
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005554#ifdef CONFIG_INTEL_IOMMU_SVM
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005555struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5556{
5557 struct intel_iommu *iommu;
5558 u8 bus, devfn;
5559
5560 if (iommu_dummy(dev)) {
5561 dev_warn(dev,
5562 "No IOMMU translation for device; cannot enable SVM\n");
5563 return NULL;
5564 }
5565
5566 iommu = device_to_iommu(dev, &bus, &devfn);
5567 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07005568 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005569 return NULL;
5570 }
5571
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005572 return iommu;
5573}
5574#endif /* CONFIG_INTEL_IOMMU_SVM */
5575
Lu Baolu95587a72019-03-25 09:30:30 +08005576static int intel_iommu_enable_auxd(struct device *dev)
5577{
5578 struct device_domain_info *info;
5579 struct intel_iommu *iommu;
5580 unsigned long flags;
5581 u8 bus, devfn;
5582 int ret;
5583
5584 iommu = device_to_iommu(dev, &bus, &devfn);
5585 if (!iommu || dmar_disabled)
5586 return -EINVAL;
5587
5588 if (!sm_supported(iommu) || !pasid_supported(iommu))
5589 return -EINVAL;
5590
5591 ret = intel_iommu_enable_pasid(iommu, dev);
5592 if (ret)
5593 return -ENODEV;
5594
5595 spin_lock_irqsave(&device_domain_lock, flags);
5596 info = dev->archdata.iommu;
5597 info->auxd_enabled = 1;
5598 spin_unlock_irqrestore(&device_domain_lock, flags);
5599
5600 return 0;
5601}
5602
5603static int intel_iommu_disable_auxd(struct device *dev)
5604{
5605 struct device_domain_info *info;
5606 unsigned long flags;
5607
5608 spin_lock_irqsave(&device_domain_lock, flags);
5609 info = dev->archdata.iommu;
5610 if (!WARN_ON(!info))
5611 info->auxd_enabled = 0;
5612 spin_unlock_irqrestore(&device_domain_lock, flags);
5613
5614 return 0;
5615}
5616
5617/*
5618 * A PCI express designated vendor specific extended capability is defined
5619 * in the section 3.7 of Intel scalable I/O virtualization technical spec
5620 * for system software and tools to detect endpoint devices supporting the
5621 * Intel scalable IO virtualization without host driver dependency.
5622 *
5623 * Returns the address of the matching extended capability structure within
5624 * the device's PCI configuration space or 0 if the device does not support
5625 * it.
5626 */
5627static int siov_find_pci_dvsec(struct pci_dev *pdev)
5628{
5629 int pos;
5630 u16 vendor, id;
5631
5632 pos = pci_find_next_ext_capability(pdev, 0, 0x23);
5633 while (pos) {
5634 pci_read_config_word(pdev, pos + 4, &vendor);
5635 pci_read_config_word(pdev, pos + 8, &id);
5636 if (vendor == PCI_VENDOR_ID_INTEL && id == 5)
5637 return pos;
5638
5639 pos = pci_find_next_ext_capability(pdev, pos, 0x23);
5640 }
5641
5642 return 0;
5643}
5644
5645static bool
5646intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat)
5647{
5648 if (feat == IOMMU_DEV_FEAT_AUX) {
5649 int ret;
5650
5651 if (!dev_is_pci(dev) || dmar_disabled ||
5652 !scalable_mode_support() || !iommu_pasid_support())
5653 return false;
5654
5655 ret = pci_pasid_features(to_pci_dev(dev));
5656 if (ret < 0)
5657 return false;
5658
5659 return !!siov_find_pci_dvsec(to_pci_dev(dev));
5660 }
5661
5662 return false;
5663}
5664
5665static int
5666intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
5667{
5668 if (feat == IOMMU_DEV_FEAT_AUX)
5669 return intel_iommu_enable_auxd(dev);
5670
5671 return -ENODEV;
5672}
5673
5674static int
5675intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
5676{
5677 if (feat == IOMMU_DEV_FEAT_AUX)
5678 return intel_iommu_disable_auxd(dev);
5679
5680 return -ENODEV;
5681}
5682
5683static bool
5684intel_iommu_dev_feat_enabled(struct device *dev, enum iommu_dev_features feat)
5685{
5686 struct device_domain_info *info = dev->archdata.iommu;
5687
5688 if (feat == IOMMU_DEV_FEAT_AUX)
5689 return scalable_mode_support() && info && info->auxd_enabled;
5690
5691 return false;
5692}
5693
Lu Baolu0e8000f2019-03-25 09:30:33 +08005694static int
5695intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
5696{
5697 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5698
5699 return dmar_domain->default_pasid > 0 ?
5700 dmar_domain->default_pasid : -EINVAL;
5701}
5702
Joerg Roedelb0119e82017-02-01 13:23:08 +01005703const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00005704 .capable = intel_iommu_capable,
5705 .domain_alloc = intel_iommu_domain_alloc,
5706 .domain_free = intel_iommu_domain_free,
5707 .attach_dev = intel_iommu_attach_device,
5708 .detach_dev = intel_iommu_detach_device,
Lu Baolu67b8e022019-03-25 09:30:32 +08005709 .aux_attach_dev = intel_iommu_aux_attach_device,
5710 .aux_detach_dev = intel_iommu_aux_detach_device,
Lu Baolu0e8000f2019-03-25 09:30:33 +08005711 .aux_get_pasid = intel_iommu_aux_get_pasid,
Eric Auger0659b8d2017-01-19 20:57:53 +00005712 .map = intel_iommu_map,
5713 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00005714 .iova_to_phys = intel_iommu_iova_to_phys,
5715 .add_device = intel_iommu_add_device,
5716 .remove_device = intel_iommu_remove_device,
5717 .get_resv_regions = intel_iommu_get_resv_regions,
5718 .put_resv_regions = intel_iommu_put_resv_regions,
5719 .device_group = pci_device_group,
Lu Baolu95587a72019-03-25 09:30:30 +08005720 .dev_has_feat = intel_iommu_dev_has_feat,
5721 .dev_feat_enabled = intel_iommu_dev_feat_enabled,
5722 .dev_enable_feat = intel_iommu_dev_enable_feat,
5723 .dev_disable_feat = intel_iommu_dev_disable_feat,
Eric Auger0659b8d2017-01-19 20:57:53 +00005724 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005725};
David Woodhouse9af88142009-02-13 23:18:03 +00005726
Daniel Vetter94526182013-01-20 23:50:13 +01005727static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
5728{
5729 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005730 pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01005731 dmar_map_gfx = 0;
5732}
5733
5734DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
5735DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
5736DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
5737DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
5738DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
5739DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
5740DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
5741
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005742static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00005743{
5744 /*
5745 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01005746 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00005747 */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005748 pci_info(dev, "Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00005749 rwbf_quirk = 1;
5750}
5751
5752DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01005753DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
5754DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
5755DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
5756DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
5757DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
5758DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07005759
Adam Jacksoneecfd572010-08-25 21:17:34 +01005760#define GGC 0x52
5761#define GGC_MEMORY_SIZE_MASK (0xf << 8)
5762#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
5763#define GGC_MEMORY_SIZE_1M (0x1 << 8)
5764#define GGC_MEMORY_SIZE_2M (0x3 << 8)
5765#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
5766#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
5767#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
5768#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
5769
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005770static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01005771{
5772 unsigned short ggc;
5773
Adam Jacksoneecfd572010-08-25 21:17:34 +01005774 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01005775 return;
5776
Adam Jacksoneecfd572010-08-25 21:17:34 +01005777 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005778 pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01005779 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005780 } else if (dmar_map_gfx) {
5781 /* we have to ensure the gfx device is idle before we flush */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005782 pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005783 intel_iommu_strict = 1;
5784 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01005785}
5786DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
5787DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
5788DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
5789DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
5790
David Woodhousee0fc7e02009-09-30 09:12:17 -07005791/* On Tylersburg chipsets, some BIOSes have been known to enable the
5792 ISOCH DMAR unit for the Azalia sound device, but not give it any
5793 TLB entries, which causes it to deadlock. Check for that. We do
5794 this in a function called from init_dmars(), instead of in a PCI
5795 quirk, because we don't want to print the obnoxious "BIOS broken"
5796 message if VT-d is actually disabled.
5797*/
5798static void __init check_tylersburg_isoch(void)
5799{
5800 struct pci_dev *pdev;
5801 uint32_t vtisochctrl;
5802
5803 /* If there's no Azalia in the system anyway, forget it. */
5804 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
5805 if (!pdev)
5806 return;
5807 pci_dev_put(pdev);
5808
5809 /* System Management Registers. Might be hidden, in which case
5810 we can't do the sanity check. But that's OK, because the
5811 known-broken BIOSes _don't_ actually hide it, so far. */
5812 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
5813 if (!pdev)
5814 return;
5815
5816 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
5817 pci_dev_put(pdev);
5818 return;
5819 }
5820
5821 pci_dev_put(pdev);
5822
5823 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
5824 if (vtisochctrl & 1)
5825 return;
5826
5827 /* Drop all bits other than the number of TLB entries */
5828 vtisochctrl &= 0x1c;
5829
5830 /* If we have the recommended number of TLB entries (16), fine. */
5831 if (vtisochctrl == 0x10)
5832 return;
5833
5834 /* Zero TLB entries? You get to ride the short bus to school. */
5835 if (!vtisochctrl) {
5836 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5837 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5838 dmi_get_system_info(DMI_BIOS_VENDOR),
5839 dmi_get_system_info(DMI_BIOS_VERSION),
5840 dmi_get_system_info(DMI_PRODUCT_VERSION));
5841 iommu_identity_mapping |= IDENTMAP_AZALIA;
5842 return;
5843 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005844
5845 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005846 vtisochctrl);
5847}