blob: 0d7d177673ddab2081ab5528e1b92de343a64bd0 [file] [log] [blame]
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001/*
David Woodhouseea8ea462014-03-05 17:09:32 +00002 * Copyright © 2006-2014 Intel Corporation.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
David Woodhouseea8ea462014-03-05 17:09:32 +000013 * Authors: David Woodhouse <dwmw2@infradead.org>,
14 * Ashok Raj <ashok.raj@intel.com>,
15 * Shaohua Li <shaohua.li@intel.com>,
16 * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
17 * Fenghua Yu <fenghua.yu@intel.com>
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020018 * Joerg Roedel <jroedel@suse.de>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070019 */
20
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020021#define pr_fmt(fmt) "DMAR: " fmt
Bjorn Helgaas932a6522019-02-08 16:06:00 -060022#define dev_fmt(fmt) pr_fmt(fmt)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020023
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070024#include <linux/init.h>
25#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080026#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040027#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070028#include <linux/slab.h>
29#include <linux/irq.h>
30#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070031#include <linux/spinlock.h>
32#include <linux/pci.h>
33#include <linux/dmar.h>
34#include <linux/dma-mapping.h>
35#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080036#include <linux/memory.h>
Omer Pelegaa473242016-04-20 11:33:02 +030037#include <linux/cpu.h>
mark gross5e0d2a62008-03-04 15:22:08 -080038#include <linux/timer.h>
Dan Williamsdfddb962015-10-09 18:16:46 -040039#include <linux/io.h>
Kay, Allen M38717942008-09-09 18:37:29 +030040#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010041#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030042#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010043#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070044#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100045#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020046#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080047#include <linux/memblock.h>
Akinobu Mita36746432014-06-04 16:06:51 -070048#include <linux/dma-contiguous.h>
Christoph Hellwigfec777c2018-03-19 11:38:15 +010049#include <linux/dma-direct.h>
Joerg Roedel091d42e2015-06-12 11:56:10 +020050#include <linux/crash_dump.h>
Anshuman Khandual98fa15f2019-03-05 15:42:58 -080051#include <linux/numa.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070052#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070053#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090054#include <asm/iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070055
Joerg Roedel078e1ee2012-09-26 12:44:43 +020056#include "irq_remapping.h"
Lu Baolu56283172018-07-14 15:46:54 +080057#include "intel-pasid.h"
Joerg Roedel078e1ee2012-09-26 12:44:43 +020058
Fenghua Yu5b6985c2008-10-16 18:02:32 -070059#define ROOT_SIZE VTD_PAGE_SIZE
60#define CONTEXT_SIZE VTD_PAGE_SIZE
61
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070062#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000063#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070064#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070065#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070066
67#define IOAPIC_RANGE_START (0xfee00000)
68#define IOAPIC_RANGE_END (0xfeefffff)
69#define IOVA_START_ADDR (0x1000)
70
Sohil Mehta5e3b4a12017-12-20 11:59:24 -080071#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070072
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070073#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080074#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070075
David Woodhouse2ebe3152009-09-19 07:34:04 -070076#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
77#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
78
79/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
80 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
81#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
82 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
83#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070084
Robin Murphy1b722502015-01-12 17:51:15 +000085/* IO virtual address start page frame number */
86#define IOVA_START_PFN (1)
87
Mark McLoughlinf27be032008-11-20 15:49:43 +000088#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
mark gross5e0d2a62008-03-04 15:22:08 -080089
Andrew Mortondf08cdc2010-09-22 13:05:11 -070090/* page table handling */
91#define LEVEL_STRIDE (9)
92#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
93
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020094/*
95 * This bitmap is used to advertise the page sizes our hardware support
96 * to the IOMMU core, which will then use this information to split
97 * physically contiguous memory regions it is mapping into page sizes
98 * that we support.
99 *
100 * Traditionally the IOMMU core just handed us the mappings directly,
101 * after making sure the size is an order of a 4KiB page and that the
102 * mapping has natural alignment.
103 *
104 * To retain this behavior, we currently advertise that we support
105 * all page sizes that are an order of 4KiB.
106 *
107 * If at some point we'd like to utilize the IOMMU core's new behavior,
108 * we could change this to advertise the real page sizes we support.
109 */
110#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
111
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700112static inline int agaw_to_level(int agaw)
113{
114 return agaw + 2;
115}
116
117static inline int agaw_to_width(int agaw)
118{
Jiang Liu5c645b32014-01-06 14:18:12 +0800119 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700120}
121
122static inline int width_to_agaw(int width)
123{
Jiang Liu5c645b32014-01-06 14:18:12 +0800124 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700125}
126
127static inline unsigned int level_to_offset_bits(int level)
128{
129 return (level - 1) * LEVEL_STRIDE;
130}
131
132static inline int pfn_level_offset(unsigned long pfn, int level)
133{
134 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
135}
136
137static inline unsigned long level_mask(int level)
138{
139 return -1UL << level_to_offset_bits(level);
140}
141
142static inline unsigned long level_size(int level)
143{
144 return 1UL << level_to_offset_bits(level);
145}
146
147static inline unsigned long align_to_level(unsigned long pfn, int level)
148{
149 return (pfn + level_size(level) - 1) & level_mask(level);
150}
David Woodhousefd18de52009-05-10 23:57:41 +0100151
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100152static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
153{
Jiang Liu5c645b32014-01-06 14:18:12 +0800154 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100155}
156
David Woodhousedd4e8312009-06-27 16:21:20 +0100157/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
158 are never going to work. */
159static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
160{
161 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
162}
163
164static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
165{
166 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
167}
168static inline unsigned long page_to_dma_pfn(struct page *pg)
169{
170 return mm_to_dma_pfn(page_to_pfn(pg));
171}
172static inline unsigned long virt_to_dma_pfn(void *p)
173{
174 return page_to_dma_pfn(virt_to_page(p));
175}
176
Weidong Hand9630fe2008-12-08 11:06:32 +0800177/* global iommu list, set NULL for ignored DMAR units */
178static struct intel_iommu **g_iommus;
179
David Woodhousee0fc7e02009-09-30 09:12:17 -0700180static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000181static int rwbf_quirk;
182
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000183/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700184 * set to 1 to panic kernel if can't successfully enable VT-d
185 * (used when kernel is launched w/ TXT)
186 */
187static int force_on = 0;
Shaohua Libfd20f12017-04-26 09:18:35 -0700188int intel_iommu_tboot_noforce;
Lu Baolu89a60792018-10-23 15:45:01 +0800189static int no_platform_optin;
Joseph Cihulab7792602011-05-03 00:08:37 -0700190
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000191#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000192
Joerg Roedel091d42e2015-06-12 11:56:10 +0200193/*
194 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
195 * if marked present.
196 */
197static phys_addr_t root_entry_lctp(struct root_entry *re)
198{
199 if (!(re->lo & 1))
200 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000201
Joerg Roedel091d42e2015-06-12 11:56:10 +0200202 return re->lo & VTD_PAGE_MASK;
203}
204
205/*
206 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
207 * if marked present.
208 */
209static phys_addr_t root_entry_uctp(struct root_entry *re)
210{
211 if (!(re->hi & 1))
212 return 0;
213
214 return re->hi & VTD_PAGE_MASK;
215}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000216
Joerg Roedelcf484d02015-06-12 12:21:46 +0200217static inline void context_clear_pasid_enable(struct context_entry *context)
218{
219 context->lo &= ~(1ULL << 11);
220}
221
222static inline bool context_pasid_enabled(struct context_entry *context)
223{
224 return !!(context->lo & (1ULL << 11));
225}
226
227static inline void context_set_copied(struct context_entry *context)
228{
229 context->hi |= (1ull << 3);
230}
231
232static inline bool context_copied(struct context_entry *context)
233{
234 return !!(context->hi & (1ULL << 3));
235}
236
237static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000238{
239 return (context->lo & 1);
240}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200241
Sohil Mehta26b86092018-09-11 17:11:36 -0700242bool context_present(struct context_entry *context)
Joerg Roedelcf484d02015-06-12 12:21:46 +0200243{
244 return context_pasid_enabled(context) ?
245 __context_present(context) :
246 __context_present(context) && !context_copied(context);
247}
248
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000249static inline void context_set_present(struct context_entry *context)
250{
251 context->lo |= 1;
252}
253
254static inline void context_set_fault_enable(struct context_entry *context)
255{
256 context->lo &= (((u64)-1) << 2) | 1;
257}
258
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000259static inline void context_set_translation_type(struct context_entry *context,
260 unsigned long value)
261{
262 context->lo &= (((u64)-1) << 4) | 3;
263 context->lo |= (value & 3) << 2;
264}
265
266static inline void context_set_address_root(struct context_entry *context,
267 unsigned long value)
268{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800269 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000270 context->lo |= value & VTD_PAGE_MASK;
271}
272
273static inline void context_set_address_width(struct context_entry *context,
274 unsigned long value)
275{
276 context->hi |= value & 7;
277}
278
279static inline void context_set_domain_id(struct context_entry *context,
280 unsigned long value)
281{
282 context->hi |= (value & ((1 << 16) - 1)) << 8;
283}
284
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200285static inline int context_domain_id(struct context_entry *c)
286{
287 return((c->hi >> 8) & 0xffff);
288}
289
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000290static inline void context_clear_entry(struct context_entry *context)
291{
292 context->lo = 0;
293 context->hi = 0;
294}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000295
Mark McLoughlin622ba122008-11-20 15:49:46 +0000296/*
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700297 * This domain is a statically identity mapping domain.
298 * 1. This domain creats a static 1:1 mapping to all usable memory.
299 * 2. It maps to each iommu if successful.
300 * 3. Each iommu mapps to this domain if successful.
301 */
David Woodhouse19943b02009-08-04 16:19:20 +0100302static struct dmar_domain *si_domain;
303static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700304
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700305/* si_domain contains mulitple devices */
Lu Baolufa954e62019-05-25 13:41:28 +0800306#define DOMAIN_FLAG_STATIC_IDENTITY BIT(0)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700307
Lu Baolu942067f2019-05-25 13:41:29 +0800308/*
309 * This is a DMA domain allocated through the iommu domain allocation
310 * interface. But one or more devices belonging to this domain have
311 * been chosen to use a private domain. We should avoid to use the
312 * map/unmap/iova_to_phys APIs on it.
313 */
314#define DOMAIN_FLAG_LOSE_CHILDREN BIT(1)
315
Joerg Roedel29a27712015-07-21 17:17:12 +0200316#define for_each_domain_iommu(idx, domain) \
317 for (idx = 0; idx < g_num_of_iommus; idx++) \
318 if (domain->iommu_refcnt[idx])
319
Jiang Liub94e4112014-02-19 14:07:25 +0800320struct dmar_rmrr_unit {
321 struct list_head list; /* list of rmrr units */
322 struct acpi_dmar_header *hdr; /* ACPI header */
323 u64 base_address; /* reserved base address*/
324 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000325 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800326 int devices_cnt; /* target device count */
327};
328
329struct dmar_atsr_unit {
330 struct list_head list; /* list of ATSR units */
331 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000332 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800333 int devices_cnt; /* target device count */
334 u8 include_all:1; /* include all ports */
335};
336
337static LIST_HEAD(dmar_atsr_units);
338static LIST_HEAD(dmar_rmrr_units);
339
340#define for_each_rmrr_units(rmrr) \
341 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
342
mark gross5e0d2a62008-03-04 15:22:08 -0800343/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800344static int g_num_of_iommus;
345
Jiang Liu92d03cc2014-02-19 14:07:28 +0800346static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700347static void domain_remove_dev_info(struct dmar_domain *domain);
Bjorn Helgaas71753232019-02-08 16:06:15 -0600348static void dmar_remove_one_dev_info(struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200349static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Joerg Roedel2452d9d2015-07-23 16:20:14 +0200350static void domain_context_clear(struct intel_iommu *iommu,
351 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800352static int domain_detach_iommu(struct dmar_domain *domain,
353 struct intel_iommu *iommu);
Lu Baolu4de354e2019-05-25 13:41:27 +0800354static bool device_is_rmrr_locked(struct device *dev);
Lu Baolu8af46c72019-05-25 13:41:32 +0800355static int intel_iommu_attach_device(struct iommu_domain *domain,
356 struct device *dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700357
Suresh Siddhad3f13812011-08-23 17:05:25 -0700358#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800359int dmar_disabled = 0;
360#else
361int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700362#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800363
Sai Praneeth Prakhyacdd3a242019-05-24 16:40:16 -0700364int intel_iommu_sm;
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200365int intel_iommu_enabled = 0;
366EXPORT_SYMBOL_GPL(intel_iommu_enabled);
367
David Woodhouse2d9e6672010-06-15 10:57:57 +0100368static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700369static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800370static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100371static int intel_iommu_superpage = 1;
David Woodhouseae853dd2015-09-09 11:58:59 +0100372static int iommu_identity_mapping;
David Woodhousec83b2f22015-06-12 10:15:49 +0100373
David Woodhouseae853dd2015-09-09 11:58:59 +0100374#define IDENTMAP_ALL 1
375#define IDENTMAP_GFX 2
376#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100377
David Woodhousec0771df2011-10-14 20:59:46 +0100378int intel_iommu_gfx_mapped;
379EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
380
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700381#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
Lu Baolu8af46c72019-05-25 13:41:32 +0800382#define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700383static DEFINE_SPINLOCK(device_domain_lock);
384static LIST_HEAD(device_domain_list);
385
Lu Baolu85319dc2018-07-14 15:46:58 +0800386/*
387 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800388 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800389 */
390int for_each_device_domain(int (*fn)(struct device_domain_info *info,
391 void *data), void *data)
392{
393 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800394 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800395 struct device_domain_info *info;
396
Lu Baolu0bbeb012018-12-10 09:58:56 +0800397 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800398 list_for_each_entry(info, &device_domain_list, global) {
399 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800400 if (ret) {
401 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800402 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800403 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800404 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800405 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800406
407 return 0;
408}
409
Joerg Roedelb0119e82017-02-01 13:23:08 +0100410const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100411
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200412static bool translation_pre_enabled(struct intel_iommu *iommu)
413{
414 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
415}
416
Joerg Roedel091d42e2015-06-12 11:56:10 +0200417static void clear_translation_pre_enabled(struct intel_iommu *iommu)
418{
419 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
420}
421
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200422static void init_translation_status(struct intel_iommu *iommu)
423{
424 u32 gsts;
425
426 gsts = readl(iommu->reg + DMAR_GSTS_REG);
427 if (gsts & DMA_GSTS_TES)
428 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
429}
430
Joerg Roedel00a77de2015-03-26 13:43:08 +0100431/* Convert generic 'struct iommu_domain to private struct dmar_domain */
432static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
433{
434 return container_of(dom, struct dmar_domain, domain);
435}
436
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700437static int __init intel_iommu_setup(char *str)
438{
439 if (!str)
440 return -EINVAL;
441 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800442 if (!strncmp(str, "on", 2)) {
443 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200444 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800445 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700446 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800447 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200448 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700449 } else if (!strncmp(str, "igfx_off", 8)) {
450 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200451 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700452 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200453 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700454 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800455 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200456 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800457 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100458 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200459 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100460 intel_iommu_superpage = 0;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800461 } else if (!strncmp(str, "sm_on", 5)) {
462 pr_info("Intel-IOMMU: scalable mode supported\n");
463 intel_iommu_sm = 1;
Shaohua Libfd20f12017-04-26 09:18:35 -0700464 } else if (!strncmp(str, "tboot_noforce", 13)) {
465 printk(KERN_INFO
466 "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
467 intel_iommu_tboot_noforce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700468 }
469
470 str += strcspn(str, ",");
471 while (*str == ',')
472 str++;
473 }
474 return 0;
475}
476__setup("intel_iommu=", intel_iommu_setup);
477
478static struct kmem_cache *iommu_domain_cache;
479static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700480
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200481static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
482{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200483 struct dmar_domain **domains;
484 int idx = did >> 8;
485
486 domains = iommu->domains[idx];
487 if (!domains)
488 return NULL;
489
490 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200491}
492
493static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
494 struct dmar_domain *domain)
495{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200496 struct dmar_domain **domains;
497 int idx = did >> 8;
498
499 if (!iommu->domains[idx]) {
500 size_t size = 256 * sizeof(struct dmar_domain *);
501 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
502 }
503
504 domains = iommu->domains[idx];
505 if (WARN_ON(!domains))
506 return;
507 else
508 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200509}
510
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800511void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700512{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700513 struct page *page;
514 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700515
Suresh Siddha4c923d42009-10-02 11:01:24 -0700516 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
517 if (page)
518 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700519 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700520}
521
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800522void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700523{
524 free_page((unsigned long)vaddr);
525}
526
527static inline void *alloc_domain_mem(void)
528{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900529 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700530}
531
Kay, Allen M38717942008-09-09 18:37:29 +0300532static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700533{
534 kmem_cache_free(iommu_domain_cache, vaddr);
535}
536
537static inline void * alloc_devinfo_mem(void)
538{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900539 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700540}
541
542static inline void free_devinfo_mem(void *vaddr)
543{
544 kmem_cache_free(iommu_devinfo_cache, vaddr);
545}
546
Joerg Roedel28ccce02015-07-21 14:45:31 +0200547static inline int domain_type_is_si(struct dmar_domain *domain)
548{
549 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
550}
551
Jiang Liu162d1b12014-07-11 14:19:35 +0800552static inline int domain_pfn_supported(struct dmar_domain *domain,
553 unsigned long pfn)
554{
555 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
556
557 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
558}
559
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700560static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800561{
562 unsigned long sagaw;
563 int agaw = -1;
564
565 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700566 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800567 agaw >= 0; agaw--) {
568 if (test_bit(agaw, &sagaw))
569 break;
570 }
571
572 return agaw;
573}
574
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700575/*
576 * Calculate max SAGAW for each iommu.
577 */
578int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
579{
580 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
581}
582
583/*
584 * calculate agaw for each iommu.
585 * "SAGAW" may be different across iommus, use a default agaw, and
586 * get a supported less agaw for iommus that don't support the default agaw.
587 */
588int iommu_calculate_agaw(struct intel_iommu *iommu)
589{
590 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
591}
592
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700593/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800594struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800595{
596 int iommu_id;
597
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700598 /* si_domain and vm domain should not get here. */
Lu Baolufa954e62019-05-25 13:41:28 +0800599 if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_DMA))
600 return NULL;
601
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
Eric Augerb9a7f982019-06-03 08:53:32 +0200732/**
733 * is_downstream_to_pci_bridge - test if a device belongs to the PCI
734 * sub-hierarchy of a candidate PCI-PCI bridge
735 * @dev: candidate PCI device belonging to @bridge PCI sub-hierarchy
736 * @bridge: the candidate PCI-PCI bridge
737 *
738 * Return: true if @dev belongs to @bridge PCI sub-hierarchy, else false.
739 */
740static bool
741is_downstream_to_pci_bridge(struct device *dev, struct device *bridge)
742{
743 struct pci_dev *pdev, *pbridge;
744
745 if (!dev_is_pci(dev) || !dev_is_pci(bridge))
746 return false;
747
748 pdev = to_pci_dev(dev);
749 pbridge = to_pci_dev(bridge);
750
751 if (pbridge->subordinate &&
752 pbridge->subordinate->number <= pdev->bus->number &&
753 pbridge->subordinate->busn_res.end >= pdev->bus->number)
754 return true;
755
756 return false;
757}
758
David Woodhouse156baca2014-03-09 14:00:57 -0700759static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800760{
761 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800762 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700763 struct device *tmp;
Eric Augerb9a7f982019-06-03 08:53:32 +0200764 struct pci_dev *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800765 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800766 int i;
767
David Woodhouse4ed6a542015-05-11 14:59:20 +0100768 if (iommu_dummy(dev))
769 return NULL;
770
David Woodhouse156baca2014-03-09 14:00:57 -0700771 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700772 struct pci_dev *pf_pdev;
773
David Woodhouse156baca2014-03-09 14:00:57 -0700774 pdev = to_pci_dev(dev);
Jon Derrick5823e332017-08-30 15:05:59 -0600775
776#ifdef CONFIG_X86
777 /* VMD child devices currently cannot be handled individually */
778 if (is_vmd(pdev->bus))
779 return NULL;
780#endif
781
Ashok Raj1c387182016-10-21 15:32:05 -0700782 /* VFs aren't listed in scope tables; we need to look up
783 * the PF instead to find the IOMMU. */
784 pf_pdev = pci_physfn(pdev);
785 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700786 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100787 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700788 dev = &ACPI_COMPANION(dev)->dev;
789
Jiang Liu0e242612014-02-19 14:07:34 +0800790 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800791 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700792 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100793 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800794
Jiang Liub683b232014-02-19 14:07:32 +0800795 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700796 drhd->devices_cnt, i, tmp) {
797 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700798 /* For a VF use its original BDF# not that of the PF
799 * which we used for the IOMMU lookup. Strictly speaking
800 * we could do this for all PCI devices; we only need to
801 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100802 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700803 goto got_pdev;
804
David Woodhouse156baca2014-03-09 14:00:57 -0700805 *bus = drhd->devices[i].bus;
806 *devfn = drhd->devices[i].devfn;
807 goto out;
808 }
809
Eric Augerb9a7f982019-06-03 08:53:32 +0200810 if (is_downstream_to_pci_bridge(dev, tmp))
David Woodhouse156baca2014-03-09 14:00:57 -0700811 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100812 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800813
David Woodhouse156baca2014-03-09 14:00:57 -0700814 if (pdev && drhd->include_all) {
815 got_pdev:
816 *bus = pdev->bus->number;
817 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800818 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700819 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800820 }
Jiang Liub683b232014-02-19 14:07:32 +0800821 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700822 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800823 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800824
Jiang Liub683b232014-02-19 14:07:32 +0800825 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800826}
827
Weidong Han5331fe62008-12-08 23:00:00 +0800828static void domain_flush_cache(struct dmar_domain *domain,
829 void *addr, int size)
830{
831 if (!domain->iommu_coherency)
832 clflush_cache_range(addr, size);
833}
834
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700835static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
836{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700837 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000838 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700839 unsigned long flags;
840
841 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000842 context = iommu_context_addr(iommu, bus, devfn, 0);
843 if (context)
844 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700845 spin_unlock_irqrestore(&iommu->lock, flags);
846 return ret;
847}
848
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700849static void free_context_table(struct intel_iommu *iommu)
850{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700851 int i;
852 unsigned long flags;
853 struct context_entry *context;
854
855 spin_lock_irqsave(&iommu->lock, flags);
856 if (!iommu->root_entry) {
857 goto out;
858 }
859 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000860 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700861 if (context)
862 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000863
Lu Baolu765b6a92018-12-10 09:58:55 +0800864 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000865 continue;
866
867 context = iommu_context_addr(iommu, i, 0x80, 0);
868 if (context)
869 free_pgtable_page(context);
870
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700871 }
872 free_pgtable_page(iommu->root_entry);
873 iommu->root_entry = NULL;
874out:
875 spin_unlock_irqrestore(&iommu->lock, flags);
876}
877
David Woodhouseb026fd22009-06-28 10:37:25 +0100878static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000879 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700880{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600881 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700882 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700883 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700884
885 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200886
Jiang Liu162d1b12014-07-11 14:19:35 +0800887 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200888 /* Address beyond IOMMU's addressing capabilities. */
889 return NULL;
890
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700891 parent = domain->pgd;
892
David Woodhouse5cf0a762014-03-19 16:07:49 +0000893 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700894 void *tmp_page;
895
David Woodhouseb026fd22009-06-28 10:37:25 +0100896 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700897 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000898 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100899 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000900 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700901 break;
902
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000903 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100904 uint64_t pteval;
905
Suresh Siddha4c923d42009-10-02 11:01:24 -0700906 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700907
David Woodhouse206a73c2009-07-01 19:30:28 +0100908 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700909 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100910
David Woodhousec85994e2009-07-01 19:21:24 +0100911 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400912 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 +0800913 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100914 /* Someone else set it while we were thinking; use theirs. */
915 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800916 else
David Woodhousec85994e2009-07-01 19:21:24 +0100917 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700918 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000919 if (level == 1)
920 break;
921
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000922 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700923 level--;
924 }
925
David Woodhouse5cf0a762014-03-19 16:07:49 +0000926 if (!*target_level)
927 *target_level = level;
928
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700929 return pte;
930}
931
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100932
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700933/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100934static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
935 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100936 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700937{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600938 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700939 int total = agaw_to_level(domain->agaw);
940 int offset;
941
942 parent = domain->pgd;
943 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100944 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700945 pte = &parent[offset];
946 if (level == total)
947 return pte;
948
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100949 if (!dma_pte_present(pte)) {
950 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700951 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100952 }
953
Yijing Wange16922a2014-05-20 20:37:51 +0800954 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100955 *large_page = total;
956 return pte;
957 }
958
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000959 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700960 total--;
961 }
962 return NULL;
963}
964
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700965/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000966static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +0100967 unsigned long start_pfn,
968 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700969{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600970 unsigned int large_page;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100971 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700972
Jiang Liu162d1b12014-07-11 14:19:35 +0800973 BUG_ON(!domain_pfn_supported(domain, start_pfn));
974 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700975 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100976
David Woodhouse04b18e62009-06-27 19:15:01 +0100977 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700978 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100979 large_page = 1;
980 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100981 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100982 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100983 continue;
984 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100985 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100986 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100987 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100988 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100989 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
990
David Woodhouse310a5ab2009-06-28 18:52:20 +0100991 domain_flush_cache(domain, first_pte,
992 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700993
994 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700995}
996
Alex Williamson3269ee02013-06-15 10:27:19 -0600997static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -0700998 int retain_level, struct dma_pte *pte,
999 unsigned long pfn, unsigned long start_pfn,
1000 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -06001001{
1002 pfn = max(start_pfn, pfn);
1003 pte = &pte[pfn_level_offset(pfn, level)];
1004
1005 do {
1006 unsigned long level_pfn;
1007 struct dma_pte *level_pte;
1008
1009 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
1010 goto next;
1011
David Dillowf7116e12017-01-30 19:11:11 -08001012 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -06001013 level_pte = phys_to_virt(dma_pte_addr(pte));
1014
David Dillowbc24c572017-06-28 19:42:23 -07001015 if (level > 2) {
1016 dma_pte_free_level(domain, level - 1, retain_level,
1017 level_pte, level_pfn, start_pfn,
1018 last_pfn);
1019 }
Alex Williamson3269ee02013-06-15 10:27:19 -06001020
David Dillowbc24c572017-06-28 19:42:23 -07001021 /*
1022 * Free the page table if we're below the level we want to
1023 * retain and the range covers the entire table.
1024 */
1025 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001026 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001027 dma_clear_pte(pte);
1028 domain_flush_cache(domain, pte, sizeof(*pte));
1029 free_pgtable_page(level_pte);
1030 }
1031next:
1032 pfn += level_size(level);
1033 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1034}
1035
David Dillowbc24c572017-06-28 19:42:23 -07001036/*
1037 * clear last level (leaf) ptes and free page table pages below the
1038 * level we wish to keep intact.
1039 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001040static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001041 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001042 unsigned long last_pfn,
1043 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001044{
Jiang Liu162d1b12014-07-11 14:19:35 +08001045 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1046 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001047 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001048
Jiang Liud41a4ad2014-07-11 14:19:34 +08001049 dma_pte_clear_range(domain, start_pfn, last_pfn);
1050
David Woodhousef3a0a522009-06-30 03:40:07 +01001051 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001052 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001053 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001054
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001055 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001056 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001057 free_pgtable_page(domain->pgd);
1058 domain->pgd = NULL;
1059 }
1060}
1061
David Woodhouseea8ea462014-03-05 17:09:32 +00001062/* When a page at a given level is being unlinked from its parent, we don't
1063 need to *modify* it at all. All we need to do is make a list of all the
1064 pages which can be freed just as soon as we've flushed the IOTLB and we
1065 know the hardware page-walk will no longer touch them.
1066 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1067 be freed. */
1068static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1069 int level, struct dma_pte *pte,
1070 struct page *freelist)
1071{
1072 struct page *pg;
1073
1074 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1075 pg->freelist = freelist;
1076 freelist = pg;
1077
1078 if (level == 1)
1079 return freelist;
1080
Jiang Liuadeb2592014-04-09 10:20:39 +08001081 pte = page_address(pg);
1082 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001083 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1084 freelist = dma_pte_list_pagetables(domain, level - 1,
1085 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001086 pte++;
1087 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001088
1089 return freelist;
1090}
1091
1092static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1093 struct dma_pte *pte, unsigned long pfn,
1094 unsigned long start_pfn,
1095 unsigned long last_pfn,
1096 struct page *freelist)
1097{
1098 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1099
1100 pfn = max(start_pfn, pfn);
1101 pte = &pte[pfn_level_offset(pfn, level)];
1102
1103 do {
1104 unsigned long level_pfn;
1105
1106 if (!dma_pte_present(pte))
1107 goto next;
1108
1109 level_pfn = pfn & level_mask(level);
1110
1111 /* If range covers entire pagetable, free it */
1112 if (start_pfn <= level_pfn &&
1113 last_pfn >= level_pfn + level_size(level) - 1) {
1114 /* These suborbinate page tables are going away entirely. Don't
1115 bother to clear them; we're just going to *free* them. */
1116 if (level > 1 && !dma_pte_superpage(pte))
1117 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1118
1119 dma_clear_pte(pte);
1120 if (!first_pte)
1121 first_pte = pte;
1122 last_pte = pte;
1123 } else if (level > 1) {
1124 /* Recurse down into a level that isn't *entirely* obsolete */
1125 freelist = dma_pte_clear_level(domain, level - 1,
1126 phys_to_virt(dma_pte_addr(pte)),
1127 level_pfn, start_pfn, last_pfn,
1128 freelist);
1129 }
1130next:
1131 pfn += level_size(level);
1132 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1133
1134 if (first_pte)
1135 domain_flush_cache(domain, first_pte,
1136 (void *)++last_pte - (void *)first_pte);
1137
1138 return freelist;
1139}
1140
1141/* We can't just free the pages because the IOMMU may still be walking
1142 the page tables, and may have cached the intermediate levels. The
1143 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001144static struct page *domain_unmap(struct dmar_domain *domain,
1145 unsigned long start_pfn,
1146 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001147{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001148 struct page *freelist;
David Woodhouseea8ea462014-03-05 17:09:32 +00001149
Jiang Liu162d1b12014-07-11 14:19:35 +08001150 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1151 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001152 BUG_ON(start_pfn > last_pfn);
1153
1154 /* we don't need lock here; nobody else touches the iova range */
1155 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1156 domain->pgd, 0, start_pfn, last_pfn, NULL);
1157
1158 /* free pgd */
1159 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1160 struct page *pgd_page = virt_to_page(domain->pgd);
1161 pgd_page->freelist = freelist;
1162 freelist = pgd_page;
1163
1164 domain->pgd = NULL;
1165 }
1166
1167 return freelist;
1168}
1169
Joerg Roedelb6904202015-08-13 11:32:18 +02001170static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001171{
1172 struct page *pg;
1173
1174 while ((pg = freelist)) {
1175 freelist = pg->freelist;
1176 free_pgtable_page(page_address(pg));
1177 }
1178}
1179
Joerg Roedel13cf0172017-08-11 11:40:10 +02001180static void iova_entry_free(unsigned long data)
1181{
1182 struct page *freelist = (struct page *)data;
1183
1184 dma_free_pagelist(freelist);
1185}
1186
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001187/* iommu handling */
1188static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1189{
1190 struct root_entry *root;
1191 unsigned long flags;
1192
Suresh Siddha4c923d42009-10-02 11:01:24 -07001193 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001194 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001195 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001196 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001197 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001198 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001199
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001200 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001201
1202 spin_lock_irqsave(&iommu->lock, flags);
1203 iommu->root_entry = root;
1204 spin_unlock_irqrestore(&iommu->lock, flags);
1205
1206 return 0;
1207}
1208
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001209static void iommu_set_root_entry(struct intel_iommu *iommu)
1210{
David Woodhouse03ecc322015-02-13 14:35:21 +00001211 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001212 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001213 unsigned long flag;
1214
David Woodhouse03ecc322015-02-13 14:35:21 +00001215 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001216 if (sm_supported(iommu))
1217 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001218
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001219 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001220 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001221
David Woodhousec416daa2009-05-10 20:30:58 +01001222 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001223
1224 /* Make sure hardware complete it */
1225 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001226 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001227
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001228 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001229}
1230
Lu Baolu6f7db752018-12-10 09:59:00 +08001231void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001232{
1233 u32 val;
1234 unsigned long flag;
1235
David Woodhouse9af88142009-02-13 23:18:03 +00001236 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001237 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001238
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001239 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001240 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001241
1242 /* Make sure hardware complete it */
1243 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001244 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001245
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001246 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001247}
1248
1249/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001250static void __iommu_flush_context(struct intel_iommu *iommu,
1251 u16 did, u16 source_id, u8 function_mask,
1252 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001253{
1254 u64 val = 0;
1255 unsigned long flag;
1256
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001257 switch (type) {
1258 case DMA_CCMD_GLOBAL_INVL:
1259 val = DMA_CCMD_GLOBAL_INVL;
1260 break;
1261 case DMA_CCMD_DOMAIN_INVL:
1262 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1263 break;
1264 case DMA_CCMD_DEVICE_INVL:
1265 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1266 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1267 break;
1268 default:
1269 BUG();
1270 }
1271 val |= DMA_CCMD_ICC;
1272
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001273 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001274 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1275
1276 /* Make sure hardware complete it */
1277 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1278 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1279
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001280 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001281}
1282
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001283/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001284static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1285 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001286{
1287 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1288 u64 val = 0, val_iva = 0;
1289 unsigned long flag;
1290
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001291 switch (type) {
1292 case DMA_TLB_GLOBAL_FLUSH:
1293 /* global flush doesn't need set IVA_REG */
1294 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1295 break;
1296 case DMA_TLB_DSI_FLUSH:
1297 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1298 break;
1299 case DMA_TLB_PSI_FLUSH:
1300 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001301 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001302 val_iva = size_order | addr;
1303 break;
1304 default:
1305 BUG();
1306 }
1307 /* Note: set drain read/write */
1308#if 0
1309 /*
1310 * This is probably to be super secure.. Looks like we can
1311 * ignore it without any impact.
1312 */
1313 if (cap_read_drain(iommu->cap))
1314 val |= DMA_TLB_READ_DRAIN;
1315#endif
1316 if (cap_write_drain(iommu->cap))
1317 val |= DMA_TLB_WRITE_DRAIN;
1318
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001319 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001320 /* Note: Only uses first TLB reg currently */
1321 if (val_iva)
1322 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1323 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1324
1325 /* Make sure hardware complete it */
1326 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1327 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1328
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001329 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001330
1331 /* check IOTLB invalidation granularity */
1332 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001333 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001334 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001335 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001336 (unsigned long long)DMA_TLB_IIRG(type),
1337 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001338}
1339
David Woodhouse64ae8922014-03-09 12:52:30 -07001340static struct device_domain_info *
1341iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1342 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001343{
Yu Zhao93a23a72009-05-18 13:51:37 +08001344 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001345
Joerg Roedel55d94042015-07-22 16:50:40 +02001346 assert_spin_locked(&device_domain_lock);
1347
Yu Zhao93a23a72009-05-18 13:51:37 +08001348 if (!iommu->qi)
1349 return NULL;
1350
Yu Zhao93a23a72009-05-18 13:51:37 +08001351 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001352 if (info->iommu == iommu && info->bus == bus &&
1353 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001354 if (info->ats_supported && info->dev)
1355 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001356 break;
1357 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001358
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001359 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001360}
1361
Omer Peleg0824c592016-04-20 19:03:35 +03001362static void domain_update_iotlb(struct dmar_domain *domain)
1363{
1364 struct device_domain_info *info;
1365 bool has_iotlb_device = false;
1366
1367 assert_spin_locked(&device_domain_lock);
1368
1369 list_for_each_entry(info, &domain->devices, link) {
1370 struct pci_dev *pdev;
1371
1372 if (!info->dev || !dev_is_pci(info->dev))
1373 continue;
1374
1375 pdev = to_pci_dev(info->dev);
1376 if (pdev->ats_enabled) {
1377 has_iotlb_device = true;
1378 break;
1379 }
1380 }
1381
1382 domain->has_iotlb_device = has_iotlb_device;
1383}
1384
Yu Zhao93a23a72009-05-18 13:51:37 +08001385static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1386{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001387 struct pci_dev *pdev;
1388
Omer Peleg0824c592016-04-20 19:03:35 +03001389 assert_spin_locked(&device_domain_lock);
1390
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001391 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001392 return;
1393
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001394 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001395 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1396 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1397 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1398 * reserved, which should be set to 0.
1399 */
1400 if (!ecap_dit(info->iommu->ecap))
1401 info->pfsid = 0;
1402 else {
1403 struct pci_dev *pf_pdev;
1404
1405 /* pdev will be returned if device is not a vf */
1406 pf_pdev = pci_physfn(pdev);
Heiner Kallweitcc49baa2019-04-24 21:16:10 +02001407 info->pfsid = pci_dev_id(pf_pdev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001408 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001409
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001410#ifdef CONFIG_INTEL_IOMMU_SVM
1411 /* The PCIe spec, in its wisdom, declares that the behaviour of
1412 the device if you enable PASID support after ATS support is
1413 undefined. So always enable PASID support on devices which
1414 have it, even if we can't yet know if we're ever going to
1415 use it. */
1416 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1417 info->pasid_enabled = 1;
1418
Kuppuswamy Sathyanarayanan1b84778a2019-02-19 11:04:52 -08001419 if (info->pri_supported &&
1420 (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
1421 !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001422 info->pri_enabled = 1;
1423#endif
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001424 if (!pdev->untrusted && info->ats_supported &&
Kuppuswamy Sathyanarayanan61363c12019-02-19 11:06:10 -08001425 pci_ats_page_aligned(pdev) &&
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001426 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001427 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001428 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001429 info->ats_qdep = pci_ats_queue_depth(pdev);
1430 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001431}
1432
1433static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1434{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001435 struct pci_dev *pdev;
1436
Omer Peleg0824c592016-04-20 19:03:35 +03001437 assert_spin_locked(&device_domain_lock);
1438
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001439 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001440 return;
1441
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001442 pdev = to_pci_dev(info->dev);
1443
1444 if (info->ats_enabled) {
1445 pci_disable_ats(pdev);
1446 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001447 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001448 }
1449#ifdef CONFIG_INTEL_IOMMU_SVM
1450 if (info->pri_enabled) {
1451 pci_disable_pri(pdev);
1452 info->pri_enabled = 0;
1453 }
1454 if (info->pasid_enabled) {
1455 pci_disable_pasid(pdev);
1456 info->pasid_enabled = 0;
1457 }
1458#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001459}
1460
1461static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1462 u64 addr, unsigned mask)
1463{
1464 u16 sid, qdep;
1465 unsigned long flags;
1466 struct device_domain_info *info;
1467
Omer Peleg0824c592016-04-20 19:03:35 +03001468 if (!domain->has_iotlb_device)
1469 return;
1470
Yu Zhao93a23a72009-05-18 13:51:37 +08001471 spin_lock_irqsave(&device_domain_lock, flags);
1472 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001473 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001474 continue;
1475
1476 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001477 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001478 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1479 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001480 }
1481 spin_unlock_irqrestore(&device_domain_lock, flags);
1482}
1483
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001484static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1485 struct dmar_domain *domain,
1486 unsigned long pfn, unsigned int pages,
1487 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001488{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001489 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001490 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001491 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001492
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001493 BUG_ON(pages == 0);
1494
David Woodhouseea8ea462014-03-05 17:09:32 +00001495 if (ih)
1496 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001497 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001498 * Fallback to domain selective flush if no PSI support or the size is
1499 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001500 * PSI requires page size to be 2 ^ x, and the base address is naturally
1501 * aligned to the size
1502 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001503 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1504 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001505 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001506 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001507 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001508 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001509
1510 /*
Nadav Amit82653632010-04-01 13:24:40 +03001511 * In caching mode, changes of pages from non-present to present require
1512 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001513 */
Nadav Amit82653632010-04-01 13:24:40 +03001514 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001515 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001516}
1517
Peter Xueed91a02018-05-04 10:34:52 +08001518/* Notification for newly created mappings */
1519static inline void __mapping_notify_one(struct intel_iommu *iommu,
1520 struct dmar_domain *domain,
1521 unsigned long pfn, unsigned int pages)
1522{
1523 /* It's a non-present to present mapping. Only flush if caching mode */
1524 if (cap_caching_mode(iommu->cap))
1525 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1526 else
1527 iommu_flush_write_buffer(iommu);
1528}
1529
Joerg Roedel13cf0172017-08-11 11:40:10 +02001530static void iommu_flush_iova(struct iova_domain *iovad)
1531{
1532 struct dmar_domain *domain;
1533 int idx;
1534
1535 domain = container_of(iovad, struct dmar_domain, iovad);
1536
1537 for_each_domain_iommu(idx, domain) {
1538 struct intel_iommu *iommu = g_iommus[idx];
1539 u16 did = domain->iommu_did[iommu->seq_id];
1540
1541 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
1542
1543 if (!cap_caching_mode(iommu->cap))
1544 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1545 0, MAX_AGAW_PFN_WIDTH);
1546 }
1547}
1548
mark grossf8bab732008-02-08 04:18:38 -08001549static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1550{
1551 u32 pmen;
1552 unsigned long flags;
1553
Lu Baolu5bb71fc72019-03-20 09:58:33 +08001554 if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
1555 return;
1556
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001557 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001558 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1559 pmen &= ~DMA_PMEN_EPM;
1560 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1561
1562 /* wait for the protected region status bit to clear */
1563 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1564 readl, !(pmen & DMA_PMEN_PRS), pmen);
1565
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001566 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001567}
1568
Jiang Liu2a41cce2014-07-11 14:19:33 +08001569static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001570{
1571 u32 sts;
1572 unsigned long flags;
1573
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001574 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001575 iommu->gcmd |= DMA_GCMD_TE;
1576 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001577
1578 /* Make sure hardware complete it */
1579 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001580 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001581
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001582 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001583}
1584
Jiang Liu2a41cce2014-07-11 14:19:33 +08001585static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001586{
1587 u32 sts;
1588 unsigned long flag;
1589
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001590 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001591 iommu->gcmd &= ~DMA_GCMD_TE;
1592 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1593
1594 /* Make sure hardware complete it */
1595 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001596 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001597
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001598 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001599}
1600
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001601
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001602static int iommu_init_domains(struct intel_iommu *iommu)
1603{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001604 u32 ndomains, nlongs;
1605 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001606
1607 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001608 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001609 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001610 nlongs = BITS_TO_LONGS(ndomains);
1611
Donald Dutile94a91b502009-08-20 16:51:34 -04001612 spin_lock_init(&iommu->lock);
1613
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001614 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1615 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001616 pr_err("%s: Allocating domain id array failed\n",
1617 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001618 return -ENOMEM;
1619 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001620
Wei Yang86f004c2016-05-21 02:41:51 +00001621 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001622 iommu->domains = kzalloc(size, GFP_KERNEL);
1623
1624 if (iommu->domains) {
1625 size = 256 * sizeof(struct dmar_domain *);
1626 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1627 }
1628
1629 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001630 pr_err("%s: Allocating domain array failed\n",
1631 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001632 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001633 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001634 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001635 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001636 return -ENOMEM;
1637 }
1638
Joerg Roedel8bf47812015-07-21 10:41:21 +02001639
1640
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001641 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001642 * If Caching mode is set, then invalid translations are tagged
1643 * with domain-id 0, hence we need to pre-allocate it. We also
1644 * use domain-id 0 as a marker for non-allocated domain-id, so
1645 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001646 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001647 set_bit(0, iommu->domain_ids);
1648
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001649 /*
1650 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1651 * entry for first-level or pass-through translation modes should
1652 * be programmed with a domain id different from those used for
1653 * second-level or nested translation. We reserve a domain id for
1654 * this purpose.
1655 */
1656 if (sm_supported(iommu))
1657 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1658
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001659 return 0;
1660}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001661
Jiang Liuffebeb42014-11-09 22:48:02 +08001662static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001663{
Joerg Roedel29a27712015-07-21 17:17:12 +02001664 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001665 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001666
Joerg Roedel29a27712015-07-21 17:17:12 +02001667 if (!iommu->domains || !iommu->domain_ids)
1668 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001669
Joerg Roedel55d94042015-07-22 16:50:40 +02001670 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001671 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
Joerg Roedel29a27712015-07-21 17:17:12 +02001672 if (info->iommu != iommu)
1673 continue;
1674
1675 if (!info->dev || !info->domain)
1676 continue;
1677
Joerg Roedelbea64032016-11-08 15:08:26 +01001678 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001679 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001680 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001681
1682 if (iommu->gcmd & DMA_GCMD_TE)
1683 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001684}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001685
Jiang Liuffebeb42014-11-09 22:48:02 +08001686static void free_dmar_iommu(struct intel_iommu *iommu)
1687{
1688 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001689 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001690 int i;
1691
1692 for (i = 0; i < elems; i++)
1693 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001694 kfree(iommu->domains);
1695 kfree(iommu->domain_ids);
1696 iommu->domains = NULL;
1697 iommu->domain_ids = NULL;
1698 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001699
Weidong Hand9630fe2008-12-08 11:06:32 +08001700 g_iommus[iommu->seq_id] = NULL;
1701
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001702 /* free context mapping */
1703 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001704
1705#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001706 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001707 if (ecap_prs(iommu->ecap))
1708 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001709 }
David Woodhouse8a94ade2015-03-24 14:54:56 +00001710#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711}
1712
Jiang Liuab8dfe22014-07-11 14:19:27 +08001713static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001714{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001715 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001716
1717 domain = alloc_domain_mem();
1718 if (!domain)
1719 return NULL;
1720
Jiang Liuab8dfe22014-07-11 14:19:27 +08001721 memset(domain, 0, sizeof(*domain));
Anshuman Khandual98fa15f2019-03-05 15:42:58 -08001722 domain->nid = NUMA_NO_NODE;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001723 domain->flags = flags;
Omer Peleg0824c592016-04-20 19:03:35 +03001724 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001725 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001726
1727 return domain;
1728}
1729
Joerg Roedeld160aca2015-07-22 11:52:53 +02001730/* Must be called with iommu->lock */
1731static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001732 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001733{
Jiang Liu44bde612014-07-11 14:19:29 +08001734 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001735 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001736
Joerg Roedel55d94042015-07-22 16:50:40 +02001737 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001738 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001739
Joerg Roedel29a27712015-07-21 17:17:12 +02001740 domain->iommu_refcnt[iommu->seq_id] += 1;
1741 domain->iommu_count += 1;
1742 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001743 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001744 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1745
1746 if (num >= ndomains) {
1747 pr_err("%s: No free domain ids\n", iommu->name);
1748 domain->iommu_refcnt[iommu->seq_id] -= 1;
1749 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001750 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001751 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001752
Joerg Roedeld160aca2015-07-22 11:52:53 +02001753 set_bit(num, iommu->domain_ids);
1754 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001755
Joerg Roedeld160aca2015-07-22 11:52:53 +02001756 domain->iommu_did[iommu->seq_id] = num;
1757 domain->nid = iommu->node;
1758
Jiang Liufb170fb2014-07-11 14:19:28 +08001759 domain_update_iommu_cap(domain);
1760 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001761
Joerg Roedel55d94042015-07-22 16:50:40 +02001762 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001763}
1764
1765static int domain_detach_iommu(struct dmar_domain *domain,
1766 struct intel_iommu *iommu)
1767{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001768 int num, count;
Jiang Liufb170fb2014-07-11 14:19:28 +08001769
Joerg Roedel55d94042015-07-22 16:50:40 +02001770 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001771 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001772
Joerg Roedel29a27712015-07-21 17:17:12 +02001773 domain->iommu_refcnt[iommu->seq_id] -= 1;
1774 count = --domain->iommu_count;
1775 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001776 num = domain->iommu_did[iommu->seq_id];
1777 clear_bit(num, iommu->domain_ids);
1778 set_iommu_domain(iommu, num, NULL);
1779
Jiang Liufb170fb2014-07-11 14:19:28 +08001780 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001781 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001782 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001783
1784 return count;
1785}
1786
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001787static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001788static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001789
Joseph Cihula51a63e62011-03-21 11:04:24 -07001790static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001791{
1792 struct pci_dev *pdev = NULL;
1793 struct iova *iova;
1794 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001795
Zhen Leiaa3ac942017-09-21 16:52:45 +01001796 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001797
Mark Gross8a443df2008-03-04 14:59:31 -08001798 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1799 &reserved_rbtree_key);
1800
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001801 /* IOAPIC ranges shouldn't be accessed by DMA */
1802 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1803 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001804 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001805 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001806 return -ENODEV;
1807 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001808
1809 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1810 for_each_pci_dev(pdev) {
1811 struct resource *r;
1812
1813 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1814 r = &pdev->resource[i];
1815 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1816 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001817 iova = reserve_iova(&reserved_iova_list,
1818 IOVA_PFN(r->start),
1819 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001820 if (!iova) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06001821 pci_err(pdev, "Reserve iova for %pR failed\n", r);
Joseph Cihula51a63e62011-03-21 11:04:24 -07001822 return -ENODEV;
1823 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001824 }
1825 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001826 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001827}
1828
1829static void domain_reserve_special_ranges(struct dmar_domain *domain)
1830{
1831 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1832}
1833
1834static inline int guestwidth_to_adjustwidth(int gaw)
1835{
1836 int agaw;
1837 int r = (gaw - 12) % 9;
1838
1839 if (r == 0)
1840 agaw = gaw;
1841 else
1842 agaw = gaw + 9 - r;
1843 if (agaw > 64)
1844 agaw = 64;
1845 return agaw;
1846}
1847
Joerg Roedeldc534b22015-07-22 12:44:02 +02001848static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1849 int guest_width)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001850{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001851 int adjust_width, agaw;
1852 unsigned long sagaw;
Joerg Roedel13cf0172017-08-11 11:40:10 +02001853 int err;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001854
Zhen Leiaa3ac942017-09-21 16:52:45 +01001855 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001856
1857 err = init_iova_flush_queue(&domain->iovad,
1858 iommu_flush_iova, iova_entry_free);
1859 if (err)
1860 return err;
1861
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001862 domain_reserve_special_ranges(domain);
1863
1864 /* calculate AGAW */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001865 if (guest_width > cap_mgaw(iommu->cap))
1866 guest_width = cap_mgaw(iommu->cap);
1867 domain->gaw = guest_width;
1868 adjust_width = guestwidth_to_adjustwidth(guest_width);
1869 agaw = width_to_agaw(adjust_width);
1870 sagaw = cap_sagaw(iommu->cap);
1871 if (!test_bit(agaw, &sagaw)) {
1872 /* hardware doesn't support it, choose a bigger one */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001873 pr_debug("Hardware doesn't support agaw %d\n", agaw);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001874 agaw = find_next_bit(&sagaw, 5, agaw);
1875 if (agaw >= 5)
1876 return -ENODEV;
1877 }
1878 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001879
Weidong Han8e6040972008-12-08 15:49:06 +08001880 if (ecap_coherent(iommu->ecap))
1881 domain->iommu_coherency = 1;
1882 else
1883 domain->iommu_coherency = 0;
1884
Sheng Yang58c610b2009-03-18 15:33:05 +08001885 if (ecap_sc_support(iommu->ecap))
1886 domain->iommu_snooping = 1;
1887 else
1888 domain->iommu_snooping = 0;
1889
David Woodhouse214e39a2014-03-19 10:38:49 +00001890 if (intel_iommu_superpage)
1891 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1892 else
1893 domain->iommu_superpage = 0;
1894
Suresh Siddha4c923d42009-10-02 11:01:24 -07001895 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001896
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001897 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001898 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001899 if (!domain->pgd)
1900 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001901 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001902 return 0;
1903}
1904
1905static void domain_exit(struct dmar_domain *domain)
1906{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001907 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001908
Joerg Roedeld160aca2015-07-22 11:52:53 +02001909 /* Remove associated devices and clear attached or cached domains */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001910 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001911
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001912 /* destroy iovas */
1913 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001914
David Woodhouseea8ea462014-03-05 17:09:32 +00001915 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001916
David Woodhouseea8ea462014-03-05 17:09:32 +00001917 dma_free_pagelist(freelist);
1918
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001919 free_domain_mem(domain);
1920}
1921
Lu Baolu7373a8c2018-12-10 09:59:03 +08001922/*
1923 * Get the PASID directory size for scalable mode context entry.
1924 * Value of X in the PDTS field of a scalable mode context entry
1925 * indicates PASID directory with 2^(X + 7) entries.
1926 */
1927static inline unsigned long context_get_sm_pds(struct pasid_table *table)
1928{
1929 int pds, max_pde;
1930
1931 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
1932 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
1933 if (pds < 7)
1934 return 0;
1935
1936 return pds - 7;
1937}
1938
1939/*
1940 * Set the RID_PASID field of a scalable mode context entry. The
1941 * IOMMU hardware will use the PASID value set in this field for
1942 * DMA translations of DMA requests without PASID.
1943 */
1944static inline void
1945context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
1946{
1947 context->hi |= pasid & ((1 << 20) - 1);
1948 context->hi |= (1 << 20);
1949}
1950
1951/*
1952 * Set the DTE(Device-TLB Enable) field of a scalable mode context
1953 * entry.
1954 */
1955static inline void context_set_sm_dte(struct context_entry *context)
1956{
1957 context->lo |= (1 << 2);
1958}
1959
1960/*
1961 * Set the PRE(Page Request Enable) field of a scalable mode context
1962 * entry.
1963 */
1964static inline void context_set_sm_pre(struct context_entry *context)
1965{
1966 context->lo |= (1 << 4);
1967}
1968
1969/* Convert value to context PASID directory size field coding. */
1970#define context_pdts(pds) (((pds) & 0x7) << 9)
1971
David Woodhouse64ae8922014-03-09 12:52:30 -07001972static int domain_context_mapping_one(struct dmar_domain *domain,
1973 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08001974 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001975 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001976{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001977 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02001978 int translation = CONTEXT_TT_MULTI_LEVEL;
1979 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001980 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001981 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08001982 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02001983
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001984 WARN_ON(did == 0);
1985
Joerg Roedel28ccce02015-07-21 14:45:31 +02001986 if (hw_pass_through && domain_type_is_si(domain))
1987 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001988
1989 pr_debug("Set context mapping for %02x:%02x.%d\n",
1990 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001991
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001992 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08001993
Joerg Roedel55d94042015-07-22 16:50:40 +02001994 spin_lock_irqsave(&device_domain_lock, flags);
1995 spin_lock(&iommu->lock);
1996
1997 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00001998 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001999 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02002000 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002001
Joerg Roedel55d94042015-07-22 16:50:40 +02002002 ret = 0;
2003 if (context_present(context))
2004 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002005
Xunlei Pangaec0e862016-12-05 20:09:07 +08002006 /*
2007 * For kdump cases, old valid entries may be cached due to the
2008 * in-flight DMA and copied pgtable, but there is no unmapping
2009 * behaviour for them, thus we need an explicit cache flush for
2010 * the newly-mapped device. For kdump, at this point, the device
2011 * is supposed to finish reset at its driver probe stage, so no
2012 * in-flight DMA will exist, and we don't need to worry anymore
2013 * hereafter.
2014 */
2015 if (context_copied(context)) {
2016 u16 did_old = context_domain_id(context);
2017
Christos Gkekasb117e032017-10-08 23:33:31 +01002018 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002019 iommu->flush.flush_context(iommu, did_old,
2020 (((u16)bus) << 8) | devfn,
2021 DMA_CCMD_MASK_NOBIT,
2022 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002023 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2024 DMA_TLB_DSI_FLUSH);
2025 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002026 }
2027
Joerg Roedelde24e552015-07-21 14:53:04 +02002028 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002029
Lu Baolu7373a8c2018-12-10 09:59:03 +08002030 if (sm_supported(iommu)) {
2031 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002032
Lu Baolu7373a8c2018-12-10 09:59:03 +08002033 WARN_ON(!table);
2034
2035 /* Setup the PASID DIR pointer: */
2036 pds = context_get_sm_pds(table);
2037 context->lo = (u64)virt_to_phys(table->table) |
2038 context_pdts(pds);
2039
2040 /* Setup the RID_PASID field: */
2041 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2042
2043 /*
2044 * Setup the Device-TLB enable bit and Page request
2045 * Enable bit:
2046 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002047 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002048 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002049 context_set_sm_dte(context);
2050 if (info && info->pri_supported)
2051 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002052 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002053 struct dma_pte *pgd = domain->pgd;
2054 int agaw;
2055
2056 context_set_domain_id(context, did);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002057
2058 if (translation != CONTEXT_TT_PASS_THROUGH) {
2059 /*
2060 * Skip top levels of page tables for iommu which has
2061 * less agaw than default. Unnecessary for PT mode.
2062 */
2063 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2064 ret = -ENOMEM;
2065 pgd = phys_to_virt(dma_pte_addr(pgd));
2066 if (!dma_pte_present(pgd))
2067 goto out_unlock;
2068 }
2069
2070 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2071 if (info && info->ats_supported)
2072 translation = CONTEXT_TT_DEV_IOTLB;
2073 else
2074 translation = CONTEXT_TT_MULTI_LEVEL;
2075
2076 context_set_address_root(context, virt_to_phys(pgd));
2077 context_set_address_width(context, agaw);
2078 } else {
2079 /*
2080 * In pass through mode, AW must be programmed to
2081 * indicate the largest AGAW value supported by
2082 * hardware. And ASR is ignored by hardware.
2083 */
2084 context_set_address_width(context, iommu->msagaw);
2085 }
Lu Baolu41b80db2019-03-01 11:23:11 +08002086
2087 context_set_translation_type(context, translation);
Yu Zhao93a23a72009-05-18 13:51:37 +08002088 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002089
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002090 context_set_fault_enable(context);
2091 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08002092 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002093
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002094 /*
2095 * It's a non-present to present mapping. If hardware doesn't cache
2096 * non-present entry we only need to flush the write-buffer. If the
2097 * _does_ cache non-present entries, then it does so in the special
2098 * domain #0, which we have to flush:
2099 */
2100 if (cap_caching_mode(iommu->cap)) {
2101 iommu->flush.flush_context(iommu, 0,
2102 (((u16)bus) << 8) | devfn,
2103 DMA_CCMD_MASK_NOBIT,
2104 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002105 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002106 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002107 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002108 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002109 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002110
Joerg Roedel55d94042015-07-22 16:50:40 +02002111 ret = 0;
2112
2113out_unlock:
2114 spin_unlock(&iommu->lock);
2115 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002116
Wei Yang5c365d12016-07-13 13:53:21 +00002117 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002118}
2119
Alex Williamson579305f2014-07-03 09:51:43 -06002120struct domain_context_mapping_data {
2121 struct dmar_domain *domain;
2122 struct intel_iommu *iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002123 struct pasid_table *table;
Alex Williamson579305f2014-07-03 09:51:43 -06002124};
2125
2126static int domain_context_mapping_cb(struct pci_dev *pdev,
2127 u16 alias, void *opaque)
2128{
2129 struct domain_context_mapping_data *data = opaque;
2130
2131 return domain_context_mapping_one(data->domain, data->iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002132 data->table, PCI_BUS_NUM(alias),
2133 alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06002134}
2135
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002136static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002137domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002138{
Lu Baoluca6e3222018-12-10 09:59:02 +08002139 struct domain_context_mapping_data data;
2140 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002141 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002142 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002143
David Woodhousee1f167f2014-03-09 15:24:46 -07002144 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002145 if (!iommu)
2146 return -ENODEV;
2147
Lu Baoluca6e3222018-12-10 09:59:02 +08002148 table = intel_pasid_get_table(dev);
2149
Alex Williamson579305f2014-07-03 09:51:43 -06002150 if (!dev_is_pci(dev))
Lu Baoluca6e3222018-12-10 09:59:02 +08002151 return domain_context_mapping_one(domain, iommu, table,
2152 bus, devfn);
Alex Williamson579305f2014-07-03 09:51:43 -06002153
2154 data.domain = domain;
2155 data.iommu = iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002156 data.table = table;
Alex Williamson579305f2014-07-03 09:51:43 -06002157
2158 return pci_for_each_dma_alias(to_pci_dev(dev),
2159 &domain_context_mapping_cb, &data);
2160}
2161
2162static int domain_context_mapped_cb(struct pci_dev *pdev,
2163 u16 alias, void *opaque)
2164{
2165 struct intel_iommu *iommu = opaque;
2166
2167 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002168}
2169
David Woodhousee1f167f2014-03-09 15:24:46 -07002170static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002171{
Weidong Han5331fe62008-12-08 23:00:00 +08002172 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002173 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002174
David Woodhousee1f167f2014-03-09 15:24:46 -07002175 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002176 if (!iommu)
2177 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002178
Alex Williamson579305f2014-07-03 09:51:43 -06002179 if (!dev_is_pci(dev))
2180 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002181
Alex Williamson579305f2014-07-03 09:51:43 -06002182 return !pci_for_each_dma_alias(to_pci_dev(dev),
2183 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002184}
2185
Fenghua Yuf5329592009-08-04 15:09:37 -07002186/* Returns a number of VTD pages, but aligned to MM page size */
2187static inline unsigned long aligned_nrpages(unsigned long host_addr,
2188 size_t size)
2189{
2190 host_addr &= ~PAGE_MASK;
2191 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2192}
2193
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002194/* Return largest possible superpage level for a given mapping */
2195static inline int hardware_largepage_caps(struct dmar_domain *domain,
2196 unsigned long iov_pfn,
2197 unsigned long phy_pfn,
2198 unsigned long pages)
2199{
2200 int support, level = 1;
2201 unsigned long pfnmerge;
2202
2203 support = domain->iommu_superpage;
2204
2205 /* To use a large page, the virtual *and* physical addresses
2206 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2207 of them will mean we have to use smaller pages. So just
2208 merge them and check both at once. */
2209 pfnmerge = iov_pfn | phy_pfn;
2210
2211 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2212 pages >>= VTD_STRIDE_SHIFT;
2213 if (!pages)
2214 break;
2215 pfnmerge >>= VTD_STRIDE_SHIFT;
2216 level++;
2217 support--;
2218 }
2219 return level;
2220}
2221
David Woodhouse9051aa02009-06-29 12:30:54 +01002222static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2223 struct scatterlist *sg, unsigned long phys_pfn,
2224 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002225{
2226 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002227 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002228 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002229 unsigned int largepage_lvl = 0;
2230 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01002231
Jiang Liu162d1b12014-07-11 14:19:35 +08002232 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002233
2234 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2235 return -EINVAL;
2236
2237 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
2238
Jiang Liucc4f14a2014-11-26 09:42:10 +08002239 if (!sg) {
2240 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01002241 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
2242 }
2243
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002244 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002245 uint64_t tmp;
2246
David Woodhousee1605492009-06-29 11:17:38 +01002247 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002248 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2249
Fenghua Yuf5329592009-08-04 15:09:37 -07002250 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002251 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002252 sg->dma_length = sg->length;
Robin Murphy29a90b72017-09-28 15:14:01 +01002253 pteval = (sg_phys(sg) - pgoff) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002254 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002255 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002256
David Woodhousee1605492009-06-29 11:17:38 +01002257 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002258 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2259
David Woodhouse5cf0a762014-03-19 16:07:49 +00002260 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002261 if (!pte)
2262 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002263 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002264 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002265 unsigned long nr_superpages, end_pfn;
2266
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002267 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002268 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002269
2270 nr_superpages = sg_res / lvl_pages;
2271 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2272
Jiang Liud41a4ad2014-07-11 14:19:34 +08002273 /*
2274 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002275 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002276 * We're adding new large pages, so make sure
2277 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002278 */
David Dillowbc24c572017-06-28 19:42:23 -07002279 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2280 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002281 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002282 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002283 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002284
David Woodhousee1605492009-06-29 11:17:38 +01002285 }
2286 /* We don't need lock here, nobody else
2287 * touches the iova range
2288 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002289 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002290 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002291 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002292 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2293 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002294 if (dumps) {
2295 dumps--;
2296 debug_dma_dump_mappings(NULL);
2297 }
2298 WARN_ON(1);
2299 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002300
2301 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2302
2303 BUG_ON(nr_pages < lvl_pages);
2304 BUG_ON(sg_res < lvl_pages);
2305
2306 nr_pages -= lvl_pages;
2307 iov_pfn += lvl_pages;
2308 phys_pfn += lvl_pages;
2309 pteval += lvl_pages * VTD_PAGE_SIZE;
2310 sg_res -= lvl_pages;
2311
2312 /* If the next PTE would be the first in a new page, then we
2313 need to flush the cache on the entries we've just written.
2314 And then we'll need to recalculate 'pte', so clear it and
2315 let it get set again in the if (!pte) block above.
2316
2317 If we're done (!nr_pages) we need to flush the cache too.
2318
2319 Also if we've been setting superpages, we may need to
2320 recalculate 'pte' and switch back to smaller pages for the
2321 end of the mapping, if the trailing size is not enough to
2322 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002323 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002324 if (!nr_pages || first_pte_in_page(pte) ||
2325 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002326 domain_flush_cache(domain, first_pte,
2327 (void *)pte - (void *)first_pte);
2328 pte = NULL;
2329 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002330
2331 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002332 sg = sg_next(sg);
2333 }
2334 return 0;
2335}
2336
Peter Xu87684fd2018-05-04 10:34:53 +08002337static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
Lu Baolu095303e2019-04-29 09:16:02 +08002338 struct scatterlist *sg, unsigned long phys_pfn,
2339 unsigned long nr_pages, int prot)
Peter Xu87684fd2018-05-04 10:34:53 +08002340{
Lu Baolufa954e62019-05-25 13:41:28 +08002341 int iommu_id, ret;
Lu Baolu095303e2019-04-29 09:16:02 +08002342 struct intel_iommu *iommu;
Peter Xu87684fd2018-05-04 10:34:53 +08002343
Lu Baolu095303e2019-04-29 09:16:02 +08002344 /* Do the real mapping first */
2345 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2346 if (ret)
2347 return ret;
Peter Xu87684fd2018-05-04 10:34:53 +08002348
Lu Baolufa954e62019-05-25 13:41:28 +08002349 for_each_domain_iommu(iommu_id, domain) {
2350 iommu = g_iommus[iommu_id];
Lu Baolu095303e2019-04-29 09:16:02 +08002351 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2352 }
2353
2354 return 0;
Peter Xu87684fd2018-05-04 10:34:53 +08002355}
2356
David Woodhouse9051aa02009-06-29 12:30:54 +01002357static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2358 struct scatterlist *sg, unsigned long nr_pages,
2359 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002360{
Peter Xu87684fd2018-05-04 10:34:53 +08002361 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002362}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002363
David Woodhouse9051aa02009-06-29 12:30:54 +01002364static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2365 unsigned long phys_pfn, unsigned long nr_pages,
2366 int prot)
2367{
Peter Xu87684fd2018-05-04 10:34:53 +08002368 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002369}
2370
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002371static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002372{
Filippo Sironi50822192017-08-31 10:58:11 +02002373 unsigned long flags;
2374 struct context_entry *context;
2375 u16 did_old;
2376
Weidong Hanc7151a82008-12-08 22:51:37 +08002377 if (!iommu)
2378 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002379
Filippo Sironi50822192017-08-31 10:58:11 +02002380 spin_lock_irqsave(&iommu->lock, flags);
2381 context = iommu_context_addr(iommu, bus, devfn, 0);
2382 if (!context) {
2383 spin_unlock_irqrestore(&iommu->lock, flags);
2384 return;
2385 }
2386 did_old = context_domain_id(context);
2387 context_clear_entry(context);
2388 __iommu_flush_cache(iommu, context, sizeof(*context));
2389 spin_unlock_irqrestore(&iommu->lock, flags);
2390 iommu->flush.flush_context(iommu,
2391 did_old,
2392 (((u16)bus) << 8) | devfn,
2393 DMA_CCMD_MASK_NOBIT,
2394 DMA_CCMD_DEVICE_INVL);
2395 iommu->flush.flush_iotlb(iommu,
2396 did_old,
2397 0,
2398 0,
2399 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002400}
2401
David Woodhouse109b9b02012-05-25 17:43:02 +01002402static inline void unlink_domain_info(struct device_domain_info *info)
2403{
2404 assert_spin_locked(&device_domain_lock);
2405 list_del(&info->link);
2406 list_del(&info->global);
2407 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002408 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002409}
2410
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002411static void domain_remove_dev_info(struct dmar_domain *domain)
2412{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002413 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002414 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002415
2416 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002417 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002418 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002419 spin_unlock_irqrestore(&device_domain_lock, flags);
2420}
2421
2422/*
2423 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002424 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002425 */
David Woodhouse1525a292014-03-06 16:19:30 +00002426static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002427{
2428 struct device_domain_info *info;
2429
Lu Baolu8af46c72019-05-25 13:41:32 +08002430 if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
2431 struct iommu_domain *domain;
2432
2433 dev->archdata.iommu = NULL;
2434 domain = iommu_get_domain_for_dev(dev);
2435 if (domain)
2436 intel_iommu_attach_device(domain, dev);
2437 }
2438
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002439 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002440 info = dev->archdata.iommu;
Lu Baolu8af46c72019-05-25 13:41:32 +08002441
Peter Xub316d022017-05-22 18:28:51 +08002442 if (likely(info))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002443 return info->domain;
2444 return NULL;
2445}
2446
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002447static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002448dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2449{
2450 struct device_domain_info *info;
2451
2452 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002453 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002454 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002455 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002456
2457 return NULL;
2458}
2459
Joerg Roedel5db31562015-07-22 12:40:43 +02002460static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2461 int bus, int devfn,
2462 struct device *dev,
2463 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002464{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002465 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002466 struct device_domain_info *info;
2467 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002468 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002469
2470 info = alloc_devinfo_mem();
2471 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002472 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002473
Jiang Liu745f2582014-02-19 14:07:26 +08002474 info->bus = bus;
2475 info->devfn = devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002476 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2477 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2478 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002479 info->dev = dev;
2480 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002481 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002482 info->pasid_table = NULL;
Lu Baolu95587a72019-03-25 09:30:30 +08002483 info->auxd_enabled = 0;
Lu Baolu67b8e022019-03-25 09:30:32 +08002484 INIT_LIST_HEAD(&info->auxiliary_domains);
Jiang Liu745f2582014-02-19 14:07:26 +08002485
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002486 if (dev && dev_is_pci(dev)) {
2487 struct pci_dev *pdev = to_pci_dev(info->dev);
2488
Lu Baolud8b85912019-03-01 11:23:10 +08002489 if (!pdev->untrusted &&
2490 !pci_ats_disabled() &&
Gil Kupfercef74402018-05-10 17:56:02 -05002491 ecap_dev_iotlb_support(iommu->ecap) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002492 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
2493 dmar_find_matched_atsr_unit(pdev))
2494 info->ats_supported = 1;
2495
Lu Baolu765b6a92018-12-10 09:58:55 +08002496 if (sm_supported(iommu)) {
2497 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002498 int features = pci_pasid_features(pdev);
2499 if (features >= 0)
2500 info->pasid_supported = features | 1;
2501 }
2502
2503 if (info->ats_supported && ecap_prs(iommu->ecap) &&
2504 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
2505 info->pri_supported = 1;
2506 }
2507 }
2508
Jiang Liu745f2582014-02-19 14:07:26 +08002509 spin_lock_irqsave(&device_domain_lock, flags);
2510 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002511 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002512
2513 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002514 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002515 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002516 if (info2) {
2517 found = info2->domain;
2518 info2->dev = dev;
2519 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002520 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002521
Jiang Liu745f2582014-02-19 14:07:26 +08002522 if (found) {
2523 spin_unlock_irqrestore(&device_domain_lock, flags);
2524 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 spin_lock(&iommu->lock);
2530 ret = domain_attach_iommu(domain, iommu);
2531 spin_unlock(&iommu->lock);
2532
2533 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002534 spin_unlock_irqrestore(&device_domain_lock, flags);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302535 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002536 return NULL;
2537 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002538
David Woodhouseb718cd32014-03-09 13:11:33 -07002539 list_add(&info->link, &domain->devices);
2540 list_add(&info->global, &device_domain_list);
2541 if (dev)
2542 dev->archdata.iommu = info;
Lu Baolu0bbeb012018-12-10 09:58:56 +08002543 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002544
Lu Baolu0bbeb012018-12-10 09:58:56 +08002545 /* PASID table is mandatory for a PCI device in scalable mode. */
2546 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002547 ret = intel_pasid_alloc_table(dev);
2548 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002549 dev_err(dev, "PASID table allocation failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002550 dmar_remove_one_dev_info(dev);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002551 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002552 }
Lu Baoluef848b72018-12-10 09:59:01 +08002553
2554 /* Setup the PASID entry for requests without PASID: */
2555 spin_lock(&iommu->lock);
2556 if (hw_pass_through && domain_type_is_si(domain))
2557 ret = intel_pasid_setup_pass_through(iommu, domain,
2558 dev, PASID_RID2PASID);
2559 else
2560 ret = intel_pasid_setup_second_level(iommu, domain,
2561 dev, PASID_RID2PASID);
2562 spin_unlock(&iommu->lock);
2563 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002564 dev_err(dev, "Setup RID2PASID failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002565 dmar_remove_one_dev_info(dev);
Lu Baoluef848b72018-12-10 09:59:01 +08002566 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002567 }
2568 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002569
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002570 if (dev && domain_context_mapping(domain, dev)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002571 dev_err(dev, "Domain context map failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002572 dmar_remove_one_dev_info(dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002573 return NULL;
2574 }
2575
David Woodhouseb718cd32014-03-09 13:11:33 -07002576 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002577}
2578
Alex Williamson579305f2014-07-03 09:51:43 -06002579static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2580{
2581 *(u16 *)opaque = alias;
2582 return 0;
2583}
2584
Joerg Roedel76208352016-08-25 14:25:12 +02002585static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002586{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002587 struct device_domain_info *info;
Joerg Roedel76208352016-08-25 14:25:12 +02002588 struct dmar_domain *domain = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002589 struct intel_iommu *iommu;
Lu Baolufcc35c62018-05-04 13:08:17 +08002590 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002591 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002592 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002593
David Woodhouse146922e2014-03-09 15:44:17 -07002594 iommu = device_to_iommu(dev, &bus, &devfn);
2595 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002596 return NULL;
2597
2598 if (dev_is_pci(dev)) {
2599 struct pci_dev *pdev = to_pci_dev(dev);
2600
2601 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2602
2603 spin_lock_irqsave(&device_domain_lock, flags);
2604 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2605 PCI_BUS_NUM(dma_alias),
2606 dma_alias & 0xff);
2607 if (info) {
2608 iommu = info->iommu;
2609 domain = info->domain;
2610 }
2611 spin_unlock_irqrestore(&device_domain_lock, flags);
2612
Joerg Roedel76208352016-08-25 14:25:12 +02002613 /* DMA alias already has a domain, use it */
Alex Williamson579305f2014-07-03 09:51:43 -06002614 if (info)
Joerg Roedel76208352016-08-25 14:25:12 +02002615 goto out;
Alex Williamson579305f2014-07-03 09:51:43 -06002616 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002617
David Woodhouse146922e2014-03-09 15:44:17 -07002618 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002619 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002620 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002621 return NULL;
Joerg Roedeldc534b22015-07-22 12:44:02 +02002622 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002623 domain_exit(domain);
2624 return NULL;
2625 }
2626
Joerg Roedel76208352016-08-25 14:25:12 +02002627out:
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
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002781static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002782
Matt Kraai071e1372009-08-23 22:30:22 -07002783static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002784{
Lu Baolu4de354e2019-05-25 13:41:27 +08002785 struct dmar_rmrr_unit *rmrr;
2786 struct device *dev;
2787 int i, nid, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002788
Jiang Liuab8dfe22014-07-11 14:19:27 +08002789 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002790 if (!si_domain)
2791 return -EFAULT;
2792
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002793 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2794 domain_exit(si_domain);
2795 return -EFAULT;
2796 }
2797
David Woodhouse19943b02009-08-04 16:19:20 +01002798 if (hw)
2799 return 0;
2800
David Woodhousec7ab48d2009-06-26 19:10:36 +01002801 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002802 unsigned long start_pfn, end_pfn;
2803 int i;
2804
2805 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2806 ret = iommu_domain_identity_map(si_domain,
2807 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2808 if (ret)
2809 return ret;
2810 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002811 }
2812
Lu Baolu4de354e2019-05-25 13:41:27 +08002813 /*
2814 * Normally we use DMA domains for devices which have RMRRs. But we
2815 * loose this requirement for graphic and usb devices. Identity map
2816 * the RMRRs for graphic and USB devices so that they could use the
2817 * si_domain.
2818 */
2819 for_each_rmrr_units(rmrr) {
2820 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
2821 i, dev) {
2822 unsigned long long start = rmrr->base_address;
2823 unsigned long long end = rmrr->end_address;
2824
2825 if (device_is_rmrr_locked(dev))
2826 continue;
2827
2828 if (WARN_ON(end < start ||
2829 end >> agaw_to_width(si_domain->agaw)))
2830 continue;
2831
2832 ret = iommu_domain_identity_map(si_domain, start, end);
2833 if (ret)
2834 return ret;
2835 }
2836 }
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
David Woodhouse9b226622014-03-09 14:03:28 -07002845 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002846 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2847 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002848
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002849 return 0;
2850}
2851
Joerg Roedel28ccce02015-07-21 14:45:31 +02002852static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002853{
David Woodhouse0ac72662014-03-09 13:19:22 -07002854 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002855 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002856 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002857
David Woodhouse5913c9b2014-03-09 16:27:31 -07002858 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002859 if (!iommu)
2860 return -ENODEV;
2861
Joerg Roedel5db31562015-07-22 12:40:43 +02002862 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002863 if (ndomain != domain)
2864 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002865
2866 return 0;
2867}
2868
David Woodhouse0b9d9752014-03-09 15:48:15 -07002869static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002870{
2871 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002872 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002873 int i;
2874
Jiang Liu0e242612014-02-19 14:07:34 +08002875 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002876 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002877 /*
2878 * Return TRUE if this RMRR contains the device that
2879 * is passed in.
2880 */
2881 for_each_active_dev_scope(rmrr->devices,
2882 rmrr->devices_cnt, i, tmp)
Eric Augere143fd42019-06-03 08:53:33 +02002883 if (tmp == dev ||
2884 is_downstream_to_pci_bridge(dev, tmp)) {
Jiang Liu0e242612014-02-19 14:07:34 +08002885 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002886 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002887 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002888 }
Jiang Liu0e242612014-02-19 14:07:34 +08002889 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002890 return false;
2891}
2892
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002893/*
2894 * There are a couple cases where we need to restrict the functionality of
2895 * devices associated with RMRRs. The first is when evaluating a device for
2896 * identity mapping because problems exist when devices are moved in and out
2897 * of domains and their respective RMRR information is lost. This means that
2898 * a device with associated RMRRs will never be in a "passthrough" domain.
2899 * The second is use of the device through the IOMMU API. This interface
2900 * expects to have full control of the IOVA space for the device. We cannot
2901 * satisfy both the requirement that RMRR access is maintained and have an
2902 * unencumbered IOVA space. We also have no ability to quiesce the device's
2903 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2904 * We therefore prevent devices associated with an RMRR from participating in
2905 * the IOMMU API, which eliminates them from device assignment.
2906 *
2907 * In both cases we assume that PCI USB devices with RMRRs have them largely
2908 * for historical reasons and that the RMRR space is not actively used post
2909 * boot. This exclusion may change if vendors begin to abuse it.
David Woodhouse18436af2015-03-25 15:05:47 +00002910 *
2911 * The same exception is made for graphics devices, with the requirement that
2912 * any use of the RMRR regions will be torn down before assigning the device
2913 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002914 */
2915static bool device_is_rmrr_locked(struct device *dev)
2916{
2917 if (!device_has_rmrr(dev))
2918 return false;
2919
2920 if (dev_is_pci(dev)) {
2921 struct pci_dev *pdev = to_pci_dev(dev);
2922
David Woodhouse18436af2015-03-25 15:05:47 +00002923 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002924 return false;
2925 }
2926
2927 return true;
2928}
2929
Lu Baoluf273a452019-05-25 13:41:26 +08002930/*
2931 * Return the required default domain type for a specific device.
2932 *
2933 * @dev: the device in query
2934 * @startup: true if this is during early boot
2935 *
2936 * Returns:
2937 * - IOMMU_DOMAIN_DMA: device requires a dynamic mapping domain
2938 * - IOMMU_DOMAIN_IDENTITY: device requires an identical mapping domain
2939 * - 0: both identity and dynamic domains work for this device
2940 */
Lu Baolu0e31a722019-05-25 13:41:34 +08002941static int device_def_domain_type(struct device *dev)
David Woodhouse6941af22009-07-04 18:24:27 +01002942{
David Woodhouse3bdb2592014-03-09 16:03:08 -07002943 if (dev_is_pci(dev)) {
2944 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002945
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002946 if (device_is_rmrr_locked(dev))
Lu Baoluf273a452019-05-25 13:41:26 +08002947 return IOMMU_DOMAIN_DMA;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002948
Lu Baolu89a60792018-10-23 15:45:01 +08002949 /*
2950 * Prevent any device marked as untrusted from getting
2951 * placed into the statically identity mapping domain.
2952 */
2953 if (pdev->untrusted)
Lu Baoluf273a452019-05-25 13:41:26 +08002954 return IOMMU_DOMAIN_DMA;
Lu Baolu89a60792018-10-23 15:45:01 +08002955
David Woodhouse3bdb2592014-03-09 16:03:08 -07002956 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08002957 return IOMMU_DOMAIN_IDENTITY;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002958
David Woodhouse3bdb2592014-03-09 16:03:08 -07002959 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08002960 return IOMMU_DOMAIN_IDENTITY;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002961
2962 /*
2963 * We want to start off with all devices in the 1:1 domain, and
2964 * take them out later if we find they can't access all of memory.
2965 *
2966 * However, we can't do this for PCI devices behind bridges,
2967 * because all PCI devices behind the same bridge will end up
2968 * with the same source-id on their transactions.
2969 *
2970 * Practically speaking, we can't change things around for these
2971 * devices at run-time, because we can't be sure there'll be no
2972 * DMA transactions in flight for any of their siblings.
2973 *
2974 * So PCI devices (unless they're on the root bus) as well as
2975 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2976 * the 1:1 domain, just in _case_ one of their siblings turns out
2977 * not to be able to map all of memory.
2978 */
2979 if (!pci_is_pcie(pdev)) {
2980 if (!pci_is_root_bus(pdev->bus))
Lu Baoluf273a452019-05-25 13:41:26 +08002981 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002982 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
Lu Baoluf273a452019-05-25 13:41:26 +08002983 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002984 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
Lu Baoluf273a452019-05-25 13:41:26 +08002985 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002986 } else {
2987 if (device_has_rmrr(dev))
Lu Baoluf273a452019-05-25 13:41:26 +08002988 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07002989 }
David Woodhouse6941af22009-07-04 18:24:27 +01002990
Lu Baoluf273a452019-05-25 13:41:26 +08002991 return (iommu_identity_mapping & IDENTMAP_ALL) ?
2992 IOMMU_DOMAIN_IDENTITY : 0;
2993}
2994
Jiang Liuffebeb42014-11-09 22:48:02 +08002995static void intel_iommu_init_qi(struct intel_iommu *iommu)
2996{
2997 /*
2998 * Start from the sane iommu hardware state.
2999 * If the queued invalidation is already initialized by us
3000 * (for example, while enabling interrupt-remapping) then
3001 * we got the things already rolling from a sane state.
3002 */
3003 if (!iommu->qi) {
3004 /*
3005 * Clear any previous faults.
3006 */
3007 dmar_fault(-1, iommu);
3008 /*
3009 * Disable queued invalidation if supported and already enabled
3010 * before OS handover.
3011 */
3012 dmar_disable_qi(iommu);
3013 }
3014
3015 if (dmar_enable_qi(iommu)) {
3016 /*
3017 * Queued Invalidate not enabled, use Register Based Invalidate
3018 */
3019 iommu->flush.flush_context = __iommu_flush_context;
3020 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003021 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08003022 iommu->name);
3023 } else {
3024 iommu->flush.flush_context = qi_flush_context;
3025 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003026 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08003027 }
3028}
3029
Joerg Roedel091d42e2015-06-12 11:56:10 +02003030static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04003031 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02003032 struct context_entry **tbl,
3033 int bus, bool ext)
3034{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003035 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003036 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04003037 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003038 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003039 phys_addr_t old_ce_phys;
3040
3041 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04003042 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003043
3044 for (devfn = 0; devfn < 256; devfn++) {
3045 /* First calculate the correct index */
3046 idx = (ext ? devfn * 2 : devfn) % 256;
3047
3048 if (idx == 0) {
3049 /* First save what we may have and clean up */
3050 if (new_ce) {
3051 tbl[tbl_idx] = new_ce;
3052 __iommu_flush_cache(iommu, new_ce,
3053 VTD_PAGE_SIZE);
3054 pos = 1;
3055 }
3056
3057 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08003058 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003059
3060 ret = 0;
3061 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003062 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003063 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003064 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003065
3066 if (!old_ce_phys) {
3067 if (ext && devfn == 0) {
3068 /* No LCTP, try UCTP */
3069 devfn = 0x7f;
3070 continue;
3071 } else {
3072 goto out;
3073 }
3074 }
3075
3076 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003077 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3078 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003079 if (!old_ce)
3080 goto out;
3081
3082 new_ce = alloc_pgtable_page(iommu->node);
3083 if (!new_ce)
3084 goto out_unmap;
3085
3086 ret = 0;
3087 }
3088
3089 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003090 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003091
Joerg Roedelcf484d02015-06-12 12:21:46 +02003092 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003093 continue;
3094
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003095 did = context_domain_id(&ce);
3096 if (did >= 0 && did < cap_ndoms(iommu->cap))
3097 set_bit(did, iommu->domain_ids);
3098
Joerg Roedelcf484d02015-06-12 12:21:46 +02003099 /*
3100 * We need a marker for copied context entries. This
3101 * marker needs to work for the old format as well as
3102 * for extended context entries.
3103 *
3104 * Bit 67 of the context entry is used. In the old
3105 * format this bit is available to software, in the
3106 * extended format it is the PGE bit, but PGE is ignored
3107 * by HW if PASIDs are disabled (and thus still
3108 * available).
3109 *
3110 * So disable PASIDs first and then mark the entry
3111 * copied. This means that we don't copy PASID
3112 * translations from the old kernel, but this is fine as
3113 * faults there are not fatal.
3114 */
3115 context_clear_pasid_enable(&ce);
3116 context_set_copied(&ce);
3117
Joerg Roedel091d42e2015-06-12 11:56:10 +02003118 new_ce[idx] = ce;
3119 }
3120
3121 tbl[tbl_idx + pos] = new_ce;
3122
3123 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3124
3125out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003126 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003127
3128out:
3129 return ret;
3130}
3131
3132static int copy_translation_tables(struct intel_iommu *iommu)
3133{
3134 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003135 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003136 phys_addr_t old_rt_phys;
3137 int ctxt_table_entries;
3138 unsigned long flags;
3139 u64 rtaddr_reg;
3140 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003141 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003142
3143 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3144 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003145 new_ext = !!ecap_ecs(iommu->ecap);
3146
3147 /*
3148 * The RTT bit can only be changed when translation is disabled,
3149 * but disabling translation means to open a window for data
3150 * corruption. So bail out and don't copy anything if we would
3151 * have to change the bit.
3152 */
3153 if (new_ext != ext)
3154 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003155
3156 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3157 if (!old_rt_phys)
3158 return -EINVAL;
3159
Dan Williamsdfddb962015-10-09 18:16:46 -04003160 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003161 if (!old_rt)
3162 return -ENOMEM;
3163
3164 /* This is too big for the stack - allocate it from slab */
3165 ctxt_table_entries = ext ? 512 : 256;
3166 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003167 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003168 if (!ctxt_tbls)
3169 goto out_unmap;
3170
3171 for (bus = 0; bus < 256; bus++) {
3172 ret = copy_context_table(iommu, &old_rt[bus],
3173 ctxt_tbls, bus, ext);
3174 if (ret) {
3175 pr_err("%s: Failed to copy context table for bus %d\n",
3176 iommu->name, bus);
3177 continue;
3178 }
3179 }
3180
3181 spin_lock_irqsave(&iommu->lock, flags);
3182
3183 /* Context tables are copied, now write them to the root_entry table */
3184 for (bus = 0; bus < 256; bus++) {
3185 int idx = ext ? bus * 2 : bus;
3186 u64 val;
3187
3188 if (ctxt_tbls[idx]) {
3189 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3190 iommu->root_entry[bus].lo = val;
3191 }
3192
3193 if (!ext || !ctxt_tbls[idx + 1])
3194 continue;
3195
3196 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3197 iommu->root_entry[bus].hi = val;
3198 }
3199
3200 spin_unlock_irqrestore(&iommu->lock, flags);
3201
3202 kfree(ctxt_tbls);
3203
3204 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3205
3206 ret = 0;
3207
3208out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003209 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003210
3211 return ret;
3212}
3213
Joseph Cihulab7792602011-05-03 00:08:37 -07003214static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003215{
3216 struct dmar_drhd_unit *drhd;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003217 struct intel_iommu *iommu;
Lu Baoludf4f3c62019-05-25 13:41:36 +08003218 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003219
3220 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003221 * for each drhd
3222 * allocate root
3223 * initialize and program root entry to not present
3224 * endfor
3225 */
3226 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003227 /*
3228 * lock not needed as this is only incremented in the single
3229 * threaded kernel __init code path all other access are read
3230 * only
3231 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003232 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003233 g_num_of_iommus++;
3234 continue;
3235 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003236 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003237 }
3238
Jiang Liuffebeb42014-11-09 22:48:02 +08003239 /* Preallocate enough resources for IOMMU hot-addition */
3240 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3241 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3242
Weidong Hand9630fe2008-12-08 11:06:32 +08003243 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3244 GFP_KERNEL);
3245 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003246 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003247 ret = -ENOMEM;
3248 goto error;
3249 }
3250
Jiang Liu7c919772014-01-06 14:18:18 +08003251 for_each_active_iommu(iommu, drhd) {
Lu Baolu56283172018-07-14 15:46:54 +08003252 /*
3253 * Find the max pasid size of all IOMMU's in the system.
3254 * We need to ensure the system pasid table is no bigger
3255 * than the smallest supported.
3256 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003257 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003258 u32 temp = 2 << ecap_pss(iommu->ecap);
3259
3260 intel_pasid_max_id = min_t(u32, temp,
3261 intel_pasid_max_id);
3262 }
3263
Weidong Hand9630fe2008-12-08 11:06:32 +08003264 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003265
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003266 intel_iommu_init_qi(iommu);
3267
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003268 ret = iommu_init_domains(iommu);
3269 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003270 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003271
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003272 init_translation_status(iommu);
3273
Joerg Roedel091d42e2015-06-12 11:56:10 +02003274 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3275 iommu_disable_translation(iommu);
3276 clear_translation_pre_enabled(iommu);
3277 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3278 iommu->name);
3279 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003280
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003281 /*
3282 * TBD:
3283 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003284 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003285 */
3286 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003287 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003288 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003289
Joerg Roedel091d42e2015-06-12 11:56:10 +02003290 if (translation_pre_enabled(iommu)) {
3291 pr_info("Translation already enabled - trying to copy translation structures\n");
3292
3293 ret = copy_translation_tables(iommu);
3294 if (ret) {
3295 /*
3296 * We found the IOMMU with translation
3297 * enabled - but failed to copy over the
3298 * old root-entry table. Try to proceed
3299 * by disabling translation now and
3300 * allocating a clean root-entry table.
3301 * This might cause DMAR faults, but
3302 * probably the dump will still succeed.
3303 */
3304 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3305 iommu->name);
3306 iommu_disable_translation(iommu);
3307 clear_translation_pre_enabled(iommu);
3308 } else {
3309 pr_info("Copied translation tables from previous kernel for %s\n",
3310 iommu->name);
3311 }
3312 }
3313
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003314 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003315 hw_pass_through = 0;
David Woodhouse8a94ade2015-03-24 14:54:56 +00003316#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003317 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08003318 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00003319#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003320 }
3321
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003322 /*
3323 * Now that qi is enabled on all iommus, set the root entry and flush
3324 * caches. This is required on some Intel X58 chipsets, otherwise the
3325 * flush_context function will loop forever and the boot hangs.
3326 */
3327 for_each_active_iommu(iommu, drhd) {
3328 iommu_flush_write_buffer(iommu);
3329 iommu_set_root_entry(iommu);
3330 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3331 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3332 }
3333
David Woodhouse19943b02009-08-04 16:19:20 +01003334 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07003335 iommu_identity_mapping |= IDENTMAP_ALL;
3336
Suresh Siddhad3f13812011-08-23 17:05:25 -07003337#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
Lu Baolu5daab582019-05-02 09:34:26 +08003338 dmar_map_gfx = 0;
David Woodhouse19943b02009-08-04 16:19:20 +01003339#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003340
Lu Baolu5daab582019-05-02 09:34:26 +08003341 if (!dmar_map_gfx)
3342 iommu_identity_mapping |= IDENTMAP_GFX;
3343
Ashok Raj21e722c2017-01-30 09:39:53 -08003344 check_tylersburg_isoch();
3345
Lu Baolu4de354e2019-05-25 13:41:27 +08003346 ret = si_domain_init(hw_pass_through);
3347 if (ret)
3348 goto free_iommu;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003349
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003350 /*
3351 * for each drhd
3352 * enable fault log
3353 * global invalidate context cache
3354 * global invalidate iotlb
3355 * enable translation
3356 */
Jiang Liu7c919772014-01-06 14:18:18 +08003357 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003358 if (drhd->ignored) {
3359 /*
3360 * we always have to disable PMRs or DMA may fail on
3361 * this device
3362 */
3363 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003364 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003365 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003366 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003367
3368 iommu_flush_write_buffer(iommu);
3369
David Woodhousea222a7f2015-10-07 23:35:18 +01003370#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003371 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
Lu Baolua7755c32019-04-19 14:43:29 +08003372 /*
3373 * Call dmar_alloc_hwirq() with dmar_global_lock held,
3374 * could cause possible lock race condition.
3375 */
3376 up_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003377 ret = intel_svm_enable_prq(iommu);
Lu Baolua7755c32019-04-19 14:43:29 +08003378 down_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003379 if (ret)
3380 goto free_iommu;
3381 }
3382#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003383 ret = dmar_set_interrupt(iommu);
3384 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003385 goto free_iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003386 }
3387
3388 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003389
3390free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003391 for_each_active_iommu(iommu, drhd) {
3392 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003393 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003394 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003395
Weidong Hand9630fe2008-12-08 11:06:32 +08003396 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003397
Jiang Liu989d51f2014-02-19 14:07:21 +08003398error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003399 return ret;
3400}
3401
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003402/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003403static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003404 struct dmar_domain *domain,
3405 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003406{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06003407 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003408
David Woodhouse875764d2009-06-28 21:20:51 +01003409 /* Restrict dma_mask to the width that the iommu can handle */
3410 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
Robin Murphy8f6429c2015-07-16 19:40:12 +01003411 /* Ensure we reserve the whole size-aligned region */
3412 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003413
3414 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003415 /*
3416 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003417 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003418 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003419 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003420 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003421 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003422 if (iova_pfn)
3423 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003424 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003425 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3426 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003427 if (unlikely(!iova_pfn)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003428 dev_err(dev, "Allocating %ld-page iova failed", nrpages);
Omer Peleg2aac6302016-04-20 11:33:57 +03003429 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003430 }
3431
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003432 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003433}
3434
Lu Baolu4ec066c2019-05-25 13:41:33 +08003435static struct dmar_domain *get_private_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003436{
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003437 struct dmar_domain *domain, *tmp;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003438 struct dmar_rmrr_unit *rmrr;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003439 struct device *i_dev;
3440 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003441
Lu Baolu4ec066c2019-05-25 13:41:33 +08003442 /* Device shouldn't be attached by any domains. */
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003443 domain = find_domain(dev);
3444 if (domain)
Lu Baolu4ec066c2019-05-25 13:41:33 +08003445 return NULL;
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003446
3447 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3448 if (!domain)
3449 goto out;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003450
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003451 /* We have a new domain - setup possible RMRRs for the device */
3452 rcu_read_lock();
3453 for_each_rmrr_units(rmrr) {
3454 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3455 i, i_dev) {
3456 if (i_dev != dev)
3457 continue;
3458
3459 ret = domain_prepare_identity_map(dev, domain,
3460 rmrr->base_address,
3461 rmrr->end_address);
3462 if (ret)
3463 dev_err(dev, "Mapping reserved region failed\n");
3464 }
3465 }
3466 rcu_read_unlock();
3467
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003468 tmp = set_domain_for_dev(dev, domain);
3469 if (!tmp || domain != tmp) {
3470 domain_exit(domain);
3471 domain = tmp;
3472 }
3473
3474out:
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003475 if (!domain)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003476 dev_err(dev, "Allocating domain failed\n");
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003477
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003478 return domain;
3479}
3480
David Woodhouseecb509e2014-03-09 16:29:55 -07003481/* Check if the dev needs to go through non-identity map and unmap process.*/
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003482static bool iommu_need_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003483{
Lu Baolu98b2fff2019-05-25 13:41:30 +08003484 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003485
David Woodhouse3d891942014-03-06 15:59:26 +00003486 if (iommu_dummy(dev))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003487 return false;
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003488
Lu Baolu98b2fff2019-05-25 13:41:30 +08003489 ret = identity_mapping(dev);
3490 if (ret) {
3491 u64 dma_mask = *dev->dma_mask;
3492
3493 if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask)
3494 dma_mask = dev->coherent_dma_mask;
3495
3496 if (dma_mask >= dma_get_required_mask(dev))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003497 return false;
3498
3499 /*
3500 * 32 bit DMA is removed from si_domain and fall back to
3501 * non-identity mapping.
3502 */
3503 dmar_remove_one_dev_info(dev);
Lu Baolu98b2fff2019-05-25 13:41:30 +08003504 ret = iommu_request_dma_domain_for_dev(dev);
3505 if (ret) {
3506 struct iommu_domain *domain;
3507 struct dmar_domain *dmar_domain;
3508
3509 domain = iommu_get_domain_for_dev(dev);
3510 if (domain) {
3511 dmar_domain = to_dmar_domain(domain);
3512 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
3513 }
Lu Baolu4ec066c2019-05-25 13:41:33 +08003514 get_private_domain_for_dev(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003515 }
Lu Baolu98b2fff2019-05-25 13:41:30 +08003516
3517 dev_info(dev, "32bit DMA uses non-identity mapping\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003518 }
3519
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003520 return true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003521}
3522
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003523static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3524 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003525{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003526 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003527 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003528 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003529 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003530 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003531 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003532 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003533
3534 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003535
Lu Baolu4ec066c2019-05-25 13:41:33 +08003536 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003537 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003538 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003539
Weidong Han8c11e792008-12-08 15:29:22 +08003540 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003541 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003542
Omer Peleg2aac6302016-04-20 11:33:57 +03003543 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3544 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003545 goto error;
3546
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003547 /*
3548 * Check if DMAR supports zero-length reads on write only
3549 * mappings..
3550 */
3551 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003552 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003553 prot |= DMA_PTE_READ;
3554 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3555 prot |= DMA_PTE_WRITE;
3556 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003557 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003558 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003559 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003560 * is not a big problem
3561 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003562 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003563 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003564 if (ret)
3565 goto error;
3566
Omer Peleg2aac6302016-04-20 11:33:57 +03003567 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003568 start_paddr += paddr & ~PAGE_MASK;
3569 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003570
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003571error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003572 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003573 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003574 dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n",
3575 size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003576 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003577}
3578
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003579static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3580 unsigned long offset, size_t size,
3581 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003582 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003583{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003584 if (iommu_need_mapping(dev))
3585 return __intel_map_single(dev, page_to_phys(page) + offset,
3586 size, dir, *dev->dma_mask);
3587 return dma_direct_map_page(dev, page, offset, size, dir, attrs);
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003588}
3589
3590static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3591 size_t size, enum dma_data_direction dir,
3592 unsigned long attrs)
3593{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003594 if (iommu_need_mapping(dev))
3595 return __intel_map_single(dev, phys_addr, size, dir,
3596 *dev->dma_mask);
3597 return dma_direct_map_resource(dev, phys_addr, size, dir, attrs);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003598}
3599
Omer Peleg769530e2016-04-20 11:33:25 +03003600static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003601{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003602 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003603 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003604 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003605 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003606 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003607 struct page *freelist;
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003608 struct pci_dev *pdev = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003609
David Woodhouse1525a292014-03-06 16:19:30 +00003610 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003611 BUG_ON(!domain);
3612
Weidong Han8c11e792008-12-08 15:29:22 +08003613 iommu = domain_get_iommu(domain);
3614
Omer Peleg2aac6302016-04-20 11:33:57 +03003615 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003616
Omer Peleg769530e2016-04-20 11:33:25 +03003617 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003618 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003619 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003620
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003621 if (dev_is_pci(dev))
3622 pdev = to_pci_dev(dev);
3623
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003624 dev_dbg(dev, "Device unmapping: pfn %lx-%lx\n", start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003625
David Woodhouseea8ea462014-03-05 17:09:32 +00003626 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003627
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003628 if (intel_iommu_strict || (pdev && pdev->untrusted)) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003629 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003630 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003631 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003632 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003633 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003634 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003635 queue_iova(&domain->iovad, iova_pfn, nrpages,
3636 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003637 /*
3638 * queue up the release of the unmap to save the 1/6th of the
3639 * cpu used up by the iotlb flush operation...
3640 */
mark gross5e0d2a62008-03-04 15:22:08 -08003641 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003642}
3643
Jiang Liud41a4ad2014-07-11 14:19:34 +08003644static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3645 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003646 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003647{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003648 if (iommu_need_mapping(dev))
3649 intel_unmap(dev, dev_addr, size);
3650 else
3651 dma_direct_unmap_page(dev, dev_addr, size, dir, attrs);
3652}
3653
3654static void intel_unmap_resource(struct device *dev, dma_addr_t dev_addr,
3655 size_t size, enum dma_data_direction dir, unsigned long attrs)
3656{
3657 if (iommu_need_mapping(dev))
3658 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003659}
3660
David Woodhouse5040a912014-03-09 16:14:00 -07003661static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003662 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003663 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003664{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003665 struct page *page = NULL;
3666 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003667
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003668 if (!iommu_need_mapping(dev))
3669 return dma_direct_alloc(dev, size, dma_handle, flags, attrs);
3670
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003671 size = PAGE_ALIGN(size);
3672 order = get_order(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003673
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003674 if (gfpflags_allow_blocking(flags)) {
3675 unsigned int count = size >> PAGE_SHIFT;
3676
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003677 page = dma_alloc_from_contiguous(dev, count, order,
3678 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003679 }
3680
3681 if (!page)
3682 page = alloc_pages(flags, order);
3683 if (!page)
3684 return NULL;
3685 memset(page_address(page), 0, size);
3686
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003687 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3688 DMA_BIDIRECTIONAL,
3689 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003690 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003691 return page_address(page);
3692 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3693 __free_pages(page, order);
3694
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003695 return NULL;
3696}
3697
David Woodhouse5040a912014-03-09 16:14:00 -07003698static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003699 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003700{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003701 int order;
3702 struct page *page = virt_to_page(vaddr);
3703
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003704 if (!iommu_need_mapping(dev))
3705 return dma_direct_free(dev, size, vaddr, dma_handle, attrs);
3706
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003707 size = PAGE_ALIGN(size);
3708 order = get_order(size);
3709
3710 intel_unmap(dev, dma_handle, size);
3711 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3712 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003713}
3714
David Woodhouse5040a912014-03-09 16:14:00 -07003715static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003716 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003717 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003718{
Omer Peleg769530e2016-04-20 11:33:25 +03003719 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3720 unsigned long nrpages = 0;
3721 struct scatterlist *sg;
3722 int i;
3723
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003724 if (!iommu_need_mapping(dev))
3725 return dma_direct_unmap_sg(dev, sglist, nelems, dir, attrs);
3726
Omer Peleg769530e2016-04-20 11:33:25 +03003727 for_each_sg(sglist, sg, nelems, i) {
3728 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3729 }
3730
3731 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003732}
3733
David Woodhouse5040a912014-03-09 16:14:00 -07003734static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003735 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003736{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003737 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003738 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003739 size_t size = 0;
3740 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003741 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003742 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003743 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003744 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003745 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003746
3747 BUG_ON(dir == DMA_NONE);
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003748 if (!iommu_need_mapping(dev))
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003749 return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003750
Lu Baolu4ec066c2019-05-25 13:41:33 +08003751 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003752 if (!domain)
3753 return 0;
3754
Weidong Han8c11e792008-12-08 15:29:22 +08003755 iommu = domain_get_iommu(domain);
3756
David Woodhouseb536d242009-06-28 14:49:31 +01003757 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003758 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003759
Omer Peleg2aac6302016-04-20 11:33:57 +03003760 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003761 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003762 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003763 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003764 return 0;
3765 }
3766
3767 /*
3768 * Check if DMAR supports zero-length reads on write only
3769 * mappings..
3770 */
3771 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003772 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003773 prot |= DMA_PTE_READ;
3774 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3775 prot |= DMA_PTE_WRITE;
3776
Omer Peleg2aac6302016-04-20 11:33:57 +03003777 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003778
Fenghua Yuf5329592009-08-04 15:09:37 -07003779 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003780 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003781 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003782 start_vpfn + size - 1,
3783 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003784 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003785 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003786 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003787
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003788 return nelems;
3789}
3790
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003791static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003792 .alloc = intel_alloc_coherent,
3793 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003794 .map_sg = intel_map_sg,
3795 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003796 .map_page = intel_map_page,
3797 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003798 .map_resource = intel_map_resource,
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003799 .unmap_resource = intel_unmap_resource,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003800 .dma_supported = dma_direct_supported,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003801};
3802
3803static inline int iommu_domain_cache_init(void)
3804{
3805 int ret = 0;
3806
3807 iommu_domain_cache = kmem_cache_create("iommu_domain",
3808 sizeof(struct dmar_domain),
3809 0,
3810 SLAB_HWCACHE_ALIGN,
3811
3812 NULL);
3813 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003814 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003815 ret = -ENOMEM;
3816 }
3817
3818 return ret;
3819}
3820
3821static inline int iommu_devinfo_cache_init(void)
3822{
3823 int ret = 0;
3824
3825 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3826 sizeof(struct device_domain_info),
3827 0,
3828 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003829 NULL);
3830 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003831 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003832 ret = -ENOMEM;
3833 }
3834
3835 return ret;
3836}
3837
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003838static int __init iommu_init_mempool(void)
3839{
3840 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003841 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003842 if (ret)
3843 return ret;
3844
3845 ret = iommu_domain_cache_init();
3846 if (ret)
3847 goto domain_error;
3848
3849 ret = iommu_devinfo_cache_init();
3850 if (!ret)
3851 return ret;
3852
3853 kmem_cache_destroy(iommu_domain_cache);
3854domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003855 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003856
3857 return -ENOMEM;
3858}
3859
3860static void __init iommu_exit_mempool(void)
3861{
3862 kmem_cache_destroy(iommu_devinfo_cache);
3863 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003864 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003865}
3866
Dan Williams556ab452010-07-23 15:47:56 -07003867static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3868{
3869 struct dmar_drhd_unit *drhd;
3870 u32 vtbar;
3871 int rc;
3872
3873 /* We know that this device on this chipset has its own IOMMU.
3874 * If we find it under a different IOMMU, then the BIOS is lying
3875 * to us. Hope that the IOMMU for this device is actually
3876 * disabled, and it needs no translation...
3877 */
3878 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3879 if (rc) {
3880 /* "can't" happen */
3881 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3882 return;
3883 }
3884 vtbar &= 0xffff0000;
3885
3886 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3887 drhd = dmar_find_matched_drhd_unit(pdev);
3888 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3889 TAINT_FIRMWARE_WORKAROUND,
3890 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3891 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3892}
3893DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3894
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003895static void __init init_no_remapping_devices(void)
3896{
3897 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003898 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003899 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003900
3901 for_each_drhd_unit(drhd) {
3902 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003903 for_each_active_dev_scope(drhd->devices,
3904 drhd->devices_cnt, i, dev)
3905 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003906 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003907 if (i == drhd->devices_cnt)
3908 drhd->ignored = 1;
3909 }
3910 }
3911
Jiang Liu7c919772014-01-06 14:18:18 +08003912 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003913 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003914 continue;
3915
Jiang Liub683b232014-02-19 14:07:32 +08003916 for_each_active_dev_scope(drhd->devices,
3917 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003918 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003919 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003920 if (i < drhd->devices_cnt)
3921 continue;
3922
David Woodhousec0771df2011-10-14 20:59:46 +01003923 /* This IOMMU has *only* gfx devices. Either bypass it or
3924 set the gfx_mapped flag, as appropriate */
Lu Baolucf1ec452019-05-02 09:34:25 +08003925 if (!dmar_map_gfx) {
David Woodhousec0771df2011-10-14 20:59:46 +01003926 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003927 for_each_active_dev_scope(drhd->devices,
3928 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003929 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003930 }
3931 }
3932}
3933
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003934#ifdef CONFIG_SUSPEND
3935static int init_iommu_hw(void)
3936{
3937 struct dmar_drhd_unit *drhd;
3938 struct intel_iommu *iommu = NULL;
3939
3940 for_each_active_iommu(iommu, drhd)
3941 if (iommu->qi)
3942 dmar_reenable_qi(iommu);
3943
Joseph Cihulab7792602011-05-03 00:08:37 -07003944 for_each_iommu(iommu, drhd) {
3945 if (drhd->ignored) {
3946 /*
3947 * we always have to disable PMRs or DMA may fail on
3948 * this device
3949 */
3950 if (force_on)
3951 iommu_disable_protect_mem_regions(iommu);
3952 continue;
3953 }
Lu Baolu095303e2019-04-29 09:16:02 +08003954
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003955 iommu_flush_write_buffer(iommu);
3956
3957 iommu_set_root_entry(iommu);
3958
3959 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003960 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003961 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3962 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003963 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003964 }
3965
3966 return 0;
3967}
3968
3969static void iommu_flush_all(void)
3970{
3971 struct dmar_drhd_unit *drhd;
3972 struct intel_iommu *iommu;
3973
3974 for_each_active_iommu(iommu, drhd) {
3975 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003976 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003977 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003978 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003979 }
3980}
3981
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003982static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003983{
3984 struct dmar_drhd_unit *drhd;
3985 struct intel_iommu *iommu = NULL;
3986 unsigned long flag;
3987
3988 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07003989 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003990 GFP_ATOMIC);
3991 if (!iommu->iommu_state)
3992 goto nomem;
3993 }
3994
3995 iommu_flush_all();
3996
3997 for_each_active_iommu(iommu, drhd) {
3998 iommu_disable_translation(iommu);
3999
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004000 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004001
4002 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4003 readl(iommu->reg + DMAR_FECTL_REG);
4004 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4005 readl(iommu->reg + DMAR_FEDATA_REG);
4006 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4007 readl(iommu->reg + DMAR_FEADDR_REG);
4008 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4009 readl(iommu->reg + DMAR_FEUADDR_REG);
4010
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004011 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004012 }
4013 return 0;
4014
4015nomem:
4016 for_each_active_iommu(iommu, drhd)
4017 kfree(iommu->iommu_state);
4018
4019 return -ENOMEM;
4020}
4021
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004022static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004023{
4024 struct dmar_drhd_unit *drhd;
4025 struct intel_iommu *iommu = NULL;
4026 unsigned long flag;
4027
4028 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004029 if (force_on)
4030 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4031 else
4032 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004033 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004034 }
4035
4036 for_each_active_iommu(iommu, drhd) {
4037
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004038 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004039
4040 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4041 iommu->reg + DMAR_FECTL_REG);
4042 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4043 iommu->reg + DMAR_FEDATA_REG);
4044 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4045 iommu->reg + DMAR_FEADDR_REG);
4046 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4047 iommu->reg + DMAR_FEUADDR_REG);
4048
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004049 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004050 }
4051
4052 for_each_active_iommu(iommu, drhd)
4053 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004054}
4055
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004056static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004057 .resume = iommu_resume,
4058 .suspend = iommu_suspend,
4059};
4060
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004061static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004062{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004063 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004064}
4065
4066#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004067static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004068#endif /* CONFIG_PM */
4069
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004070
Jiang Liuc2a0b532014-11-09 22:47:56 +08004071int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004072{
4073 struct acpi_dmar_reserved_memory *rmrr;
4074 struct dmar_rmrr_unit *rmrru;
Eric Auger0659b8d2017-01-19 20:57:53 +00004075 size_t length;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004076
4077 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4078 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004079 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004080
4081 rmrru->hdr = header;
4082 rmrr = (struct acpi_dmar_reserved_memory *)header;
4083 rmrru->base_address = rmrr->base_address;
4084 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004085
4086 length = rmrr->end_address - rmrr->base_address + 1;
Eric Auger0659b8d2017-01-19 20:57:53 +00004087
Jiang Liu2e455282014-02-19 14:07:36 +08004088 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4089 ((void *)rmrr) + rmrr->header.length,
4090 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004091 if (rmrru->devices_cnt && rmrru->devices == NULL)
Eric Auger5f64ce52019-06-03 08:53:31 +02004092 goto free_rmrru;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004093
Jiang Liu2e455282014-02-19 14:07:36 +08004094 list_add(&rmrru->list, &dmar_rmrr_units);
4095
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004096 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004097free_rmrru:
4098 kfree(rmrru);
4099out:
4100 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004101}
4102
Jiang Liu6b197242014-11-09 22:47:58 +08004103static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4104{
4105 struct dmar_atsr_unit *atsru;
4106 struct acpi_dmar_atsr *tmp;
4107
4108 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4109 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4110 if (atsr->segment != tmp->segment)
4111 continue;
4112 if (atsr->header.length != tmp->header.length)
4113 continue;
4114 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4115 return atsru;
4116 }
4117
4118 return NULL;
4119}
4120
4121int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004122{
4123 struct acpi_dmar_atsr *atsr;
4124 struct dmar_atsr_unit *atsru;
4125
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004126 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004127 return 0;
4128
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004129 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004130 atsru = dmar_find_atsr(atsr);
4131 if (atsru)
4132 return 0;
4133
4134 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004135 if (!atsru)
4136 return -ENOMEM;
4137
Jiang Liu6b197242014-11-09 22:47:58 +08004138 /*
4139 * If memory is allocated from slab by ACPI _DSM method, we need to
4140 * copy the memory content because the memory buffer will be freed
4141 * on return.
4142 */
4143 atsru->hdr = (void *)(atsru + 1);
4144 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004145 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004146 if (!atsru->include_all) {
4147 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4148 (void *)atsr + atsr->header.length,
4149 &atsru->devices_cnt);
4150 if (atsru->devices_cnt && atsru->devices == NULL) {
4151 kfree(atsru);
4152 return -ENOMEM;
4153 }
4154 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004155
Jiang Liu0e242612014-02-19 14:07:34 +08004156 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004157
4158 return 0;
4159}
4160
Jiang Liu9bdc5312014-01-06 14:18:27 +08004161static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4162{
4163 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4164 kfree(atsru);
4165}
4166
Jiang Liu6b197242014-11-09 22:47:58 +08004167int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4168{
4169 struct acpi_dmar_atsr *atsr;
4170 struct dmar_atsr_unit *atsru;
4171
4172 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4173 atsru = dmar_find_atsr(atsr);
4174 if (atsru) {
4175 list_del_rcu(&atsru->list);
4176 synchronize_rcu();
4177 intel_iommu_free_atsr(atsru);
4178 }
4179
4180 return 0;
4181}
4182
4183int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4184{
4185 int i;
4186 struct device *dev;
4187 struct acpi_dmar_atsr *atsr;
4188 struct dmar_atsr_unit *atsru;
4189
4190 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4191 atsru = dmar_find_atsr(atsr);
4192 if (!atsru)
4193 return 0;
4194
Linus Torvalds194dc872016-07-27 20:03:31 -07004195 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004196 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4197 i, dev)
4198 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004199 }
Jiang Liu6b197242014-11-09 22:47:58 +08004200
4201 return 0;
4202}
4203
Jiang Liuffebeb42014-11-09 22:48:02 +08004204static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4205{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004206 int sp, ret;
Jiang Liuffebeb42014-11-09 22:48:02 +08004207 struct intel_iommu *iommu = dmaru->iommu;
4208
4209 if (g_iommus[iommu->seq_id])
4210 return 0;
4211
4212 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004213 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004214 iommu->name);
4215 return -ENXIO;
4216 }
4217 if (!ecap_sc_support(iommu->ecap) &&
4218 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004219 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004220 iommu->name);
4221 return -ENXIO;
4222 }
4223 sp = domain_update_iommu_superpage(iommu) - 1;
4224 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004225 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004226 iommu->name);
4227 return -ENXIO;
4228 }
4229
4230 /*
4231 * Disable translation if already enabled prior to OS handover.
4232 */
4233 if (iommu->gcmd & DMA_GCMD_TE)
4234 iommu_disable_translation(iommu);
4235
4236 g_iommus[iommu->seq_id] = iommu;
4237 ret = iommu_init_domains(iommu);
4238 if (ret == 0)
4239 ret = iommu_alloc_root_entry(iommu);
4240 if (ret)
4241 goto out;
4242
David Woodhouse8a94ade2015-03-24 14:54:56 +00004243#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004244 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08004245 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004246#endif
4247
Jiang Liuffebeb42014-11-09 22:48:02 +08004248 if (dmaru->ignored) {
4249 /*
4250 * we always have to disable PMRs or DMA may fail on this device
4251 */
4252 if (force_on)
4253 iommu_disable_protect_mem_regions(iommu);
4254 return 0;
4255 }
4256
4257 intel_iommu_init_qi(iommu);
4258 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004259
4260#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004261 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004262 ret = intel_svm_enable_prq(iommu);
4263 if (ret)
4264 goto disable_iommu;
4265 }
4266#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004267 ret = dmar_set_interrupt(iommu);
4268 if (ret)
4269 goto disable_iommu;
4270
4271 iommu_set_root_entry(iommu);
4272 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4273 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4274 iommu_enable_translation(iommu);
4275
Jiang Liuffebeb42014-11-09 22:48:02 +08004276 iommu_disable_protect_mem_regions(iommu);
4277 return 0;
4278
4279disable_iommu:
4280 disable_dmar_iommu(iommu);
4281out:
4282 free_dmar_iommu(iommu);
4283 return ret;
4284}
4285
Jiang Liu6b197242014-11-09 22:47:58 +08004286int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4287{
Jiang Liuffebeb42014-11-09 22:48:02 +08004288 int ret = 0;
4289 struct intel_iommu *iommu = dmaru->iommu;
4290
4291 if (!intel_iommu_enabled)
4292 return 0;
4293 if (iommu == NULL)
4294 return -EINVAL;
4295
4296 if (insert) {
4297 ret = intel_iommu_add(dmaru);
4298 } else {
4299 disable_dmar_iommu(iommu);
4300 free_dmar_iommu(iommu);
4301 }
4302
4303 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004304}
4305
Jiang Liu9bdc5312014-01-06 14:18:27 +08004306static void intel_iommu_free_dmars(void)
4307{
4308 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4309 struct dmar_atsr_unit *atsru, *atsr_n;
4310
4311 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4312 list_del(&rmrru->list);
4313 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
4314 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004315 }
4316
Jiang Liu9bdc5312014-01-06 14:18:27 +08004317 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4318 list_del(&atsru->list);
4319 intel_iommu_free_atsr(atsru);
4320 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004321}
4322
4323int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4324{
Jiang Liub683b232014-02-19 14:07:32 +08004325 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004326 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004327 struct pci_dev *bridge = NULL;
4328 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004329 struct acpi_dmar_atsr *atsr;
4330 struct dmar_atsr_unit *atsru;
4331
4332 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004333 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004334 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004335 /* If it's an integrated device, allow ATS */
4336 if (!bridge)
4337 return 1;
4338 /* Connected via non-PCIe: no ATS */
4339 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004340 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004341 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004342 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004343 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004344 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004345 }
4346
Jiang Liu0e242612014-02-19 14:07:34 +08004347 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004348 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4349 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4350 if (atsr->segment != pci_domain_nr(dev->bus))
4351 continue;
4352
Jiang Liub683b232014-02-19 14:07:32 +08004353 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004354 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004355 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004356
4357 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004358 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004359 }
Jiang Liub683b232014-02-19 14:07:32 +08004360 ret = 0;
4361out:
Jiang Liu0e242612014-02-19 14:07:34 +08004362 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004363
Jiang Liub683b232014-02-19 14:07:32 +08004364 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004365}
4366
Jiang Liu59ce0512014-02-19 14:07:35 +08004367int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4368{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004369 int ret;
Jiang Liu59ce0512014-02-19 14:07:35 +08004370 struct dmar_rmrr_unit *rmrru;
4371 struct dmar_atsr_unit *atsru;
4372 struct acpi_dmar_atsr *atsr;
4373 struct acpi_dmar_reserved_memory *rmrr;
4374
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004375 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004376 return 0;
4377
4378 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4379 rmrr = container_of(rmrru->hdr,
4380 struct acpi_dmar_reserved_memory, header);
4381 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4382 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4383 ((void *)rmrr) + rmrr->header.length,
4384 rmrr->segment, rmrru->devices,
4385 rmrru->devices_cnt);
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004386 if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004387 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004388 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004389 dmar_remove_dev_scope(info, rmrr->segment,
4390 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004391 }
4392 }
4393
4394 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4395 if (atsru->include_all)
4396 continue;
4397
4398 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4399 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4400 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4401 (void *)atsr + atsr->header.length,
4402 atsr->segment, atsru->devices,
4403 atsru->devices_cnt);
4404 if (ret > 0)
4405 break;
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004406 else if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004407 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004408 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004409 if (dmar_remove_dev_scope(info, atsr->segment,
4410 atsru->devices, atsru->devices_cnt))
4411 break;
4412 }
4413 }
4414
4415 return 0;
4416}
4417
Jiang Liu75f05562014-02-19 14:07:37 +08004418static int intel_iommu_memory_notifier(struct notifier_block *nb,
4419 unsigned long val, void *v)
4420{
4421 struct memory_notify *mhp = v;
4422 unsigned long long start, end;
4423 unsigned long start_vpfn, last_vpfn;
4424
4425 switch (val) {
4426 case MEM_GOING_ONLINE:
4427 start = mhp->start_pfn << PAGE_SHIFT;
4428 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4429 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004430 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004431 start, end);
4432 return NOTIFY_BAD;
4433 }
4434 break;
4435
4436 case MEM_OFFLINE:
4437 case MEM_CANCEL_ONLINE:
4438 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4439 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4440 while (start_vpfn <= last_vpfn) {
4441 struct iova *iova;
4442 struct dmar_drhd_unit *drhd;
4443 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004444 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004445
4446 iova = find_iova(&si_domain->iovad, start_vpfn);
4447 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004448 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004449 start_vpfn);
4450 break;
4451 }
4452
4453 iova = split_and_remove_iova(&si_domain->iovad, iova,
4454 start_vpfn, last_vpfn);
4455 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004456 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004457 start_vpfn, last_vpfn);
4458 return NOTIFY_BAD;
4459 }
4460
David Woodhouseea8ea462014-03-05 17:09:32 +00004461 freelist = domain_unmap(si_domain, iova->pfn_lo,
4462 iova->pfn_hi);
4463
Jiang Liu75f05562014-02-19 14:07:37 +08004464 rcu_read_lock();
4465 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004466 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004467 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004468 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004469 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004470 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004471
4472 start_vpfn = iova->pfn_hi + 1;
4473 free_iova_mem(iova);
4474 }
4475 break;
4476 }
4477
4478 return NOTIFY_OK;
4479}
4480
4481static struct notifier_block intel_iommu_memory_nb = {
4482 .notifier_call = intel_iommu_memory_notifier,
4483 .priority = 0
4484};
4485
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004486static void free_all_cpu_cached_iovas(unsigned int cpu)
4487{
4488 int i;
4489
4490 for (i = 0; i < g_num_of_iommus; i++) {
4491 struct intel_iommu *iommu = g_iommus[i];
4492 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004493 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004494
4495 if (!iommu)
4496 continue;
4497
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004498 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004499 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004500
4501 if (!domain)
4502 continue;
4503 free_cpu_cached_iovas(cpu, &domain->iovad);
4504 }
4505 }
4506}
4507
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004508static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004509{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004510 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004511 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004512}
4513
Joerg Roedel161b28a2017-03-28 17:04:52 +02004514static void intel_disable_iommus(void)
4515{
4516 struct intel_iommu *iommu = NULL;
4517 struct dmar_drhd_unit *drhd;
4518
4519 for_each_iommu(iommu, drhd)
4520 iommu_disable_translation(iommu);
4521}
4522
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004523static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4524{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004525 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4526
4527 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004528}
4529
Alex Williamsona5459cf2014-06-12 16:12:31 -06004530static ssize_t intel_iommu_show_version(struct device *dev,
4531 struct device_attribute *attr,
4532 char *buf)
4533{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004534 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004535 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4536 return sprintf(buf, "%d:%d\n",
4537 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4538}
4539static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4540
4541static ssize_t intel_iommu_show_address(struct device *dev,
4542 struct device_attribute *attr,
4543 char *buf)
4544{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004545 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004546 return sprintf(buf, "%llx\n", iommu->reg_phys);
4547}
4548static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4549
4550static ssize_t intel_iommu_show_cap(struct device *dev,
4551 struct device_attribute *attr,
4552 char *buf)
4553{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004554 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004555 return sprintf(buf, "%llx\n", iommu->cap);
4556}
4557static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4558
4559static ssize_t intel_iommu_show_ecap(struct device *dev,
4560 struct device_attribute *attr,
4561 char *buf)
4562{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004563 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004564 return sprintf(buf, "%llx\n", iommu->ecap);
4565}
4566static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4567
Alex Williamson2238c082015-07-14 15:24:53 -06004568static ssize_t intel_iommu_show_ndoms(struct device *dev,
4569 struct device_attribute *attr,
4570 char *buf)
4571{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004572 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004573 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4574}
4575static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4576
4577static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4578 struct device_attribute *attr,
4579 char *buf)
4580{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004581 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004582 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4583 cap_ndoms(iommu->cap)));
4584}
4585static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4586
Alex Williamsona5459cf2014-06-12 16:12:31 -06004587static struct attribute *intel_iommu_attrs[] = {
4588 &dev_attr_version.attr,
4589 &dev_attr_address.attr,
4590 &dev_attr_cap.attr,
4591 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004592 &dev_attr_domains_supported.attr,
4593 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004594 NULL,
4595};
4596
4597static struct attribute_group intel_iommu_group = {
4598 .name = "intel-iommu",
4599 .attrs = intel_iommu_attrs,
4600};
4601
4602const struct attribute_group *intel_iommu_groups[] = {
4603 &intel_iommu_group,
4604 NULL,
4605};
4606
Lu Baolu89a60792018-10-23 15:45:01 +08004607static int __init platform_optin_force_iommu(void)
4608{
4609 struct pci_dev *pdev = NULL;
4610 bool has_untrusted_dev = false;
4611
4612 if (!dmar_platform_optin() || no_platform_optin)
4613 return 0;
4614
4615 for_each_pci_dev(pdev) {
4616 if (pdev->untrusted) {
4617 has_untrusted_dev = true;
4618 break;
4619 }
4620 }
4621
4622 if (!has_untrusted_dev)
4623 return 0;
4624
4625 if (no_iommu || dmar_disabled)
4626 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4627
4628 /*
4629 * If Intel-IOMMU is disabled by default, we will apply identity
4630 * map for all devices except those marked as being untrusted.
4631 */
4632 if (dmar_disabled)
4633 iommu_identity_mapping |= IDENTMAP_ALL;
4634
4635 dmar_disabled = 0;
4636#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
4637 swiotlb = 0;
4638#endif
4639 no_iommu = 0;
4640
4641 return 1;
4642}
4643
Lu Baolufa212a92019-05-25 13:41:31 +08004644static int __init probe_acpi_namespace_devices(void)
4645{
4646 struct dmar_drhd_unit *drhd;
4647 struct intel_iommu *iommu;
4648 struct device *dev;
4649 int i, ret = 0;
4650
4651 for_each_active_iommu(iommu, drhd) {
4652 for_each_active_dev_scope(drhd->devices,
4653 drhd->devices_cnt, i, dev) {
4654 struct acpi_device_physical_node *pn;
4655 struct iommu_group *group;
4656 struct acpi_device *adev;
4657
4658 if (dev->bus != &acpi_bus_type)
4659 continue;
4660
4661 adev = to_acpi_device(dev);
4662 mutex_lock(&adev->physical_node_lock);
4663 list_for_each_entry(pn,
4664 &adev->physical_node_list, node) {
4665 group = iommu_group_get(pn->dev);
4666 if (group) {
4667 iommu_group_put(group);
4668 continue;
4669 }
4670
4671 pn->dev->bus->iommu_ops = &intel_iommu_ops;
4672 ret = iommu_probe_device(pn->dev);
4673 if (ret)
4674 break;
4675 }
4676 mutex_unlock(&adev->physical_node_lock);
4677
4678 if (ret)
4679 return ret;
4680 }
4681 }
4682
4683 return 0;
4684}
4685
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004686int __init intel_iommu_init(void)
4687{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004688 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004689 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004690 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004691
Lu Baolu89a60792018-10-23 15:45:01 +08004692 /*
4693 * Intel IOMMU is required for a TXT/tboot launch or platform
4694 * opt in, so enforce that.
4695 */
4696 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004697
Jiang Liu3a5670e2014-02-19 14:07:33 +08004698 if (iommu_init_mempool()) {
4699 if (force_on)
4700 panic("tboot: Failed to initialize iommu memory\n");
4701 return -ENOMEM;
4702 }
4703
4704 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004705 if (dmar_table_init()) {
4706 if (force_on)
4707 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004708 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004709 }
4710
Suresh Siddhac2c72862011-08-23 17:05:19 -07004711 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004712 if (force_on)
4713 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004714 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004715 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004716
Joerg Roedelec154bf2017-10-06 15:00:53 +02004717 up_write(&dmar_global_lock);
4718
4719 /*
4720 * The bus notifier takes the dmar_global_lock, so lockdep will
4721 * complain later when we register it under the lock.
4722 */
4723 dmar_register_bus_notifier();
4724
4725 down_write(&dmar_global_lock);
4726
Joerg Roedel161b28a2017-03-28 17:04:52 +02004727 if (no_iommu || dmar_disabled) {
4728 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004729 * We exit the function here to ensure IOMMU's remapping and
4730 * mempool aren't setup, which means that the IOMMU's PMRs
4731 * won't be disabled via the call to init_dmars(). So disable
4732 * it explicitly here. The PMRs were setup by tboot prior to
4733 * calling SENTER, but the kernel is expected to reset/tear
4734 * down the PMRs.
4735 */
4736 if (intel_iommu_tboot_noforce) {
4737 for_each_iommu(iommu, drhd)
4738 iommu_disable_protect_mem_regions(iommu);
4739 }
4740
4741 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004742 * Make sure the IOMMUs are switched off, even when we
4743 * boot into a kexec kernel and the previous kernel left
4744 * them enabled
4745 */
4746 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004747 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004748 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004749
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004750 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004751 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004752
4753 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004754 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004755
Joseph Cihula51a63e62011-03-21 11:04:24 -07004756 if (dmar_init_reserved_ranges()) {
4757 if (force_on)
4758 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004759 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004760 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004761
Lu Baolucf1ec452019-05-02 09:34:25 +08004762 if (dmar_map_gfx)
4763 intel_iommu_gfx_mapped = 1;
4764
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004765 init_no_remapping_devices();
4766
Joseph Cihulab7792602011-05-03 00:08:37 -07004767 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004768 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004769 if (force_on)
4770 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004771 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004772 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004773 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004774 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004775
Christoph Hellwig4fac8072017-12-24 13:57:08 +01004776#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004777 swiotlb = 0;
4778#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004779 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004780
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004781 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004782
Joerg Roedel39ab9552017-02-01 16:56:46 +01004783 for_each_active_iommu(iommu, drhd) {
4784 iommu_device_sysfs_add(&iommu->iommu, NULL,
4785 intel_iommu_groups,
4786 "%s", iommu->name);
4787 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4788 iommu_device_register(&iommu->iommu);
4789 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06004790
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004791 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Jiang Liu75f05562014-02-19 14:07:37 +08004792 if (si_domain && !hw_pass_through)
4793 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004794 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4795 intel_iommu_cpu_dead);
Lu Baolud8190dc2019-05-25 13:41:25 +08004796
Lu Baolufa212a92019-05-25 13:41:31 +08004797 if (probe_acpi_namespace_devices())
4798 pr_warn("ACPI name space devices didn't probe correctly\n");
4799
Lu Baolud8190dc2019-05-25 13:41:25 +08004800 /* Finally, we enable the DMA remapping hardware. */
4801 for_each_iommu(iommu, drhd) {
4802 if (!translation_pre_enabled(iommu))
4803 iommu_enable_translation(iommu);
4804
4805 iommu_disable_protect_mem_regions(iommu);
4806 }
4807 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
4808
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004809 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07004810 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004811
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004812 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004813
4814out_free_reserved_range:
4815 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004816out_free_dmar:
4817 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004818 up_write(&dmar_global_lock);
4819 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004820 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004821}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004822
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004823static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004824{
4825 struct intel_iommu *iommu = opaque;
4826
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004827 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004828 return 0;
4829}
4830
4831/*
4832 * NB - intel-iommu lacks any sort of reference counting for the users of
4833 * dependent devices. If multiple endpoints have intersecting dependent
4834 * devices, unbinding the driver from any one of them will possibly leave
4835 * the others unable to operate.
4836 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004837static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004838{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004839 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004840 return;
4841
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004842 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004843}
4844
Joerg Roedel127c7612015-07-23 17:44:46 +02004845static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004846{
Lu Baolu942067f2019-05-25 13:41:29 +08004847 struct dmar_domain *domain;
Weidong Hanc7151a82008-12-08 22:51:37 +08004848 struct intel_iommu *iommu;
4849 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004850
Joerg Roedel55d94042015-07-22 16:50:40 +02004851 assert_spin_locked(&device_domain_lock);
4852
Joerg Roedelb608ac32015-07-21 18:19:08 +02004853 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004854 return;
4855
Joerg Roedel127c7612015-07-23 17:44:46 +02004856 iommu = info->iommu;
Lu Baolu942067f2019-05-25 13:41:29 +08004857 domain = info->domain;
Joerg Roedel127c7612015-07-23 17:44:46 +02004858
4859 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08004860 if (dev_is_pci(info->dev) && sm_supported(iommu))
4861 intel_pasid_tear_down_entry(iommu, info->dev,
4862 PASID_RID2PASID);
4863
Joerg Roedel127c7612015-07-23 17:44:46 +02004864 iommu_disable_dev_iotlb(info);
4865 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08004866 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02004867 }
4868
Joerg Roedelb608ac32015-07-21 18:19:08 +02004869 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004870
Joerg Roedeld160aca2015-07-22 11:52:53 +02004871 spin_lock_irqsave(&iommu->lock, flags);
Lu Baolu942067f2019-05-25 13:41:29 +08004872 domain_detach_iommu(domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004873 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004874
Lu Baolu942067f2019-05-25 13:41:29 +08004875 /* free the private domain */
4876 if (domain->flags & DOMAIN_FLAG_LOSE_CHILDREN &&
4877 !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY))
4878 domain_exit(info->domain);
4879
Joerg Roedel127c7612015-07-23 17:44:46 +02004880 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004881}
4882
Bjorn Helgaas71753232019-02-08 16:06:15 -06004883static void dmar_remove_one_dev_info(struct device *dev)
Joerg Roedel55d94042015-07-22 16:50:40 +02004884{
Joerg Roedel127c7612015-07-23 17:44:46 +02004885 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02004886 unsigned long flags;
4887
Weidong Hanc7151a82008-12-08 22:51:37 +08004888 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004889 info = dev->archdata.iommu;
4890 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004891 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004892}
4893
4894static int md_domain_init(struct dmar_domain *domain, int guest_width)
4895{
4896 int adjust_width;
4897
Zhen Leiaa3ac942017-09-21 16:52:45 +01004898 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004899 domain_reserve_special_ranges(domain);
4900
4901 /* calculate AGAW */
4902 domain->gaw = guest_width;
4903 adjust_width = guestwidth_to_adjustwidth(guest_width);
4904 domain->agaw = width_to_agaw(adjust_width);
4905
Weidong Han5e98c4b2008-12-08 23:03:27 +08004906 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004907 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004908 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004909 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004910
4911 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004912 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004913 if (!domain->pgd)
4914 return -ENOMEM;
4915 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4916 return 0;
4917}
4918
Joerg Roedel00a77de2015-03-26 13:43:08 +01004919static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03004920{
Joerg Roedel5d450802008-12-03 14:52:32 +01004921 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01004922 struct iommu_domain *domain;
4923
Lu Baolu4de354e2019-05-25 13:41:27 +08004924 switch (type) {
Lu Baolufa954e62019-05-25 13:41:28 +08004925 case IOMMU_DOMAIN_DMA:
4926 /* fallthrough */
Lu Baolu4de354e2019-05-25 13:41:27 +08004927 case IOMMU_DOMAIN_UNMANAGED:
Lu Baolufa954e62019-05-25 13:41:28 +08004928 dmar_domain = alloc_domain(0);
Lu Baolu4de354e2019-05-25 13:41:27 +08004929 if (!dmar_domain) {
4930 pr_err("Can't allocate dmar_domain\n");
4931 return NULL;
4932 }
4933 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
4934 pr_err("Domain initialization failed\n");
4935 domain_exit(dmar_domain);
4936 return NULL;
4937 }
Lu Baolufa954e62019-05-25 13:41:28 +08004938
4939 if (type == IOMMU_DOMAIN_DMA &&
4940 init_iova_flush_queue(&dmar_domain->iovad,
4941 iommu_flush_iova, iova_entry_free)) {
4942 pr_warn("iova flush queue initialization failed\n");
4943 intel_iommu_strict = 1;
4944 }
4945
Lu Baolu4de354e2019-05-25 13:41:27 +08004946 domain_update_iommu_cap(dmar_domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004947
Lu Baolu4de354e2019-05-25 13:41:27 +08004948 domain = &dmar_domain->domain;
4949 domain->geometry.aperture_start = 0;
4950 domain->geometry.aperture_end =
4951 __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4952 domain->geometry.force_aperture = true;
4953
4954 return domain;
4955 case IOMMU_DOMAIN_IDENTITY:
4956 return &si_domain->domain;
4957 default:
Joerg Roedel00a77de2015-03-26 13:43:08 +01004958 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004959 }
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004960
Lu Baolu4de354e2019-05-25 13:41:27 +08004961 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004962}
Kay, Allen M38717942008-09-09 18:37:29 +03004963
Joerg Roedel00a77de2015-03-26 13:43:08 +01004964static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004965{
Lu Baolu4de354e2019-05-25 13:41:27 +08004966 if (domain != &si_domain->domain)
4967 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03004968}
Kay, Allen M38717942008-09-09 18:37:29 +03004969
Lu Baolu67b8e022019-03-25 09:30:32 +08004970/*
4971 * Check whether a @domain could be attached to the @dev through the
4972 * aux-domain attach/detach APIs.
4973 */
4974static inline bool
4975is_aux_domain(struct device *dev, struct iommu_domain *domain)
4976{
4977 struct device_domain_info *info = dev->archdata.iommu;
4978
4979 return info && info->auxd_enabled &&
4980 domain->type == IOMMU_DOMAIN_UNMANAGED;
4981}
4982
4983static void auxiliary_link_device(struct dmar_domain *domain,
4984 struct device *dev)
4985{
4986 struct device_domain_info *info = dev->archdata.iommu;
4987
4988 assert_spin_locked(&device_domain_lock);
4989 if (WARN_ON(!info))
4990 return;
4991
4992 domain->auxd_refcnt++;
4993 list_add(&domain->auxd, &info->auxiliary_domains);
4994}
4995
4996static void auxiliary_unlink_device(struct dmar_domain *domain,
4997 struct device *dev)
4998{
4999 struct device_domain_info *info = dev->archdata.iommu;
5000
5001 assert_spin_locked(&device_domain_lock);
5002 if (WARN_ON(!info))
5003 return;
5004
5005 list_del(&domain->auxd);
5006 domain->auxd_refcnt--;
5007
5008 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5009 intel_pasid_free_id(domain->default_pasid);
5010}
5011
5012static int aux_domain_add_dev(struct dmar_domain *domain,
5013 struct device *dev)
5014{
5015 int ret;
5016 u8 bus, devfn;
5017 unsigned long flags;
5018 struct intel_iommu *iommu;
5019
5020 iommu = device_to_iommu(dev, &bus, &devfn);
5021 if (!iommu)
5022 return -ENODEV;
5023
5024 if (domain->default_pasid <= 0) {
5025 int pasid;
5026
5027 pasid = intel_pasid_alloc_id(domain, PASID_MIN,
5028 pci_max_pasids(to_pci_dev(dev)),
5029 GFP_KERNEL);
5030 if (pasid <= 0) {
5031 pr_err("Can't allocate default pasid\n");
5032 return -ENODEV;
5033 }
5034 domain->default_pasid = pasid;
5035 }
5036
5037 spin_lock_irqsave(&device_domain_lock, flags);
5038 /*
5039 * iommu->lock must be held to attach domain to iommu and setup the
5040 * pasid entry for second level translation.
5041 */
5042 spin_lock(&iommu->lock);
5043 ret = domain_attach_iommu(domain, iommu);
5044 if (ret)
5045 goto attach_failed;
5046
5047 /* Setup the PASID entry for mediated devices: */
5048 ret = intel_pasid_setup_second_level(iommu, domain, dev,
5049 domain->default_pasid);
5050 if (ret)
5051 goto table_failed;
5052 spin_unlock(&iommu->lock);
5053
5054 auxiliary_link_device(domain, dev);
5055
5056 spin_unlock_irqrestore(&device_domain_lock, flags);
5057
5058 return 0;
5059
5060table_failed:
5061 domain_detach_iommu(domain, iommu);
5062attach_failed:
5063 spin_unlock(&iommu->lock);
5064 spin_unlock_irqrestore(&device_domain_lock, flags);
5065 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5066 intel_pasid_free_id(domain->default_pasid);
5067
5068 return ret;
5069}
5070
5071static void aux_domain_remove_dev(struct dmar_domain *domain,
5072 struct device *dev)
5073{
5074 struct device_domain_info *info;
5075 struct intel_iommu *iommu;
5076 unsigned long flags;
5077
5078 if (!is_aux_domain(dev, &domain->domain))
5079 return;
5080
5081 spin_lock_irqsave(&device_domain_lock, flags);
5082 info = dev->archdata.iommu;
5083 iommu = info->iommu;
5084
5085 auxiliary_unlink_device(domain, dev);
5086
5087 spin_lock(&iommu->lock);
5088 intel_pasid_tear_down_entry(iommu, dev, domain->default_pasid);
5089 domain_detach_iommu(domain, iommu);
5090 spin_unlock(&iommu->lock);
5091
5092 spin_unlock_irqrestore(&device_domain_lock, flags);
5093}
5094
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005095static int prepare_domain_attach_device(struct iommu_domain *domain,
5096 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005097{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005098 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005099 struct intel_iommu *iommu;
5100 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005101 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005102
David Woodhouse156baca2014-03-09 14:00:57 -07005103 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005104 if (!iommu)
5105 return -ENODEV;
5106
5107 /* check if this iommu agaw is sufficient for max mapped address */
5108 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005109 if (addr_width > cap_mgaw(iommu->cap))
5110 addr_width = cap_mgaw(iommu->cap);
5111
5112 if (dmar_domain->max_addr > (1LL << addr_width)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005113 dev_err(dev, "%s: iommu width (%d) is not "
5114 "sufficient for the mapped address (%llx)\n",
5115 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005116 return -EFAULT;
5117 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005118 dmar_domain->gaw = addr_width;
5119
5120 /*
5121 * Knock out extra levels of page tables if necessary
5122 */
5123 while (iommu->agaw < dmar_domain->agaw) {
5124 struct dma_pte *pte;
5125
5126 pte = dmar_domain->pgd;
5127 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005128 dmar_domain->pgd = (struct dma_pte *)
5129 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005130 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005131 }
5132 dmar_domain->agaw--;
5133 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005134
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005135 return 0;
5136}
5137
5138static int intel_iommu_attach_device(struct iommu_domain *domain,
5139 struct device *dev)
5140{
5141 int ret;
5142
5143 if (device_is_rmrr_locked(dev)) {
5144 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5145 return -EPERM;
5146 }
5147
Lu Baolu67b8e022019-03-25 09:30:32 +08005148 if (is_aux_domain(dev, domain))
5149 return -EPERM;
5150
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005151 /* normally dev is not mapped */
5152 if (unlikely(domain_context_mapped(dev))) {
5153 struct dmar_domain *old_domain;
5154
5155 old_domain = find_domain(dev);
Lu Baolufa954e62019-05-25 13:41:28 +08005156 if (old_domain)
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005157 dmar_remove_one_dev_info(dev);
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005158 }
5159
5160 ret = prepare_domain_attach_device(domain, dev);
5161 if (ret)
5162 return ret;
5163
5164 return domain_add_dev_info(to_dmar_domain(domain), dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005165}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005166
Lu Baolu67b8e022019-03-25 09:30:32 +08005167static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
5168 struct device *dev)
5169{
5170 int ret;
5171
5172 if (!is_aux_domain(dev, domain))
5173 return -EPERM;
5174
5175 ret = prepare_domain_attach_device(domain, dev);
5176 if (ret)
5177 return ret;
5178
5179 return aux_domain_add_dev(to_dmar_domain(domain), dev);
5180}
5181
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005182static void intel_iommu_detach_device(struct iommu_domain *domain,
5183 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005184{
Bjorn Helgaas71753232019-02-08 16:06:15 -06005185 dmar_remove_one_dev_info(dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005186}
Kay, Allen M38717942008-09-09 18:37:29 +03005187
Lu Baolu67b8e022019-03-25 09:30:32 +08005188static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
5189 struct device *dev)
5190{
5191 aux_domain_remove_dev(to_dmar_domain(domain), dev);
5192}
5193
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005194static int intel_iommu_map(struct iommu_domain *domain,
5195 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005196 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03005197{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005198 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005199 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005200 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005201 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005202
Lu Baolu942067f2019-05-25 13:41:29 +08005203 if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
5204 return -EINVAL;
5205
Joerg Roedeldde57a22008-12-03 15:04:09 +01005206 if (iommu_prot & IOMMU_READ)
5207 prot |= DMA_PTE_READ;
5208 if (iommu_prot & IOMMU_WRITE)
5209 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005210 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5211 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005212
David Woodhouse163cc522009-06-28 00:51:17 +01005213 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005214 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005215 u64 end;
5216
5217 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005218 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005219 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005220 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005221 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005222 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005223 return -EFAULT;
5224 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005225 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005226 }
David Woodhousead051222009-06-28 14:22:28 +01005227 /* Round up size to next multiple of PAGE_SIZE, if it and
5228 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005229 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005230 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5231 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005232 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005233}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005234
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005235static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00005236 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005237{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005238 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005239 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005240 unsigned long start_pfn, last_pfn;
5241 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005242 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005243
David Woodhouse5cf0a762014-03-19 16:07:49 +00005244 /* Cope with horrid API which requires us to unmap more than the
5245 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005246 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
Lu Baolu942067f2019-05-25 13:41:29 +08005247 if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
5248 return 0;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005249
5250 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5251 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5252
David Woodhouseea8ea462014-03-05 17:09:32 +00005253 start_pfn = iova >> VTD_PAGE_SHIFT;
5254 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5255
5256 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5257
5258 npages = last_pfn - start_pfn + 1;
5259
Shaokun Zhangf746a022018-03-22 18:18:06 +08005260 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005261 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5262 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005263
5264 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005265
David Woodhouse163cc522009-06-28 00:51:17 +01005266 if (dmar_domain->max_addr == iova + size)
5267 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005268
David Woodhouse5cf0a762014-03-19 16:07:49 +00005269 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005270}
Kay, Allen M38717942008-09-09 18:37:29 +03005271
Joerg Roedeld14d6572008-12-03 15:06:57 +01005272static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305273 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005274{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005275 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005276 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005277 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005278 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005279
Lu Baolu942067f2019-05-25 13:41:29 +08005280 if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
5281 return 0;
5282
David Woodhouse5cf0a762014-03-19 16:07:49 +00005283 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005284 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005285 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005286
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005287 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005288}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005289
Lu Baolu95587a72019-03-25 09:30:30 +08005290static inline bool scalable_mode_support(void)
5291{
5292 struct dmar_drhd_unit *drhd;
5293 struct intel_iommu *iommu;
5294 bool ret = true;
5295
5296 rcu_read_lock();
5297 for_each_active_iommu(iommu, drhd) {
5298 if (!sm_supported(iommu)) {
5299 ret = false;
5300 break;
5301 }
5302 }
5303 rcu_read_unlock();
5304
5305 return ret;
5306}
5307
5308static inline bool iommu_pasid_support(void)
5309{
5310 struct dmar_drhd_unit *drhd;
5311 struct intel_iommu *iommu;
5312 bool ret = true;
5313
5314 rcu_read_lock();
5315 for_each_active_iommu(iommu, drhd) {
5316 if (!pasid_supported(iommu)) {
5317 ret = false;
5318 break;
5319 }
5320 }
5321 rcu_read_unlock();
5322
5323 return ret;
5324}
5325
Joerg Roedel5d587b82014-09-05 10:50:45 +02005326static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005327{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005328 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005329 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005330 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005331 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005332
Joerg Roedel5d587b82014-09-05 10:50:45 +02005333 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005334}
5335
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005336static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005337{
Lu Baolu942067f2019-05-25 13:41:29 +08005338 struct dmar_domain *dmar_domain;
5339 struct iommu_domain *domain;
Alex Williamsona5459cf2014-06-12 16:12:31 -06005340 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005341 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005342 u8 bus, devfn;
Lu Baolu942067f2019-05-25 13:41:29 +08005343 int ret;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005344
Alex Williamsona5459cf2014-06-12 16:12:31 -06005345 iommu = device_to_iommu(dev, &bus, &devfn);
5346 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005347 return -ENODEV;
5348
Joerg Roedele3d10af2017-02-01 17:23:22 +01005349 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005350
Lu Baolu8af46c72019-05-25 13:41:32 +08005351 if (translation_pre_enabled(iommu))
5352 dev->archdata.iommu = DEFER_DEVICE_DOMAIN_INFO;
5353
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005354 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005355
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005356 if (IS_ERR(group))
5357 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005358
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005359 iommu_group_put(group);
Lu Baolu942067f2019-05-25 13:41:29 +08005360
5361 domain = iommu_get_domain_for_dev(dev);
5362 dmar_domain = to_dmar_domain(domain);
5363 if (domain->type == IOMMU_DOMAIN_DMA) {
Lu Baolu0e31a722019-05-25 13:41:34 +08005364 if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
Lu Baolu942067f2019-05-25 13:41:29 +08005365 ret = iommu_request_dm_for_dev(dev);
5366 if (ret) {
5367 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
5368 domain_add_dev_info(si_domain, dev);
5369 dev_info(dev,
5370 "Device uses a private identity domain.\n");
5371 return 0;
5372 }
5373
5374 return -ENODEV;
5375 }
5376 } else {
Lu Baolu0e31a722019-05-25 13:41:34 +08005377 if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) {
Lu Baolu942067f2019-05-25 13:41:29 +08005378 ret = iommu_request_dma_domain_for_dev(dev);
5379 if (ret) {
5380 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
Lu Baolu4ec066c2019-05-25 13:41:33 +08005381 if (!get_private_domain_for_dev(dev)) {
Lu Baolu942067f2019-05-25 13:41:29 +08005382 dev_warn(dev,
5383 "Failed to get a private domain.\n");
5384 return -ENOMEM;
5385 }
5386
5387 dev_info(dev,
5388 "Device uses a private dma domain.\n");
5389 return 0;
5390 }
5391
5392 return -ENODEV;
5393 }
5394 }
5395
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005396 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005397}
5398
5399static void intel_iommu_remove_device(struct device *dev)
5400{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005401 struct intel_iommu *iommu;
5402 u8 bus, devfn;
5403
5404 iommu = device_to_iommu(dev, &bus, &devfn);
5405 if (!iommu)
5406 return;
5407
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005408 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005409
Joerg Roedele3d10af2017-02-01 17:23:22 +01005410 iommu_device_unlink(&iommu->iommu, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005411}
5412
Eric Auger0659b8d2017-01-19 20:57:53 +00005413static void intel_iommu_get_resv_regions(struct device *device,
5414 struct list_head *head)
5415{
Eric Auger5f64ce52019-06-03 08:53:31 +02005416 int prot = DMA_PTE_READ | DMA_PTE_WRITE;
Eric Auger0659b8d2017-01-19 20:57:53 +00005417 struct iommu_resv_region *reg;
5418 struct dmar_rmrr_unit *rmrr;
5419 struct device *i_dev;
5420 int i;
5421
Eric Auger5f64ce52019-06-03 08:53:31 +02005422 down_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005423 for_each_rmrr_units(rmrr) {
5424 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5425 i, i_dev) {
Eric Auger5f64ce52019-06-03 08:53:31 +02005426 struct iommu_resv_region *resv;
5427 size_t length;
5428
Eric Auger0659b8d2017-01-19 20:57:53 +00005429 if (i_dev != device)
5430 continue;
5431
Eric Auger5f64ce52019-06-03 08:53:31 +02005432 length = rmrr->end_address - rmrr->base_address + 1;
5433 resv = iommu_alloc_resv_region(rmrr->base_address,
5434 length, prot,
5435 IOMMU_RESV_DIRECT);
5436 if (!resv)
5437 break;
5438
5439 list_add_tail(&resv->list, head);
Eric Auger0659b8d2017-01-19 20:57:53 +00005440 }
5441 }
Eric Auger5f64ce52019-06-03 08:53:31 +02005442 up_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005443
Lu Baolud850c2e2019-05-25 13:41:24 +08005444#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
5445 if (dev_is_pci(device)) {
5446 struct pci_dev *pdev = to_pci_dev(device);
5447
5448 if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
5449 reg = iommu_alloc_resv_region(0, 1UL << 24, 0,
5450 IOMMU_RESV_DIRECT);
5451 if (reg)
5452 list_add_tail(&reg->list, head);
5453 }
5454 }
5455#endif /* CONFIG_INTEL_IOMMU_FLOPPY_WA */
5456
Eric Auger0659b8d2017-01-19 20:57:53 +00005457 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5458 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005459 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005460 if (!reg)
5461 return;
5462 list_add_tail(&reg->list, head);
5463}
5464
5465static void intel_iommu_put_resv_regions(struct device *dev,
5466 struct list_head *head)
5467{
5468 struct iommu_resv_region *entry, *next;
5469
Eric Auger5f64ce52019-06-03 08:53:31 +02005470 list_for_each_entry_safe(entry, next, head, list)
5471 kfree(entry);
Kay, Allen M38717942008-09-09 18:37:29 +03005472}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005473
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005474int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005475{
5476 struct device_domain_info *info;
5477 struct context_entry *context;
5478 struct dmar_domain *domain;
5479 unsigned long flags;
5480 u64 ctx_lo;
5481 int ret;
5482
Lu Baolu4ec066c2019-05-25 13:41:33 +08005483 domain = find_domain(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005484 if (!domain)
5485 return -EINVAL;
5486
5487 spin_lock_irqsave(&device_domain_lock, flags);
5488 spin_lock(&iommu->lock);
5489
5490 ret = -EINVAL;
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005491 info = dev->archdata.iommu;
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005492 if (!info || !info->pasid_supported)
5493 goto out;
5494
5495 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5496 if (WARN_ON(!context))
5497 goto out;
5498
5499 ctx_lo = context[0].lo;
5500
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005501 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005502 ctx_lo |= CONTEXT_PASIDE;
5503 context[0].lo = ctx_lo;
5504 wmb();
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005505 iommu->flush.flush_context(iommu,
5506 domain->iommu_did[iommu->seq_id],
5507 PCI_DEVID(info->bus, info->devfn),
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005508 DMA_CCMD_MASK_NOBIT,
5509 DMA_CCMD_DEVICE_INVL);
5510 }
5511
5512 /* Enable PASID support in the device, if it wasn't already */
5513 if (!info->pasid_enabled)
5514 iommu_enable_dev_iotlb(info);
5515
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005516 ret = 0;
5517
5518 out:
5519 spin_unlock(&iommu->lock);
5520 spin_unlock_irqrestore(&device_domain_lock, flags);
5521
5522 return ret;
5523}
5524
James Sewart73bcbdc2019-05-25 13:41:23 +08005525static void intel_iommu_apply_resv_region(struct device *dev,
5526 struct iommu_domain *domain,
5527 struct iommu_resv_region *region)
5528{
5529 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5530 unsigned long start, end;
5531
5532 start = IOVA_PFN(region->start);
5533 end = IOVA_PFN(region->start + region->length - 1);
5534
5535 WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
5536}
5537
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005538#ifdef CONFIG_INTEL_IOMMU_SVM
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005539struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5540{
5541 struct intel_iommu *iommu;
5542 u8 bus, devfn;
5543
5544 if (iommu_dummy(dev)) {
5545 dev_warn(dev,
5546 "No IOMMU translation for device; cannot enable SVM\n");
5547 return NULL;
5548 }
5549
5550 iommu = device_to_iommu(dev, &bus, &devfn);
5551 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07005552 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005553 return NULL;
5554 }
5555
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005556 return iommu;
5557}
5558#endif /* CONFIG_INTEL_IOMMU_SVM */
5559
Lu Baolu95587a72019-03-25 09:30:30 +08005560static int intel_iommu_enable_auxd(struct device *dev)
5561{
5562 struct device_domain_info *info;
5563 struct intel_iommu *iommu;
5564 unsigned long flags;
5565 u8 bus, devfn;
5566 int ret;
5567
5568 iommu = device_to_iommu(dev, &bus, &devfn);
5569 if (!iommu || dmar_disabled)
5570 return -EINVAL;
5571
5572 if (!sm_supported(iommu) || !pasid_supported(iommu))
5573 return -EINVAL;
5574
5575 ret = intel_iommu_enable_pasid(iommu, dev);
5576 if (ret)
5577 return -ENODEV;
5578
5579 spin_lock_irqsave(&device_domain_lock, flags);
5580 info = dev->archdata.iommu;
5581 info->auxd_enabled = 1;
5582 spin_unlock_irqrestore(&device_domain_lock, flags);
5583
5584 return 0;
5585}
5586
5587static int intel_iommu_disable_auxd(struct device *dev)
5588{
5589 struct device_domain_info *info;
5590 unsigned long flags;
5591
5592 spin_lock_irqsave(&device_domain_lock, flags);
5593 info = dev->archdata.iommu;
5594 if (!WARN_ON(!info))
5595 info->auxd_enabled = 0;
5596 spin_unlock_irqrestore(&device_domain_lock, flags);
5597
5598 return 0;
5599}
5600
5601/*
5602 * A PCI express designated vendor specific extended capability is defined
5603 * in the section 3.7 of Intel scalable I/O virtualization technical spec
5604 * for system software and tools to detect endpoint devices supporting the
5605 * Intel scalable IO virtualization without host driver dependency.
5606 *
5607 * Returns the address of the matching extended capability structure within
5608 * the device's PCI configuration space or 0 if the device does not support
5609 * it.
5610 */
5611static int siov_find_pci_dvsec(struct pci_dev *pdev)
5612{
5613 int pos;
5614 u16 vendor, id;
5615
5616 pos = pci_find_next_ext_capability(pdev, 0, 0x23);
5617 while (pos) {
5618 pci_read_config_word(pdev, pos + 4, &vendor);
5619 pci_read_config_word(pdev, pos + 8, &id);
5620 if (vendor == PCI_VENDOR_ID_INTEL && id == 5)
5621 return pos;
5622
5623 pos = pci_find_next_ext_capability(pdev, pos, 0x23);
5624 }
5625
5626 return 0;
5627}
5628
5629static bool
5630intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat)
5631{
5632 if (feat == IOMMU_DEV_FEAT_AUX) {
5633 int ret;
5634
5635 if (!dev_is_pci(dev) || dmar_disabled ||
5636 !scalable_mode_support() || !iommu_pasid_support())
5637 return false;
5638
5639 ret = pci_pasid_features(to_pci_dev(dev));
5640 if (ret < 0)
5641 return false;
5642
5643 return !!siov_find_pci_dvsec(to_pci_dev(dev));
5644 }
5645
5646 return false;
5647}
5648
5649static int
5650intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
5651{
5652 if (feat == IOMMU_DEV_FEAT_AUX)
5653 return intel_iommu_enable_auxd(dev);
5654
5655 return -ENODEV;
5656}
5657
5658static int
5659intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
5660{
5661 if (feat == IOMMU_DEV_FEAT_AUX)
5662 return intel_iommu_disable_auxd(dev);
5663
5664 return -ENODEV;
5665}
5666
5667static bool
5668intel_iommu_dev_feat_enabled(struct device *dev, enum iommu_dev_features feat)
5669{
5670 struct device_domain_info *info = dev->archdata.iommu;
5671
5672 if (feat == IOMMU_DEV_FEAT_AUX)
5673 return scalable_mode_support() && info && info->auxd_enabled;
5674
5675 return false;
5676}
5677
Lu Baolu0e8000f2019-03-25 09:30:33 +08005678static int
5679intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
5680{
5681 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5682
5683 return dmar_domain->default_pasid > 0 ?
5684 dmar_domain->default_pasid : -EINVAL;
5685}
5686
Lu Baolu8af46c72019-05-25 13:41:32 +08005687static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
5688 struct device *dev)
5689{
5690 return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
5691}
5692
Joerg Roedelb0119e82017-02-01 13:23:08 +01005693const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00005694 .capable = intel_iommu_capable,
5695 .domain_alloc = intel_iommu_domain_alloc,
5696 .domain_free = intel_iommu_domain_free,
5697 .attach_dev = intel_iommu_attach_device,
5698 .detach_dev = intel_iommu_detach_device,
Lu Baolu67b8e022019-03-25 09:30:32 +08005699 .aux_attach_dev = intel_iommu_aux_attach_device,
5700 .aux_detach_dev = intel_iommu_aux_detach_device,
Lu Baolu0e8000f2019-03-25 09:30:33 +08005701 .aux_get_pasid = intel_iommu_aux_get_pasid,
Eric Auger0659b8d2017-01-19 20:57:53 +00005702 .map = intel_iommu_map,
5703 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00005704 .iova_to_phys = intel_iommu_iova_to_phys,
5705 .add_device = intel_iommu_add_device,
5706 .remove_device = intel_iommu_remove_device,
5707 .get_resv_regions = intel_iommu_get_resv_regions,
5708 .put_resv_regions = intel_iommu_put_resv_regions,
James Sewart73bcbdc2019-05-25 13:41:23 +08005709 .apply_resv_region = intel_iommu_apply_resv_region,
Eric Auger0659b8d2017-01-19 20:57:53 +00005710 .device_group = pci_device_group,
Lu Baolu95587a72019-03-25 09:30:30 +08005711 .dev_has_feat = intel_iommu_dev_has_feat,
5712 .dev_feat_enabled = intel_iommu_dev_feat_enabled,
5713 .dev_enable_feat = intel_iommu_dev_enable_feat,
5714 .dev_disable_feat = intel_iommu_dev_disable_feat,
Lu Baolu8af46c72019-05-25 13:41:32 +08005715 .is_attach_deferred = intel_iommu_is_attach_deferred,
Eric Auger0659b8d2017-01-19 20:57:53 +00005716 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005717};
David Woodhouse9af88142009-02-13 23:18:03 +00005718
Daniel Vetter94526182013-01-20 23:50:13 +01005719static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
5720{
5721 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005722 pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01005723 dmar_map_gfx = 0;
5724}
5725
5726DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
5727DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
5728DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
5729DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
5730DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
5731DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
5732DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
5733
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005734static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00005735{
5736 /*
5737 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01005738 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00005739 */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005740 pci_info(dev, "Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00005741 rwbf_quirk = 1;
5742}
5743
5744DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01005745DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
5746DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
5747DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
5748DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
5749DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
5750DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07005751
Adam Jacksoneecfd572010-08-25 21:17:34 +01005752#define GGC 0x52
5753#define GGC_MEMORY_SIZE_MASK (0xf << 8)
5754#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
5755#define GGC_MEMORY_SIZE_1M (0x1 << 8)
5756#define GGC_MEMORY_SIZE_2M (0x3 << 8)
5757#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
5758#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
5759#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
5760#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
5761
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005762static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01005763{
5764 unsigned short ggc;
5765
Adam Jacksoneecfd572010-08-25 21:17:34 +01005766 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01005767 return;
5768
Adam Jacksoneecfd572010-08-25 21:17:34 +01005769 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005770 pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01005771 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005772 } else if (dmar_map_gfx) {
5773 /* we have to ensure the gfx device is idle before we flush */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005774 pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005775 intel_iommu_strict = 1;
5776 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01005777}
5778DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
5779DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
5780DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
5781DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
5782
David Woodhousee0fc7e02009-09-30 09:12:17 -07005783/* On Tylersburg chipsets, some BIOSes have been known to enable the
5784 ISOCH DMAR unit for the Azalia sound device, but not give it any
5785 TLB entries, which causes it to deadlock. Check for that. We do
5786 this in a function called from init_dmars(), instead of in a PCI
5787 quirk, because we don't want to print the obnoxious "BIOS broken"
5788 message if VT-d is actually disabled.
5789*/
5790static void __init check_tylersburg_isoch(void)
5791{
5792 struct pci_dev *pdev;
5793 uint32_t vtisochctrl;
5794
5795 /* If there's no Azalia in the system anyway, forget it. */
5796 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
5797 if (!pdev)
5798 return;
5799 pci_dev_put(pdev);
5800
5801 /* System Management Registers. Might be hidden, in which case
5802 we can't do the sanity check. But that's OK, because the
5803 known-broken BIOSes _don't_ actually hide it, so far. */
5804 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
5805 if (!pdev)
5806 return;
5807
5808 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
5809 pci_dev_put(pdev);
5810 return;
5811 }
5812
5813 pci_dev_put(pdev);
5814
5815 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
5816 if (vtisochctrl & 1)
5817 return;
5818
5819 /* Drop all bits other than the number of TLB entries */
5820 vtisochctrl &= 0x1c;
5821
5822 /* If we have the recommended number of TLB entries (16), fine. */
5823 if (vtisochctrl == 0x10)
5824 return;
5825
5826 /* Zero TLB entries? You get to ride the short bus to school. */
5827 if (!vtisochctrl) {
5828 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5829 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5830 dmi_get_system_info(DMI_BIOS_VENDOR),
5831 dmi_get_system_info(DMI_BIOS_VERSION),
5832 dmi_get_system_info(DMI_PRODUCT_VERSION));
5833 iommu_identity_mapping |= IDENTMAP_AZALIA;
5834 return;
5835 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005836
5837 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005838 vtisochctrl);
5839}