blob: 28a998afaf74a50294afea71a0f25354e8f20aed [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
Joerg Roedel28ccce02015-07-21 14:45:31 +0200305/*
306 * Domain represents a virtual machine, more than one devices
Weidong Han1ce28fe2008-12-08 16:35:39 +0800307 * across iommus may be owned in one domain, e.g. kvm guest.
308 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800309#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800310
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700311/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800312#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700313
Joerg Roedel29a27712015-07-21 17:17:12 +0200314#define for_each_domain_iommu(idx, domain) \
315 for (idx = 0; idx < g_num_of_iommus; idx++) \
316 if (domain->iommu_refcnt[idx])
317
Jiang Liub94e4112014-02-19 14:07:25 +0800318struct dmar_rmrr_unit {
319 struct list_head list; /* list of rmrr units */
320 struct acpi_dmar_header *hdr; /* ACPI header */
321 u64 base_address; /* reserved base address*/
322 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000323 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800324 int devices_cnt; /* target device count */
Eric Auger0659b8d2017-01-19 20:57:53 +0000325 struct iommu_resv_region *resv; /* reserved region handle */
Jiang Liub94e4112014-02-19 14:07:25 +0800326};
327
328struct dmar_atsr_unit {
329 struct list_head list; /* list of ATSR units */
330 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000331 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800332 int devices_cnt; /* target device count */
333 u8 include_all:1; /* include all ports */
334};
335
336static LIST_HEAD(dmar_atsr_units);
337static LIST_HEAD(dmar_rmrr_units);
338
339#define for_each_rmrr_units(rmrr) \
340 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
341
mark gross5e0d2a62008-03-04 15:22:08 -0800342/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800343static int g_num_of_iommus;
344
Jiang Liu92d03cc2014-02-19 14:07:28 +0800345static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700346static void domain_remove_dev_info(struct dmar_domain *domain);
Bjorn Helgaas71753232019-02-08 16:06:15 -0600347static void dmar_remove_one_dev_info(struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200348static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Joerg Roedel2452d9d2015-07-23 16:20:14 +0200349static void domain_context_clear(struct intel_iommu *iommu,
350 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800351static int domain_detach_iommu(struct dmar_domain *domain,
352 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700353
Suresh Siddhad3f13812011-08-23 17:05:25 -0700354#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800355int dmar_disabled = 0;
356#else
357int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700358#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800359
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200360int intel_iommu_enabled = 0;
361EXPORT_SYMBOL_GPL(intel_iommu_enabled);
362
David Woodhouse2d9e6672010-06-15 10:57:57 +0100363static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700364static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800365static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100366static int intel_iommu_superpage = 1;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800367static int intel_iommu_sm;
David Woodhouseae853dd2015-09-09 11:58:59 +0100368static int iommu_identity_mapping;
David Woodhousec83b2f22015-06-12 10:15:49 +0100369
David Woodhouseae853dd2015-09-09 11:58:59 +0100370#define IDENTMAP_ALL 1
371#define IDENTMAP_GFX 2
372#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100373
Lu Baolu765b6a92018-12-10 09:58:55 +0800374#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))
375#define pasid_supported(iommu) (sm_supported(iommu) && \
376 ecap_pasid((iommu)->ecap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700377
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))
382static DEFINE_SPINLOCK(device_domain_lock);
383static LIST_HEAD(device_domain_list);
384
Lu Baolu85319dc2018-07-14 15:46:58 +0800385/*
386 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800387 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800388 */
389int for_each_device_domain(int (*fn)(struct device_domain_info *info,
390 void *data), void *data)
391{
392 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800393 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800394 struct device_domain_info *info;
395
Lu Baolu0bbeb012018-12-10 09:58:56 +0800396 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800397 list_for_each_entry(info, &device_domain_list, global) {
398 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800399 if (ret) {
400 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800401 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800402 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800403 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800404 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800405
406 return 0;
407}
408
Joerg Roedelb0119e82017-02-01 13:23:08 +0100409const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100410
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200411static bool translation_pre_enabled(struct intel_iommu *iommu)
412{
413 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
414}
415
Joerg Roedel091d42e2015-06-12 11:56:10 +0200416static void clear_translation_pre_enabled(struct intel_iommu *iommu)
417{
418 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
419}
420
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200421static void init_translation_status(struct intel_iommu *iommu)
422{
423 u32 gsts;
424
425 gsts = readl(iommu->reg + DMAR_GSTS_REG);
426 if (gsts & DMA_GSTS_TES)
427 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
428}
429
Joerg Roedel00a77de2015-03-26 13:43:08 +0100430/* Convert generic 'struct iommu_domain to private struct dmar_domain */
431static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
432{
433 return container_of(dom, struct dmar_domain, domain);
434}
435
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700436static int __init intel_iommu_setup(char *str)
437{
438 if (!str)
439 return -EINVAL;
440 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800441 if (!strncmp(str, "on", 2)) {
442 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200443 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800444 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700445 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800446 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200447 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700448 } else if (!strncmp(str, "igfx_off", 8)) {
449 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200450 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700451 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200452 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700453 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800454 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200455 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800456 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100457 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200458 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100459 intel_iommu_superpage = 0;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800460 } else if (!strncmp(str, "sm_on", 5)) {
461 pr_info("Intel-IOMMU: scalable mode supported\n");
462 intel_iommu_sm = 1;
Shaohua Libfd20f12017-04-26 09:18:35 -0700463 } else if (!strncmp(str, "tboot_noforce", 13)) {
464 printk(KERN_INFO
465 "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
466 intel_iommu_tboot_noforce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700467 }
468
469 str += strcspn(str, ",");
470 while (*str == ',')
471 str++;
472 }
473 return 0;
474}
475__setup("intel_iommu=", intel_iommu_setup);
476
477static struct kmem_cache *iommu_domain_cache;
478static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700479
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200480static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
481{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200482 struct dmar_domain **domains;
483 int idx = did >> 8;
484
485 domains = iommu->domains[idx];
486 if (!domains)
487 return NULL;
488
489 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200490}
491
492static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
493 struct dmar_domain *domain)
494{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200495 struct dmar_domain **domains;
496 int idx = did >> 8;
497
498 if (!iommu->domains[idx]) {
499 size_t size = 256 * sizeof(struct dmar_domain *);
500 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
501 }
502
503 domains = iommu->domains[idx];
504 if (WARN_ON(!domains))
505 return;
506 else
507 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200508}
509
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800510void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700511{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700512 struct page *page;
513 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700514
Suresh Siddha4c923d42009-10-02 11:01:24 -0700515 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
516 if (page)
517 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700518 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700519}
520
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800521void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700522{
523 free_page((unsigned long)vaddr);
524}
525
526static inline void *alloc_domain_mem(void)
527{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900528 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700529}
530
Kay, Allen M38717942008-09-09 18:37:29 +0300531static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700532{
533 kmem_cache_free(iommu_domain_cache, vaddr);
534}
535
536static inline void * alloc_devinfo_mem(void)
537{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900538 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700539}
540
541static inline void free_devinfo_mem(void *vaddr)
542{
543 kmem_cache_free(iommu_devinfo_cache, vaddr);
544}
545
Jiang Liuab8dfe22014-07-11 14:19:27 +0800546static inline int domain_type_is_vm(struct dmar_domain *domain)
547{
548 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
549}
550
Joerg Roedel28ccce02015-07-21 14:45:31 +0200551static inline int domain_type_is_si(struct dmar_domain *domain)
552{
553 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
554}
555
Jiang Liuab8dfe22014-07-11 14:19:27 +0800556static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
557{
558 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
559 DOMAIN_FLAG_STATIC_IDENTITY);
560}
Weidong Han1b573682008-12-08 15:34:06 +0800561
Jiang Liu162d1b12014-07-11 14:19:35 +0800562static inline int domain_pfn_supported(struct dmar_domain *domain,
563 unsigned long pfn)
564{
565 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
566
567 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
568}
569
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700570static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800571{
572 unsigned long sagaw;
573 int agaw = -1;
574
575 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700576 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800577 agaw >= 0; agaw--) {
578 if (test_bit(agaw, &sagaw))
579 break;
580 }
581
582 return agaw;
583}
584
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700585/*
586 * Calculate max SAGAW for each iommu.
587 */
588int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
589{
590 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
591}
592
593/*
594 * calculate agaw for each iommu.
595 * "SAGAW" may be different across iommus, use a default agaw, and
596 * get a supported less agaw for iommus that don't support the default agaw.
597 */
598int iommu_calculate_agaw(struct intel_iommu *iommu)
599{
600 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
601}
602
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700603/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800604struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800605{
606 int iommu_id;
607
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700608 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800609 BUG_ON(domain_type_is_vm_or_si(domain));
Joerg Roedel29a27712015-07-21 17:17:12 +0200610 for_each_domain_iommu(iommu_id, domain)
611 break;
612
Weidong Han8c11e792008-12-08 15:29:22 +0800613 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
614 return NULL;
615
616 return g_iommus[iommu_id];
617}
618
Weidong Han8e6040972008-12-08 15:49:06 +0800619static void domain_update_iommu_coherency(struct dmar_domain *domain)
620{
David Woodhoused0501962014-03-11 17:10:29 -0700621 struct dmar_drhd_unit *drhd;
622 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100623 bool found = false;
624 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800625
David Woodhoused0501962014-03-11 17:10:29 -0700626 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800627
Joerg Roedel29a27712015-07-21 17:17:12 +0200628 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100629 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800630 if (!ecap_coherent(g_iommus[i]->ecap)) {
631 domain->iommu_coherency = 0;
632 break;
633 }
Weidong Han8e6040972008-12-08 15:49:06 +0800634 }
David Woodhoused0501962014-03-11 17:10:29 -0700635 if (found)
636 return;
637
638 /* No hardware attached; use lowest common denominator */
639 rcu_read_lock();
640 for_each_active_iommu(iommu, drhd) {
641 if (!ecap_coherent(iommu->ecap)) {
642 domain->iommu_coherency = 0;
643 break;
644 }
645 }
646 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800647}
648
Jiang Liu161f6932014-07-11 14:19:37 +0800649static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100650{
Allen Kay8140a952011-10-14 12:32:17 -0700651 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800652 struct intel_iommu *iommu;
653 int ret = 1;
654
655 rcu_read_lock();
656 for_each_active_iommu(iommu, drhd) {
657 if (iommu != skip) {
658 if (!ecap_sc_support(iommu->ecap)) {
659 ret = 0;
660 break;
661 }
662 }
663 }
664 rcu_read_unlock();
665
666 return ret;
667}
668
669static int domain_update_iommu_superpage(struct intel_iommu *skip)
670{
671 struct dmar_drhd_unit *drhd;
672 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700673 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100674
675 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800676 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100677 }
678
Allen Kay8140a952011-10-14 12:32:17 -0700679 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800680 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700681 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800682 if (iommu != skip) {
683 mask &= cap_super_page_val(iommu->cap);
684 if (!mask)
685 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100686 }
687 }
Jiang Liu0e242612014-02-19 14:07:34 +0800688 rcu_read_unlock();
689
Jiang Liu161f6932014-07-11 14:19:37 +0800690 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100691}
692
Sheng Yang58c610b2009-03-18 15:33:05 +0800693/* Some capabilities may be different across iommus */
694static void domain_update_iommu_cap(struct dmar_domain *domain)
695{
696 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800697 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
698 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800699}
700
Sohil Mehta26b86092018-09-11 17:11:36 -0700701struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
702 u8 devfn, int alloc)
David Woodhouse03ecc322015-02-13 14:35:21 +0000703{
704 struct root_entry *root = &iommu->root_entry[bus];
705 struct context_entry *context;
706 u64 *entry;
707
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200708 entry = &root->lo;
Lu Baolu765b6a92018-12-10 09:58:55 +0800709 if (sm_supported(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000710 if (devfn >= 0x80) {
711 devfn -= 0x80;
712 entry = &root->hi;
713 }
714 devfn *= 2;
715 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000716 if (*entry & 1)
717 context = phys_to_virt(*entry & VTD_PAGE_MASK);
718 else {
719 unsigned long phy_addr;
720 if (!alloc)
721 return NULL;
722
723 context = alloc_pgtable_page(iommu->node);
724 if (!context)
725 return NULL;
726
727 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
728 phy_addr = virt_to_phys((void *)context);
729 *entry = phy_addr | 1;
730 __iommu_flush_cache(iommu, entry, sizeof(*entry));
731 }
732 return &context[devfn];
733}
734
David Woodhouse4ed6a542015-05-11 14:59:20 +0100735static int iommu_dummy(struct device *dev)
736{
737 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
738}
739
David Woodhouse156baca2014-03-09 14:00:57 -0700740static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800741{
742 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800743 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700744 struct device *tmp;
745 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800746 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800747 int i;
748
David Woodhouse4ed6a542015-05-11 14:59:20 +0100749 if (iommu_dummy(dev))
750 return NULL;
751
David Woodhouse156baca2014-03-09 14:00:57 -0700752 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700753 struct pci_dev *pf_pdev;
754
David Woodhouse156baca2014-03-09 14:00:57 -0700755 pdev = to_pci_dev(dev);
Jon Derrick5823e332017-08-30 15:05:59 -0600756
757#ifdef CONFIG_X86
758 /* VMD child devices currently cannot be handled individually */
759 if (is_vmd(pdev->bus))
760 return NULL;
761#endif
762
Ashok Raj1c387182016-10-21 15:32:05 -0700763 /* VFs aren't listed in scope tables; we need to look up
764 * the PF instead to find the IOMMU. */
765 pf_pdev = pci_physfn(pdev);
766 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700767 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100768 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700769 dev = &ACPI_COMPANION(dev)->dev;
770
Jiang Liu0e242612014-02-19 14:07:34 +0800771 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800772 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700773 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100774 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800775
Jiang Liub683b232014-02-19 14:07:32 +0800776 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700777 drhd->devices_cnt, i, tmp) {
778 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700779 /* For a VF use its original BDF# not that of the PF
780 * which we used for the IOMMU lookup. Strictly speaking
781 * we could do this for all PCI devices; we only need to
782 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100783 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700784 goto got_pdev;
785
David Woodhouse156baca2014-03-09 14:00:57 -0700786 *bus = drhd->devices[i].bus;
787 *devfn = drhd->devices[i].devfn;
788 goto out;
789 }
790
791 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000792 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700793
794 ptmp = to_pci_dev(tmp);
795 if (ptmp->subordinate &&
796 ptmp->subordinate->number <= pdev->bus->number &&
797 ptmp->subordinate->busn_res.end >= pdev->bus->number)
798 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100799 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800800
David Woodhouse156baca2014-03-09 14:00:57 -0700801 if (pdev && drhd->include_all) {
802 got_pdev:
803 *bus = pdev->bus->number;
804 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800805 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700806 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800807 }
Jiang Liub683b232014-02-19 14:07:32 +0800808 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700809 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800810 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800811
Jiang Liub683b232014-02-19 14:07:32 +0800812 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800813}
814
Weidong Han5331fe62008-12-08 23:00:00 +0800815static void domain_flush_cache(struct dmar_domain *domain,
816 void *addr, int size)
817{
818 if (!domain->iommu_coherency)
819 clflush_cache_range(addr, size);
820}
821
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700822static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
823{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700824 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000825 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700826 unsigned long flags;
827
828 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000829 context = iommu_context_addr(iommu, bus, devfn, 0);
830 if (context)
831 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700832 spin_unlock_irqrestore(&iommu->lock, flags);
833 return ret;
834}
835
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700836static void free_context_table(struct intel_iommu *iommu)
837{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700838 int i;
839 unsigned long flags;
840 struct context_entry *context;
841
842 spin_lock_irqsave(&iommu->lock, flags);
843 if (!iommu->root_entry) {
844 goto out;
845 }
846 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000847 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700848 if (context)
849 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000850
Lu Baolu765b6a92018-12-10 09:58:55 +0800851 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000852 continue;
853
854 context = iommu_context_addr(iommu, i, 0x80, 0);
855 if (context)
856 free_pgtable_page(context);
857
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700858 }
859 free_pgtable_page(iommu->root_entry);
860 iommu->root_entry = NULL;
861out:
862 spin_unlock_irqrestore(&iommu->lock, flags);
863}
864
David Woodhouseb026fd22009-06-28 10:37:25 +0100865static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000866 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700867{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600868 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700869 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700870 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700871
872 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200873
Jiang Liu162d1b12014-07-11 14:19:35 +0800874 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200875 /* Address beyond IOMMU's addressing capabilities. */
876 return NULL;
877
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700878 parent = domain->pgd;
879
David Woodhouse5cf0a762014-03-19 16:07:49 +0000880 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700881 void *tmp_page;
882
David Woodhouseb026fd22009-06-28 10:37:25 +0100883 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700884 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000885 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100886 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000887 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700888 break;
889
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000890 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100891 uint64_t pteval;
892
Suresh Siddha4c923d42009-10-02 11:01:24 -0700893 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700894
David Woodhouse206a73c2009-07-01 19:30:28 +0100895 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700896 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100897
David Woodhousec85994e2009-07-01 19:21:24 +0100898 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400899 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 +0800900 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100901 /* Someone else set it while we were thinking; use theirs. */
902 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800903 else
David Woodhousec85994e2009-07-01 19:21:24 +0100904 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700905 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000906 if (level == 1)
907 break;
908
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000909 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700910 level--;
911 }
912
David Woodhouse5cf0a762014-03-19 16:07:49 +0000913 if (!*target_level)
914 *target_level = level;
915
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700916 return pte;
917}
918
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100919
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700920/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100921static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
922 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100923 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700924{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600925 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700926 int total = agaw_to_level(domain->agaw);
927 int offset;
928
929 parent = domain->pgd;
930 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100931 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700932 pte = &parent[offset];
933 if (level == total)
934 return pte;
935
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100936 if (!dma_pte_present(pte)) {
937 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700938 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100939 }
940
Yijing Wange16922a2014-05-20 20:37:51 +0800941 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100942 *large_page = total;
943 return pte;
944 }
945
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000946 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700947 total--;
948 }
949 return NULL;
950}
951
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700952/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000953static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +0100954 unsigned long start_pfn,
955 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700956{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600957 unsigned int large_page;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100958 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700959
Jiang Liu162d1b12014-07-11 14:19:35 +0800960 BUG_ON(!domain_pfn_supported(domain, start_pfn));
961 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700962 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100963
David Woodhouse04b18e62009-06-27 19:15:01 +0100964 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700965 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100966 large_page = 1;
967 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100968 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100969 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100970 continue;
971 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100972 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100973 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100974 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100975 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100976 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
977
David Woodhouse310a5ab2009-06-28 18:52:20 +0100978 domain_flush_cache(domain, first_pte,
979 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700980
981 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700982}
983
Alex Williamson3269ee02013-06-15 10:27:19 -0600984static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -0700985 int retain_level, struct dma_pte *pte,
986 unsigned long pfn, unsigned long start_pfn,
987 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -0600988{
989 pfn = max(start_pfn, pfn);
990 pte = &pte[pfn_level_offset(pfn, level)];
991
992 do {
993 unsigned long level_pfn;
994 struct dma_pte *level_pte;
995
996 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
997 goto next;
998
David Dillowf7116e12017-01-30 19:11:11 -0800999 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -06001000 level_pte = phys_to_virt(dma_pte_addr(pte));
1001
David Dillowbc24c572017-06-28 19:42:23 -07001002 if (level > 2) {
1003 dma_pte_free_level(domain, level - 1, retain_level,
1004 level_pte, level_pfn, start_pfn,
1005 last_pfn);
1006 }
Alex Williamson3269ee02013-06-15 10:27:19 -06001007
David Dillowbc24c572017-06-28 19:42:23 -07001008 /*
1009 * Free the page table if we're below the level we want to
1010 * retain and the range covers the entire table.
1011 */
1012 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001013 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001014 dma_clear_pte(pte);
1015 domain_flush_cache(domain, pte, sizeof(*pte));
1016 free_pgtable_page(level_pte);
1017 }
1018next:
1019 pfn += level_size(level);
1020 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1021}
1022
David Dillowbc24c572017-06-28 19:42:23 -07001023/*
1024 * clear last level (leaf) ptes and free page table pages below the
1025 * level we wish to keep intact.
1026 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001027static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001028 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001029 unsigned long last_pfn,
1030 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001031{
Jiang Liu162d1b12014-07-11 14:19:35 +08001032 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1033 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001034 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001035
Jiang Liud41a4ad2014-07-11 14:19:34 +08001036 dma_pte_clear_range(domain, start_pfn, last_pfn);
1037
David Woodhousef3a0a522009-06-30 03:40:07 +01001038 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001039 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001040 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001041
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001042 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001043 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001044 free_pgtable_page(domain->pgd);
1045 domain->pgd = NULL;
1046 }
1047}
1048
David Woodhouseea8ea462014-03-05 17:09:32 +00001049/* When a page at a given level is being unlinked from its parent, we don't
1050 need to *modify* it at all. All we need to do is make a list of all the
1051 pages which can be freed just as soon as we've flushed the IOTLB and we
1052 know the hardware page-walk will no longer touch them.
1053 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1054 be freed. */
1055static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1056 int level, struct dma_pte *pte,
1057 struct page *freelist)
1058{
1059 struct page *pg;
1060
1061 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1062 pg->freelist = freelist;
1063 freelist = pg;
1064
1065 if (level == 1)
1066 return freelist;
1067
Jiang Liuadeb2592014-04-09 10:20:39 +08001068 pte = page_address(pg);
1069 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001070 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1071 freelist = dma_pte_list_pagetables(domain, level - 1,
1072 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001073 pte++;
1074 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001075
1076 return freelist;
1077}
1078
1079static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1080 struct dma_pte *pte, unsigned long pfn,
1081 unsigned long start_pfn,
1082 unsigned long last_pfn,
1083 struct page *freelist)
1084{
1085 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1086
1087 pfn = max(start_pfn, pfn);
1088 pte = &pte[pfn_level_offset(pfn, level)];
1089
1090 do {
1091 unsigned long level_pfn;
1092
1093 if (!dma_pte_present(pte))
1094 goto next;
1095
1096 level_pfn = pfn & level_mask(level);
1097
1098 /* If range covers entire pagetable, free it */
1099 if (start_pfn <= level_pfn &&
1100 last_pfn >= level_pfn + level_size(level) - 1) {
1101 /* These suborbinate page tables are going away entirely. Don't
1102 bother to clear them; we're just going to *free* them. */
1103 if (level > 1 && !dma_pte_superpage(pte))
1104 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1105
1106 dma_clear_pte(pte);
1107 if (!first_pte)
1108 first_pte = pte;
1109 last_pte = pte;
1110 } else if (level > 1) {
1111 /* Recurse down into a level that isn't *entirely* obsolete */
1112 freelist = dma_pte_clear_level(domain, level - 1,
1113 phys_to_virt(dma_pte_addr(pte)),
1114 level_pfn, start_pfn, last_pfn,
1115 freelist);
1116 }
1117next:
1118 pfn += level_size(level);
1119 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1120
1121 if (first_pte)
1122 domain_flush_cache(domain, first_pte,
1123 (void *)++last_pte - (void *)first_pte);
1124
1125 return freelist;
1126}
1127
1128/* We can't just free the pages because the IOMMU may still be walking
1129 the page tables, and may have cached the intermediate levels. The
1130 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001131static struct page *domain_unmap(struct dmar_domain *domain,
1132 unsigned long start_pfn,
1133 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001134{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001135 struct page *freelist;
David Woodhouseea8ea462014-03-05 17:09:32 +00001136
Jiang Liu162d1b12014-07-11 14:19:35 +08001137 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1138 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001139 BUG_ON(start_pfn > last_pfn);
1140
1141 /* we don't need lock here; nobody else touches the iova range */
1142 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1143 domain->pgd, 0, start_pfn, last_pfn, NULL);
1144
1145 /* free pgd */
1146 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1147 struct page *pgd_page = virt_to_page(domain->pgd);
1148 pgd_page->freelist = freelist;
1149 freelist = pgd_page;
1150
1151 domain->pgd = NULL;
1152 }
1153
1154 return freelist;
1155}
1156
Joerg Roedelb6904202015-08-13 11:32:18 +02001157static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001158{
1159 struct page *pg;
1160
1161 while ((pg = freelist)) {
1162 freelist = pg->freelist;
1163 free_pgtable_page(page_address(pg));
1164 }
1165}
1166
Joerg Roedel13cf0172017-08-11 11:40:10 +02001167static void iova_entry_free(unsigned long data)
1168{
1169 struct page *freelist = (struct page *)data;
1170
1171 dma_free_pagelist(freelist);
1172}
1173
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001174/* iommu handling */
1175static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1176{
1177 struct root_entry *root;
1178 unsigned long flags;
1179
Suresh Siddha4c923d42009-10-02 11:01:24 -07001180 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001181 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001182 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001183 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001184 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001185 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001186
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001187 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001188
1189 spin_lock_irqsave(&iommu->lock, flags);
1190 iommu->root_entry = root;
1191 spin_unlock_irqrestore(&iommu->lock, flags);
1192
1193 return 0;
1194}
1195
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001196static void iommu_set_root_entry(struct intel_iommu *iommu)
1197{
David Woodhouse03ecc322015-02-13 14:35:21 +00001198 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001199 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001200 unsigned long flag;
1201
David Woodhouse03ecc322015-02-13 14:35:21 +00001202 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001203 if (sm_supported(iommu))
1204 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001205
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001206 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001207 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001208
David Woodhousec416daa2009-05-10 20:30:58 +01001209 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001210
1211 /* Make sure hardware complete it */
1212 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001213 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001214
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001215 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001216}
1217
Lu Baolu6f7db752018-12-10 09:59:00 +08001218void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001219{
1220 u32 val;
1221 unsigned long flag;
1222
David Woodhouse9af88142009-02-13 23:18:03 +00001223 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001224 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001225
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001226 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001227 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001228
1229 /* Make sure hardware complete it */
1230 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001231 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001232
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001233 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001234}
1235
1236/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001237static void __iommu_flush_context(struct intel_iommu *iommu,
1238 u16 did, u16 source_id, u8 function_mask,
1239 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001240{
1241 u64 val = 0;
1242 unsigned long flag;
1243
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001244 switch (type) {
1245 case DMA_CCMD_GLOBAL_INVL:
1246 val = DMA_CCMD_GLOBAL_INVL;
1247 break;
1248 case DMA_CCMD_DOMAIN_INVL:
1249 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1250 break;
1251 case DMA_CCMD_DEVICE_INVL:
1252 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1253 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1254 break;
1255 default:
1256 BUG();
1257 }
1258 val |= DMA_CCMD_ICC;
1259
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001260 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001261 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1262
1263 /* Make sure hardware complete it */
1264 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1265 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1266
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001267 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001268}
1269
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001270/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001271static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1272 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001273{
1274 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1275 u64 val = 0, val_iva = 0;
1276 unsigned long flag;
1277
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001278 switch (type) {
1279 case DMA_TLB_GLOBAL_FLUSH:
1280 /* global flush doesn't need set IVA_REG */
1281 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1282 break;
1283 case DMA_TLB_DSI_FLUSH:
1284 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1285 break;
1286 case DMA_TLB_PSI_FLUSH:
1287 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001288 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001289 val_iva = size_order | addr;
1290 break;
1291 default:
1292 BUG();
1293 }
1294 /* Note: set drain read/write */
1295#if 0
1296 /*
1297 * This is probably to be super secure.. Looks like we can
1298 * ignore it without any impact.
1299 */
1300 if (cap_read_drain(iommu->cap))
1301 val |= DMA_TLB_READ_DRAIN;
1302#endif
1303 if (cap_write_drain(iommu->cap))
1304 val |= DMA_TLB_WRITE_DRAIN;
1305
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001306 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001307 /* Note: Only uses first TLB reg currently */
1308 if (val_iva)
1309 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1310 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1311
1312 /* Make sure hardware complete it */
1313 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1314 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1315
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001316 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001317
1318 /* check IOTLB invalidation granularity */
1319 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001320 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001321 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001322 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001323 (unsigned long long)DMA_TLB_IIRG(type),
1324 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001325}
1326
David Woodhouse64ae8922014-03-09 12:52:30 -07001327static struct device_domain_info *
1328iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1329 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001330{
Yu Zhao93a23a72009-05-18 13:51:37 +08001331 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001332
Joerg Roedel55d94042015-07-22 16:50:40 +02001333 assert_spin_locked(&device_domain_lock);
1334
Yu Zhao93a23a72009-05-18 13:51:37 +08001335 if (!iommu->qi)
1336 return NULL;
1337
Yu Zhao93a23a72009-05-18 13:51:37 +08001338 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001339 if (info->iommu == iommu && info->bus == bus &&
1340 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001341 if (info->ats_supported && info->dev)
1342 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001343 break;
1344 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001345
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001346 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001347}
1348
Omer Peleg0824c592016-04-20 19:03:35 +03001349static void domain_update_iotlb(struct dmar_domain *domain)
1350{
1351 struct device_domain_info *info;
1352 bool has_iotlb_device = false;
1353
1354 assert_spin_locked(&device_domain_lock);
1355
1356 list_for_each_entry(info, &domain->devices, link) {
1357 struct pci_dev *pdev;
1358
1359 if (!info->dev || !dev_is_pci(info->dev))
1360 continue;
1361
1362 pdev = to_pci_dev(info->dev);
1363 if (pdev->ats_enabled) {
1364 has_iotlb_device = true;
1365 break;
1366 }
1367 }
1368
1369 domain->has_iotlb_device = has_iotlb_device;
1370}
1371
Yu Zhao93a23a72009-05-18 13:51:37 +08001372static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1373{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001374 struct pci_dev *pdev;
1375
Omer Peleg0824c592016-04-20 19:03:35 +03001376 assert_spin_locked(&device_domain_lock);
1377
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001378 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001379 return;
1380
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001381 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001382 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1383 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1384 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1385 * reserved, which should be set to 0.
1386 */
1387 if (!ecap_dit(info->iommu->ecap))
1388 info->pfsid = 0;
1389 else {
1390 struct pci_dev *pf_pdev;
1391
1392 /* pdev will be returned if device is not a vf */
1393 pf_pdev = pci_physfn(pdev);
1394 info->pfsid = PCI_DEVID(pf_pdev->bus->number, pf_pdev->devfn);
1395 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001396
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001397#ifdef CONFIG_INTEL_IOMMU_SVM
1398 /* The PCIe spec, in its wisdom, declares that the behaviour of
1399 the device if you enable PASID support after ATS support is
1400 undefined. So always enable PASID support on devices which
1401 have it, even if we can't yet know if we're ever going to
1402 use it. */
1403 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1404 info->pasid_enabled = 1;
1405
Kuppuswamy Sathyanarayanan1b84778a2019-02-19 11:04:52 -08001406 if (info->pri_supported &&
1407 (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
1408 !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001409 info->pri_enabled = 1;
1410#endif
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001411 if (!pdev->untrusted && info->ats_supported &&
Kuppuswamy Sathyanarayanan61363c12019-02-19 11:06:10 -08001412 pci_ats_page_aligned(pdev) &&
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001413 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001414 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001415 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001416 info->ats_qdep = pci_ats_queue_depth(pdev);
1417 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001418}
1419
1420static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1421{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001422 struct pci_dev *pdev;
1423
Omer Peleg0824c592016-04-20 19:03:35 +03001424 assert_spin_locked(&device_domain_lock);
1425
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001426 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001427 return;
1428
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001429 pdev = to_pci_dev(info->dev);
1430
1431 if (info->ats_enabled) {
1432 pci_disable_ats(pdev);
1433 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001434 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001435 }
1436#ifdef CONFIG_INTEL_IOMMU_SVM
1437 if (info->pri_enabled) {
1438 pci_disable_pri(pdev);
1439 info->pri_enabled = 0;
1440 }
1441 if (info->pasid_enabled) {
1442 pci_disable_pasid(pdev);
1443 info->pasid_enabled = 0;
1444 }
1445#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001446}
1447
1448static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1449 u64 addr, unsigned mask)
1450{
1451 u16 sid, qdep;
1452 unsigned long flags;
1453 struct device_domain_info *info;
1454
Omer Peleg0824c592016-04-20 19:03:35 +03001455 if (!domain->has_iotlb_device)
1456 return;
1457
Yu Zhao93a23a72009-05-18 13:51:37 +08001458 spin_lock_irqsave(&device_domain_lock, flags);
1459 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001460 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001461 continue;
1462
1463 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001464 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001465 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1466 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001467 }
1468 spin_unlock_irqrestore(&device_domain_lock, flags);
1469}
1470
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001471static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1472 struct dmar_domain *domain,
1473 unsigned long pfn, unsigned int pages,
1474 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001475{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001476 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001477 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001478 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001479
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001480 BUG_ON(pages == 0);
1481
David Woodhouseea8ea462014-03-05 17:09:32 +00001482 if (ih)
1483 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001484 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001485 * Fallback to domain selective flush if no PSI support or the size is
1486 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001487 * PSI requires page size to be 2 ^ x, and the base address is naturally
1488 * aligned to the size
1489 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001490 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1491 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001492 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001493 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001494 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001495 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001496
1497 /*
Nadav Amit82653632010-04-01 13:24:40 +03001498 * In caching mode, changes of pages from non-present to present require
1499 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001500 */
Nadav Amit82653632010-04-01 13:24:40 +03001501 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001502 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001503}
1504
Peter Xueed91a02018-05-04 10:34:52 +08001505/* Notification for newly created mappings */
1506static inline void __mapping_notify_one(struct intel_iommu *iommu,
1507 struct dmar_domain *domain,
1508 unsigned long pfn, unsigned int pages)
1509{
1510 /* It's a non-present to present mapping. Only flush if caching mode */
1511 if (cap_caching_mode(iommu->cap))
1512 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1513 else
1514 iommu_flush_write_buffer(iommu);
1515}
1516
Joerg Roedel13cf0172017-08-11 11:40:10 +02001517static void iommu_flush_iova(struct iova_domain *iovad)
1518{
1519 struct dmar_domain *domain;
1520 int idx;
1521
1522 domain = container_of(iovad, struct dmar_domain, iovad);
1523
1524 for_each_domain_iommu(idx, domain) {
1525 struct intel_iommu *iommu = g_iommus[idx];
1526 u16 did = domain->iommu_did[iommu->seq_id];
1527
1528 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
1529
1530 if (!cap_caching_mode(iommu->cap))
1531 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1532 0, MAX_AGAW_PFN_WIDTH);
1533 }
1534}
1535
mark grossf8bab732008-02-08 04:18:38 -08001536static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1537{
1538 u32 pmen;
1539 unsigned long flags;
1540
Lu Baolu5bb71fc72019-03-20 09:58:33 +08001541 if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
1542 return;
1543
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001544 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001545 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1546 pmen &= ~DMA_PMEN_EPM;
1547 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1548
1549 /* wait for the protected region status bit to clear */
1550 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1551 readl, !(pmen & DMA_PMEN_PRS), pmen);
1552
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001553 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001554}
1555
Jiang Liu2a41cce2014-07-11 14:19:33 +08001556static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001557{
1558 u32 sts;
1559 unsigned long flags;
1560
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001561 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001562 iommu->gcmd |= DMA_GCMD_TE;
1563 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001564
1565 /* Make sure hardware complete it */
1566 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001567 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001568
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001569 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001570}
1571
Jiang Liu2a41cce2014-07-11 14:19:33 +08001572static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001573{
1574 u32 sts;
1575 unsigned long flag;
1576
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001577 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001578 iommu->gcmd &= ~DMA_GCMD_TE;
1579 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1580
1581 /* Make sure hardware complete it */
1582 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001583 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001584
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001585 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001586}
1587
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001588
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001589static int iommu_init_domains(struct intel_iommu *iommu)
1590{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001591 u32 ndomains, nlongs;
1592 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001593
1594 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001595 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001596 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001597 nlongs = BITS_TO_LONGS(ndomains);
1598
Donald Dutile94a91b502009-08-20 16:51:34 -04001599 spin_lock_init(&iommu->lock);
1600
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001601 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1602 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001603 pr_err("%s: Allocating domain id array failed\n",
1604 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001605 return -ENOMEM;
1606 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001607
Wei Yang86f004c2016-05-21 02:41:51 +00001608 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001609 iommu->domains = kzalloc(size, GFP_KERNEL);
1610
1611 if (iommu->domains) {
1612 size = 256 * sizeof(struct dmar_domain *);
1613 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1614 }
1615
1616 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001617 pr_err("%s: Allocating domain array failed\n",
1618 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001619 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001620 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001621 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001622 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001623 return -ENOMEM;
1624 }
1625
Joerg Roedel8bf47812015-07-21 10:41:21 +02001626
1627
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001628 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001629 * If Caching mode is set, then invalid translations are tagged
1630 * with domain-id 0, hence we need to pre-allocate it. We also
1631 * use domain-id 0 as a marker for non-allocated domain-id, so
1632 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001633 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001634 set_bit(0, iommu->domain_ids);
1635
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001636 /*
1637 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1638 * entry for first-level or pass-through translation modes should
1639 * be programmed with a domain id different from those used for
1640 * second-level or nested translation. We reserve a domain id for
1641 * this purpose.
1642 */
1643 if (sm_supported(iommu))
1644 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1645
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001646 return 0;
1647}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001648
Jiang Liuffebeb42014-11-09 22:48:02 +08001649static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001650{
Joerg Roedel29a27712015-07-21 17:17:12 +02001651 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001652 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001653
Joerg Roedel29a27712015-07-21 17:17:12 +02001654 if (!iommu->domains || !iommu->domain_ids)
1655 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001656
Joerg Roedelbea64032016-11-08 15:08:26 +01001657again:
Joerg Roedel55d94042015-07-22 16:50:40 +02001658 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001659 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
1660 struct dmar_domain *domain;
1661
1662 if (info->iommu != iommu)
1663 continue;
1664
1665 if (!info->dev || !info->domain)
1666 continue;
1667
1668 domain = info->domain;
1669
Joerg Roedelbea64032016-11-08 15:08:26 +01001670 __dmar_remove_one_dev_info(info);
Joerg Roedel29a27712015-07-21 17:17:12 +02001671
Joerg Roedelbea64032016-11-08 15:08:26 +01001672 if (!domain_type_is_vm_or_si(domain)) {
1673 /*
1674 * The domain_exit() function can't be called under
1675 * device_domain_lock, as it takes this lock itself.
1676 * So release the lock here and re-run the loop
1677 * afterwards.
1678 */
1679 spin_unlock_irqrestore(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001680 domain_exit(domain);
Joerg Roedelbea64032016-11-08 15:08:26 +01001681 goto again;
1682 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001683 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001684 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001685
1686 if (iommu->gcmd & DMA_GCMD_TE)
1687 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001688}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001689
Jiang Liuffebeb42014-11-09 22:48:02 +08001690static void free_dmar_iommu(struct intel_iommu *iommu)
1691{
1692 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001693 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001694 int i;
1695
1696 for (i = 0; i < elems; i++)
1697 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001698 kfree(iommu->domains);
1699 kfree(iommu->domain_ids);
1700 iommu->domains = NULL;
1701 iommu->domain_ids = NULL;
1702 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001703
Weidong Hand9630fe2008-12-08 11:06:32 +08001704 g_iommus[iommu->seq_id] = NULL;
1705
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001706 /* free context mapping */
1707 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001708
1709#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001710 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001711 if (ecap_prs(iommu->ecap))
1712 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001713 }
David Woodhouse8a94ade2015-03-24 14:54:56 +00001714#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001715}
1716
Jiang Liuab8dfe22014-07-11 14:19:27 +08001717static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001718{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001719 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001720
1721 domain = alloc_domain_mem();
1722 if (!domain)
1723 return NULL;
1724
Jiang Liuab8dfe22014-07-11 14:19:27 +08001725 memset(domain, 0, sizeof(*domain));
Anshuman Khandual98fa15f2019-03-05 15:42:58 -08001726 domain->nid = NUMA_NO_NODE;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001727 domain->flags = flags;
Omer Peleg0824c592016-04-20 19:03:35 +03001728 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001729 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001730
1731 return domain;
1732}
1733
Joerg Roedeld160aca2015-07-22 11:52:53 +02001734/* Must be called with iommu->lock */
1735static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001736 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001737{
Jiang Liu44bde612014-07-11 14:19:29 +08001738 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001739 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001740
Joerg Roedel55d94042015-07-22 16:50:40 +02001741 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001742 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001743
Joerg Roedel29a27712015-07-21 17:17:12 +02001744 domain->iommu_refcnt[iommu->seq_id] += 1;
1745 domain->iommu_count += 1;
1746 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001747 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001748 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1749
1750 if (num >= ndomains) {
1751 pr_err("%s: No free domain ids\n", iommu->name);
1752 domain->iommu_refcnt[iommu->seq_id] -= 1;
1753 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001754 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001755 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001756
Joerg Roedeld160aca2015-07-22 11:52:53 +02001757 set_bit(num, iommu->domain_ids);
1758 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001759
Joerg Roedeld160aca2015-07-22 11:52:53 +02001760 domain->iommu_did[iommu->seq_id] = num;
1761 domain->nid = iommu->node;
1762
Jiang Liufb170fb2014-07-11 14:19:28 +08001763 domain_update_iommu_cap(domain);
1764 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001765
Joerg Roedel55d94042015-07-22 16:50:40 +02001766 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001767}
1768
1769static int domain_detach_iommu(struct dmar_domain *domain,
1770 struct intel_iommu *iommu)
1771{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001772 int num, count;
Jiang Liufb170fb2014-07-11 14:19:28 +08001773
Joerg Roedel55d94042015-07-22 16:50:40 +02001774 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001775 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001776
Joerg Roedel29a27712015-07-21 17:17:12 +02001777 domain->iommu_refcnt[iommu->seq_id] -= 1;
1778 count = --domain->iommu_count;
1779 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001780 num = domain->iommu_did[iommu->seq_id];
1781 clear_bit(num, iommu->domain_ids);
1782 set_iommu_domain(iommu, num, NULL);
1783
Jiang Liufb170fb2014-07-11 14:19:28 +08001784 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001785 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001786 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001787
1788 return count;
1789}
1790
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001791static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001792static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001793
Joseph Cihula51a63e62011-03-21 11:04:24 -07001794static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001795{
1796 struct pci_dev *pdev = NULL;
1797 struct iova *iova;
1798 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001799
Zhen Leiaa3ac942017-09-21 16:52:45 +01001800 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001801
Mark Gross8a443df2008-03-04 14:59:31 -08001802 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1803 &reserved_rbtree_key);
1804
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001805 /* IOAPIC ranges shouldn't be accessed by DMA */
1806 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1807 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001808 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001809 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001810 return -ENODEV;
1811 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001812
1813 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1814 for_each_pci_dev(pdev) {
1815 struct resource *r;
1816
1817 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1818 r = &pdev->resource[i];
1819 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1820 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001821 iova = reserve_iova(&reserved_iova_list,
1822 IOVA_PFN(r->start),
1823 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001824 if (!iova) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06001825 pci_err(pdev, "Reserve iova for %pR failed\n", r);
Joseph Cihula51a63e62011-03-21 11:04:24 -07001826 return -ENODEV;
1827 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001828 }
1829 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001830 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001831}
1832
1833static void domain_reserve_special_ranges(struct dmar_domain *domain)
1834{
1835 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1836}
1837
1838static inline int guestwidth_to_adjustwidth(int gaw)
1839{
1840 int agaw;
1841 int r = (gaw - 12) % 9;
1842
1843 if (r == 0)
1844 agaw = gaw;
1845 else
1846 agaw = gaw + 9 - r;
1847 if (agaw > 64)
1848 agaw = 64;
1849 return agaw;
1850}
1851
Joerg Roedeldc534b22015-07-22 12:44:02 +02001852static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1853 int guest_width)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001854{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001855 int adjust_width, agaw;
1856 unsigned long sagaw;
Joerg Roedel13cf0172017-08-11 11:40:10 +02001857 int err;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001858
Zhen Leiaa3ac942017-09-21 16:52:45 +01001859 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001860
1861 err = init_iova_flush_queue(&domain->iovad,
1862 iommu_flush_iova, iova_entry_free);
1863 if (err)
1864 return err;
1865
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001866 domain_reserve_special_ranges(domain);
1867
1868 /* calculate AGAW */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001869 if (guest_width > cap_mgaw(iommu->cap))
1870 guest_width = cap_mgaw(iommu->cap);
1871 domain->gaw = guest_width;
1872 adjust_width = guestwidth_to_adjustwidth(guest_width);
1873 agaw = width_to_agaw(adjust_width);
1874 sagaw = cap_sagaw(iommu->cap);
1875 if (!test_bit(agaw, &sagaw)) {
1876 /* hardware doesn't support it, choose a bigger one */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001877 pr_debug("Hardware doesn't support agaw %d\n", agaw);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001878 agaw = find_next_bit(&sagaw, 5, agaw);
1879 if (agaw >= 5)
1880 return -ENODEV;
1881 }
1882 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001883
Weidong Han8e6040972008-12-08 15:49:06 +08001884 if (ecap_coherent(iommu->ecap))
1885 domain->iommu_coherency = 1;
1886 else
1887 domain->iommu_coherency = 0;
1888
Sheng Yang58c610b2009-03-18 15:33:05 +08001889 if (ecap_sc_support(iommu->ecap))
1890 domain->iommu_snooping = 1;
1891 else
1892 domain->iommu_snooping = 0;
1893
David Woodhouse214e39a2014-03-19 10:38:49 +00001894 if (intel_iommu_superpage)
1895 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1896 else
1897 domain->iommu_superpage = 0;
1898
Suresh Siddha4c923d42009-10-02 11:01:24 -07001899 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001900
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001901 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001902 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001903 if (!domain->pgd)
1904 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001905 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001906 return 0;
1907}
1908
1909static void domain_exit(struct dmar_domain *domain)
1910{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001911 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001912
Joerg Roedeld160aca2015-07-22 11:52:53 +02001913 /* Remove associated devices and clear attached or cached domains */
1914 rcu_read_lock();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001915 domain_remove_dev_info(domain);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001916 rcu_read_unlock();
Jiang Liu92d03cc2014-02-19 14:07:28 +08001917
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001918 /* destroy iovas */
1919 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001920
David Woodhouseea8ea462014-03-05 17:09:32 +00001921 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001922
David Woodhouseea8ea462014-03-05 17:09:32 +00001923 dma_free_pagelist(freelist);
1924
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001925 free_domain_mem(domain);
1926}
1927
Lu Baolu7373a8c2018-12-10 09:59:03 +08001928/*
1929 * Get the PASID directory size for scalable mode context entry.
1930 * Value of X in the PDTS field of a scalable mode context entry
1931 * indicates PASID directory with 2^(X + 7) entries.
1932 */
1933static inline unsigned long context_get_sm_pds(struct pasid_table *table)
1934{
1935 int pds, max_pde;
1936
1937 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
1938 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
1939 if (pds < 7)
1940 return 0;
1941
1942 return pds - 7;
1943}
1944
1945/*
1946 * Set the RID_PASID field of a scalable mode context entry. The
1947 * IOMMU hardware will use the PASID value set in this field for
1948 * DMA translations of DMA requests without PASID.
1949 */
1950static inline void
1951context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
1952{
1953 context->hi |= pasid & ((1 << 20) - 1);
1954 context->hi |= (1 << 20);
1955}
1956
1957/*
1958 * Set the DTE(Device-TLB Enable) field of a scalable mode context
1959 * entry.
1960 */
1961static inline void context_set_sm_dte(struct context_entry *context)
1962{
1963 context->lo |= (1 << 2);
1964}
1965
1966/*
1967 * Set the PRE(Page Request Enable) field of a scalable mode context
1968 * entry.
1969 */
1970static inline void context_set_sm_pre(struct context_entry *context)
1971{
1972 context->lo |= (1 << 4);
1973}
1974
1975/* Convert value to context PASID directory size field coding. */
1976#define context_pdts(pds) (((pds) & 0x7) << 9)
1977
David Woodhouse64ae8922014-03-09 12:52:30 -07001978static int domain_context_mapping_one(struct dmar_domain *domain,
1979 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08001980 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001981 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001982{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001983 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02001984 int translation = CONTEXT_TT_MULTI_LEVEL;
1985 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001986 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001987 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08001988 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02001989
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001990 WARN_ON(did == 0);
1991
Joerg Roedel28ccce02015-07-21 14:45:31 +02001992 if (hw_pass_through && domain_type_is_si(domain))
1993 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001994
1995 pr_debug("Set context mapping for %02x:%02x.%d\n",
1996 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001997
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001998 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08001999
Joerg Roedel55d94042015-07-22 16:50:40 +02002000 spin_lock_irqsave(&device_domain_lock, flags);
2001 spin_lock(&iommu->lock);
2002
2003 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00002004 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002005 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02002006 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002007
Joerg Roedel55d94042015-07-22 16:50:40 +02002008 ret = 0;
2009 if (context_present(context))
2010 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002011
Xunlei Pangaec0e862016-12-05 20:09:07 +08002012 /*
2013 * For kdump cases, old valid entries may be cached due to the
2014 * in-flight DMA and copied pgtable, but there is no unmapping
2015 * behaviour for them, thus we need an explicit cache flush for
2016 * the newly-mapped device. For kdump, at this point, the device
2017 * is supposed to finish reset at its driver probe stage, so no
2018 * in-flight DMA will exist, and we don't need to worry anymore
2019 * hereafter.
2020 */
2021 if (context_copied(context)) {
2022 u16 did_old = context_domain_id(context);
2023
Christos Gkekasb117e032017-10-08 23:33:31 +01002024 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002025 iommu->flush.flush_context(iommu, did_old,
2026 (((u16)bus) << 8) | devfn,
2027 DMA_CCMD_MASK_NOBIT,
2028 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002029 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2030 DMA_TLB_DSI_FLUSH);
2031 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002032 }
2033
Joerg Roedelde24e552015-07-21 14:53:04 +02002034 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002035
Lu Baolu7373a8c2018-12-10 09:59:03 +08002036 if (sm_supported(iommu)) {
2037 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002038
Lu Baolu7373a8c2018-12-10 09:59:03 +08002039 WARN_ON(!table);
2040
2041 /* Setup the PASID DIR pointer: */
2042 pds = context_get_sm_pds(table);
2043 context->lo = (u64)virt_to_phys(table->table) |
2044 context_pdts(pds);
2045
2046 /* Setup the RID_PASID field: */
2047 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2048
2049 /*
2050 * Setup the Device-TLB enable bit and Page request
2051 * Enable bit:
2052 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002053 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002054 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002055 context_set_sm_dte(context);
2056 if (info && info->pri_supported)
2057 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002058 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002059 struct dma_pte *pgd = domain->pgd;
2060 int agaw;
2061
2062 context_set_domain_id(context, did);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002063
2064 if (translation != CONTEXT_TT_PASS_THROUGH) {
2065 /*
2066 * Skip top levels of page tables for iommu which has
2067 * less agaw than default. Unnecessary for PT mode.
2068 */
2069 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2070 ret = -ENOMEM;
2071 pgd = phys_to_virt(dma_pte_addr(pgd));
2072 if (!dma_pte_present(pgd))
2073 goto out_unlock;
2074 }
2075
2076 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2077 if (info && info->ats_supported)
2078 translation = CONTEXT_TT_DEV_IOTLB;
2079 else
2080 translation = CONTEXT_TT_MULTI_LEVEL;
2081
2082 context_set_address_root(context, virt_to_phys(pgd));
2083 context_set_address_width(context, agaw);
2084 } else {
2085 /*
2086 * In pass through mode, AW must be programmed to
2087 * indicate the largest AGAW value supported by
2088 * hardware. And ASR is ignored by hardware.
2089 */
2090 context_set_address_width(context, iommu->msagaw);
2091 }
Lu Baolu41b80db2019-03-01 11:23:11 +08002092
2093 context_set_translation_type(context, translation);
Yu Zhao93a23a72009-05-18 13:51:37 +08002094 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002095
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002096 context_set_fault_enable(context);
2097 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08002098 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002099
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002100 /*
2101 * It's a non-present to present mapping. If hardware doesn't cache
2102 * non-present entry we only need to flush the write-buffer. If the
2103 * _does_ cache non-present entries, then it does so in the special
2104 * domain #0, which we have to flush:
2105 */
2106 if (cap_caching_mode(iommu->cap)) {
2107 iommu->flush.flush_context(iommu, 0,
2108 (((u16)bus) << 8) | devfn,
2109 DMA_CCMD_MASK_NOBIT,
2110 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002111 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002112 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002113 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002114 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002115 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002116
Joerg Roedel55d94042015-07-22 16:50:40 +02002117 ret = 0;
2118
2119out_unlock:
2120 spin_unlock(&iommu->lock);
2121 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002122
Wei Yang5c365d12016-07-13 13:53:21 +00002123 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002124}
2125
Alex Williamson579305f2014-07-03 09:51:43 -06002126struct domain_context_mapping_data {
2127 struct dmar_domain *domain;
2128 struct intel_iommu *iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002129 struct pasid_table *table;
Alex Williamson579305f2014-07-03 09:51:43 -06002130};
2131
2132static int domain_context_mapping_cb(struct pci_dev *pdev,
2133 u16 alias, void *opaque)
2134{
2135 struct domain_context_mapping_data *data = opaque;
2136
2137 return domain_context_mapping_one(data->domain, data->iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002138 data->table, PCI_BUS_NUM(alias),
2139 alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06002140}
2141
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002142static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002143domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002144{
Lu Baoluca6e3222018-12-10 09:59:02 +08002145 struct domain_context_mapping_data data;
2146 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002147 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002148 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002149
David Woodhousee1f167f2014-03-09 15:24:46 -07002150 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002151 if (!iommu)
2152 return -ENODEV;
2153
Lu Baoluca6e3222018-12-10 09:59:02 +08002154 table = intel_pasid_get_table(dev);
2155
Alex Williamson579305f2014-07-03 09:51:43 -06002156 if (!dev_is_pci(dev))
Lu Baoluca6e3222018-12-10 09:59:02 +08002157 return domain_context_mapping_one(domain, iommu, table,
2158 bus, devfn);
Alex Williamson579305f2014-07-03 09:51:43 -06002159
2160 data.domain = domain;
2161 data.iommu = iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002162 data.table = table;
Alex Williamson579305f2014-07-03 09:51:43 -06002163
2164 return pci_for_each_dma_alias(to_pci_dev(dev),
2165 &domain_context_mapping_cb, &data);
2166}
2167
2168static int domain_context_mapped_cb(struct pci_dev *pdev,
2169 u16 alias, void *opaque)
2170{
2171 struct intel_iommu *iommu = opaque;
2172
2173 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002174}
2175
David Woodhousee1f167f2014-03-09 15:24:46 -07002176static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002177{
Weidong Han5331fe62008-12-08 23:00:00 +08002178 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002179 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002180
David Woodhousee1f167f2014-03-09 15:24:46 -07002181 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002182 if (!iommu)
2183 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002184
Alex Williamson579305f2014-07-03 09:51:43 -06002185 if (!dev_is_pci(dev))
2186 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002187
Alex Williamson579305f2014-07-03 09:51:43 -06002188 return !pci_for_each_dma_alias(to_pci_dev(dev),
2189 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002190}
2191
Fenghua Yuf5329592009-08-04 15:09:37 -07002192/* Returns a number of VTD pages, but aligned to MM page size */
2193static inline unsigned long aligned_nrpages(unsigned long host_addr,
2194 size_t size)
2195{
2196 host_addr &= ~PAGE_MASK;
2197 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2198}
2199
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002200/* Return largest possible superpage level for a given mapping */
2201static inline int hardware_largepage_caps(struct dmar_domain *domain,
2202 unsigned long iov_pfn,
2203 unsigned long phy_pfn,
2204 unsigned long pages)
2205{
2206 int support, level = 1;
2207 unsigned long pfnmerge;
2208
2209 support = domain->iommu_superpage;
2210
2211 /* To use a large page, the virtual *and* physical addresses
2212 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2213 of them will mean we have to use smaller pages. So just
2214 merge them and check both at once. */
2215 pfnmerge = iov_pfn | phy_pfn;
2216
2217 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2218 pages >>= VTD_STRIDE_SHIFT;
2219 if (!pages)
2220 break;
2221 pfnmerge >>= VTD_STRIDE_SHIFT;
2222 level++;
2223 support--;
2224 }
2225 return level;
2226}
2227
David Woodhouse9051aa02009-06-29 12:30:54 +01002228static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2229 struct scatterlist *sg, unsigned long phys_pfn,
2230 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002231{
2232 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002233 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002234 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002235 unsigned int largepage_lvl = 0;
2236 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01002237
Jiang Liu162d1b12014-07-11 14:19:35 +08002238 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002239
2240 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2241 return -EINVAL;
2242
2243 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
2244
Jiang Liucc4f14a2014-11-26 09:42:10 +08002245 if (!sg) {
2246 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01002247 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
2248 }
2249
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002250 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002251 uint64_t tmp;
2252
David Woodhousee1605492009-06-29 11:17:38 +01002253 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002254 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2255
Fenghua Yuf5329592009-08-04 15:09:37 -07002256 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002257 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002258 sg->dma_length = sg->length;
Robin Murphy29a90b72017-09-28 15:14:01 +01002259 pteval = (sg_phys(sg) - pgoff) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002260 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002261 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002262
David Woodhousee1605492009-06-29 11:17:38 +01002263 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002264 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2265
David Woodhouse5cf0a762014-03-19 16:07:49 +00002266 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002267 if (!pte)
2268 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002269 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002270 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002271 unsigned long nr_superpages, end_pfn;
2272
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002273 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002274 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002275
2276 nr_superpages = sg_res / lvl_pages;
2277 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2278
Jiang Liud41a4ad2014-07-11 14:19:34 +08002279 /*
2280 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002281 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002282 * We're adding new large pages, so make sure
2283 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002284 */
David Dillowbc24c572017-06-28 19:42:23 -07002285 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2286 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002287 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002288 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002289 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002290
David Woodhousee1605492009-06-29 11:17:38 +01002291 }
2292 /* We don't need lock here, nobody else
2293 * touches the iova range
2294 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002295 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002296 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002297 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002298 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2299 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002300 if (dumps) {
2301 dumps--;
2302 debug_dma_dump_mappings(NULL);
2303 }
2304 WARN_ON(1);
2305 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002306
2307 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2308
2309 BUG_ON(nr_pages < lvl_pages);
2310 BUG_ON(sg_res < lvl_pages);
2311
2312 nr_pages -= lvl_pages;
2313 iov_pfn += lvl_pages;
2314 phys_pfn += lvl_pages;
2315 pteval += lvl_pages * VTD_PAGE_SIZE;
2316 sg_res -= lvl_pages;
2317
2318 /* If the next PTE would be the first in a new page, then we
2319 need to flush the cache on the entries we've just written.
2320 And then we'll need to recalculate 'pte', so clear it and
2321 let it get set again in the if (!pte) block above.
2322
2323 If we're done (!nr_pages) we need to flush the cache too.
2324
2325 Also if we've been setting superpages, we may need to
2326 recalculate 'pte' and switch back to smaller pages for the
2327 end of the mapping, if the trailing size is not enough to
2328 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002329 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002330 if (!nr_pages || first_pte_in_page(pte) ||
2331 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002332 domain_flush_cache(domain, first_pte,
2333 (void *)pte - (void *)first_pte);
2334 pte = NULL;
2335 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002336
2337 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002338 sg = sg_next(sg);
2339 }
2340 return 0;
2341}
2342
Peter Xu87684fd2018-05-04 10:34:53 +08002343static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2344 struct scatterlist *sg, unsigned long phys_pfn,
2345 unsigned long nr_pages, int prot)
2346{
2347 int ret;
2348 struct intel_iommu *iommu;
2349
2350 /* Do the real mapping first */
2351 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2352 if (ret)
2353 return ret;
2354
2355 /* Notify about the new mapping */
2356 if (domain_type_is_vm(domain)) {
2357 /* VM typed domains can have more than one IOMMUs */
2358 int iommu_id;
2359 for_each_domain_iommu(iommu_id, domain) {
2360 iommu = g_iommus[iommu_id];
2361 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2362 }
2363 } else {
2364 /* General domains only have one IOMMU */
2365 iommu = domain_get_iommu(domain);
2366 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2367 }
2368
2369 return 0;
2370}
2371
David Woodhouse9051aa02009-06-29 12:30:54 +01002372static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2373 struct scatterlist *sg, unsigned long nr_pages,
2374 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002375{
Peter Xu87684fd2018-05-04 10:34:53 +08002376 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002377}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002378
David Woodhouse9051aa02009-06-29 12:30:54 +01002379static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2380 unsigned long phys_pfn, unsigned long nr_pages,
2381 int prot)
2382{
Peter Xu87684fd2018-05-04 10:34:53 +08002383 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002384}
2385
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002386static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002387{
Filippo Sironi50822192017-08-31 10:58:11 +02002388 unsigned long flags;
2389 struct context_entry *context;
2390 u16 did_old;
2391
Weidong Hanc7151a82008-12-08 22:51:37 +08002392 if (!iommu)
2393 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002394
Filippo Sironi50822192017-08-31 10:58:11 +02002395 spin_lock_irqsave(&iommu->lock, flags);
2396 context = iommu_context_addr(iommu, bus, devfn, 0);
2397 if (!context) {
2398 spin_unlock_irqrestore(&iommu->lock, flags);
2399 return;
2400 }
2401 did_old = context_domain_id(context);
2402 context_clear_entry(context);
2403 __iommu_flush_cache(iommu, context, sizeof(*context));
2404 spin_unlock_irqrestore(&iommu->lock, flags);
2405 iommu->flush.flush_context(iommu,
2406 did_old,
2407 (((u16)bus) << 8) | devfn,
2408 DMA_CCMD_MASK_NOBIT,
2409 DMA_CCMD_DEVICE_INVL);
2410 iommu->flush.flush_iotlb(iommu,
2411 did_old,
2412 0,
2413 0,
2414 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002415}
2416
David Woodhouse109b9b02012-05-25 17:43:02 +01002417static inline void unlink_domain_info(struct device_domain_info *info)
2418{
2419 assert_spin_locked(&device_domain_lock);
2420 list_del(&info->link);
2421 list_del(&info->global);
2422 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002423 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002424}
2425
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002426static void domain_remove_dev_info(struct dmar_domain *domain)
2427{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002428 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002429 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002430
2431 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002432 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002433 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002434 spin_unlock_irqrestore(&device_domain_lock, flags);
2435}
2436
2437/*
2438 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002439 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002440 */
David Woodhouse1525a292014-03-06 16:19:30 +00002441static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002442{
2443 struct device_domain_info *info;
2444
2445 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002446 info = dev->archdata.iommu;
Peter Xub316d022017-05-22 18:28:51 +08002447 if (likely(info))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002448 return info->domain;
2449 return NULL;
2450}
2451
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002452static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002453dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2454{
2455 struct device_domain_info *info;
2456
2457 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002458 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002459 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002460 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002461
2462 return NULL;
2463}
2464
Joerg Roedel5db31562015-07-22 12:40:43 +02002465static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2466 int bus, int devfn,
2467 struct device *dev,
2468 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002469{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002470 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002471 struct device_domain_info *info;
2472 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002473 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002474
2475 info = alloc_devinfo_mem();
2476 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002477 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002478
Jiang Liu745f2582014-02-19 14:07:26 +08002479 info->bus = bus;
2480 info->devfn = devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002481 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2482 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2483 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002484 info->dev = dev;
2485 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002486 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002487 info->pasid_table = NULL;
Lu Baolu95587a72019-03-25 09:30:30 +08002488 info->auxd_enabled = 0;
Lu Baolu67b8e022019-03-25 09:30:32 +08002489 INIT_LIST_HEAD(&info->auxiliary_domains);
Jiang Liu745f2582014-02-19 14:07:26 +08002490
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002491 if (dev && dev_is_pci(dev)) {
2492 struct pci_dev *pdev = to_pci_dev(info->dev);
2493
Lu Baolud8b85912019-03-01 11:23:10 +08002494 if (!pdev->untrusted &&
2495 !pci_ats_disabled() &&
Gil Kupfercef74402018-05-10 17:56:02 -05002496 ecap_dev_iotlb_support(iommu->ecap) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002497 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
2498 dmar_find_matched_atsr_unit(pdev))
2499 info->ats_supported = 1;
2500
Lu Baolu765b6a92018-12-10 09:58:55 +08002501 if (sm_supported(iommu)) {
2502 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002503 int features = pci_pasid_features(pdev);
2504 if (features >= 0)
2505 info->pasid_supported = features | 1;
2506 }
2507
2508 if (info->ats_supported && ecap_prs(iommu->ecap) &&
2509 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
2510 info->pri_supported = 1;
2511 }
2512 }
2513
Jiang Liu745f2582014-02-19 14:07:26 +08002514 spin_lock_irqsave(&device_domain_lock, flags);
2515 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002516 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002517
2518 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002519 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002520 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002521 if (info2) {
2522 found = info2->domain;
2523 info2->dev = dev;
2524 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002525 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002526
Jiang Liu745f2582014-02-19 14:07:26 +08002527 if (found) {
2528 spin_unlock_irqrestore(&device_domain_lock, flags);
2529 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002530 /* Caller must free the original domain */
2531 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002532 }
2533
Joerg Roedeld160aca2015-07-22 11:52:53 +02002534 spin_lock(&iommu->lock);
2535 ret = domain_attach_iommu(domain, iommu);
2536 spin_unlock(&iommu->lock);
2537
2538 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002539 spin_unlock_irqrestore(&device_domain_lock, flags);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302540 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002541 return NULL;
2542 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002543
David Woodhouseb718cd32014-03-09 13:11:33 -07002544 list_add(&info->link, &domain->devices);
2545 list_add(&info->global, &device_domain_list);
2546 if (dev)
2547 dev->archdata.iommu = info;
Lu Baolu0bbeb012018-12-10 09:58:56 +08002548 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002549
Lu Baolu0bbeb012018-12-10 09:58:56 +08002550 /* PASID table is mandatory for a PCI device in scalable mode. */
2551 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002552 ret = intel_pasid_alloc_table(dev);
2553 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002554 dev_err(dev, "PASID table allocation failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002555 dmar_remove_one_dev_info(dev);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002556 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002557 }
Lu Baoluef848b72018-12-10 09:59:01 +08002558
2559 /* Setup the PASID entry for requests without PASID: */
2560 spin_lock(&iommu->lock);
2561 if (hw_pass_through && domain_type_is_si(domain))
2562 ret = intel_pasid_setup_pass_through(iommu, domain,
2563 dev, PASID_RID2PASID);
2564 else
2565 ret = intel_pasid_setup_second_level(iommu, domain,
2566 dev, PASID_RID2PASID);
2567 spin_unlock(&iommu->lock);
2568 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002569 dev_err(dev, "Setup RID2PASID failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002570 dmar_remove_one_dev_info(dev);
Lu Baoluef848b72018-12-10 09:59:01 +08002571 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002572 }
2573 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002574
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002575 if (dev && domain_context_mapping(domain, dev)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002576 dev_err(dev, "Domain context map failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002577 dmar_remove_one_dev_info(dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002578 return NULL;
2579 }
2580
David Woodhouseb718cd32014-03-09 13:11:33 -07002581 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002582}
2583
Alex Williamson579305f2014-07-03 09:51:43 -06002584static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2585{
2586 *(u16 *)opaque = alias;
2587 return 0;
2588}
2589
Joerg Roedel76208352016-08-25 14:25:12 +02002590static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002591{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002592 struct device_domain_info *info;
Joerg Roedel76208352016-08-25 14:25:12 +02002593 struct dmar_domain *domain = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002594 struct intel_iommu *iommu;
Lu Baolufcc35c62018-05-04 13:08:17 +08002595 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002596 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002597 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002598
David Woodhouse146922e2014-03-09 15:44:17 -07002599 iommu = device_to_iommu(dev, &bus, &devfn);
2600 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002601 return NULL;
2602
2603 if (dev_is_pci(dev)) {
2604 struct pci_dev *pdev = to_pci_dev(dev);
2605
2606 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2607
2608 spin_lock_irqsave(&device_domain_lock, flags);
2609 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2610 PCI_BUS_NUM(dma_alias),
2611 dma_alias & 0xff);
2612 if (info) {
2613 iommu = info->iommu;
2614 domain = info->domain;
2615 }
2616 spin_unlock_irqrestore(&device_domain_lock, flags);
2617
Joerg Roedel76208352016-08-25 14:25:12 +02002618 /* DMA alias already has a domain, use it */
Alex Williamson579305f2014-07-03 09:51:43 -06002619 if (info)
Joerg Roedel76208352016-08-25 14:25:12 +02002620 goto out;
Alex Williamson579305f2014-07-03 09:51:43 -06002621 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002622
David Woodhouse146922e2014-03-09 15:44:17 -07002623 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002624 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002625 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002626 return NULL;
Joerg Roedeldc534b22015-07-22 12:44:02 +02002627 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002628 domain_exit(domain);
2629 return NULL;
2630 }
2631
Joerg Roedel76208352016-08-25 14:25:12 +02002632out:
Alex Williamson579305f2014-07-03 09:51:43 -06002633
Joerg Roedel76208352016-08-25 14:25:12 +02002634 return domain;
2635}
2636
2637static struct dmar_domain *set_domain_for_dev(struct device *dev,
2638 struct dmar_domain *domain)
2639{
2640 struct intel_iommu *iommu;
2641 struct dmar_domain *tmp;
2642 u16 req_id, dma_alias;
2643 u8 bus, devfn;
2644
2645 iommu = device_to_iommu(dev, &bus, &devfn);
2646 if (!iommu)
2647 return NULL;
2648
2649 req_id = ((u16)bus << 8) | devfn;
2650
2651 if (dev_is_pci(dev)) {
2652 struct pci_dev *pdev = to_pci_dev(dev);
2653
2654 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2655
2656 /* register PCI DMA alias device */
2657 if (req_id != dma_alias) {
2658 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2659 dma_alias & 0xff, NULL, domain);
2660
2661 if (!tmp || tmp != domain)
2662 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002663 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002664 }
2665
Joerg Roedel5db31562015-07-22 12:40:43 +02002666 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
Joerg Roedel76208352016-08-25 14:25:12 +02002667 if (!tmp || tmp != domain)
2668 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002669
Joerg Roedel76208352016-08-25 14:25:12 +02002670 return domain;
2671}
2672
2673static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2674{
2675 struct dmar_domain *domain, *tmp;
2676
2677 domain = find_domain(dev);
2678 if (domain)
2679 goto out;
2680
2681 domain = find_or_alloc_domain(dev, gaw);
2682 if (!domain)
2683 goto out;
2684
2685 tmp = set_domain_for_dev(dev, domain);
2686 if (!tmp || domain != tmp) {
Alex Williamson579305f2014-07-03 09:51:43 -06002687 domain_exit(domain);
2688 domain = tmp;
2689 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002690
Joerg Roedel76208352016-08-25 14:25:12 +02002691out:
2692
David Woodhouseb718cd32014-03-09 13:11:33 -07002693 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002694}
2695
David Woodhouseb2132032009-06-26 18:50:28 +01002696static int iommu_domain_identity_map(struct dmar_domain *domain,
2697 unsigned long long start,
2698 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002699{
David Woodhousec5395d52009-06-28 16:35:56 +01002700 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2701 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002702
David Woodhousec5395d52009-06-28 16:35:56 +01002703 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2704 dma_to_mm_pfn(last_vpfn))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002705 pr_err("Reserving iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002706 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002707 }
2708
Joerg Roedelaf1089c2015-07-21 15:45:19 +02002709 pr_debug("Mapping reserved region %llx-%llx\n", start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002710 /*
2711 * RMRR range might have overlap with physical memory range,
2712 * clear it first
2713 */
David Woodhousec5395d52009-06-28 16:35:56 +01002714 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002715
Peter Xu87684fd2018-05-04 10:34:53 +08002716 return __domain_mapping(domain, first_vpfn, NULL,
2717 first_vpfn, last_vpfn - first_vpfn + 1,
2718 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002719}
2720
Joerg Roedeld66ce542015-09-23 19:00:10 +02002721static int domain_prepare_identity_map(struct device *dev,
2722 struct dmar_domain *domain,
2723 unsigned long long start,
2724 unsigned long long end)
David Woodhouseb2132032009-06-26 18:50:28 +01002725{
David Woodhouse19943b02009-08-04 16:19:20 +01002726 /* For _hardware_ passthrough, don't bother. But for software
2727 passthrough, we do it anyway -- it may indicate a memory
2728 range which is reserved in E820, so which didn't get set
2729 up to start with in si_domain */
2730 if (domain == si_domain && hw_pass_through) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002731 dev_warn(dev, "Ignoring identity map for HW passthrough [0x%Lx - 0x%Lx]\n",
2732 start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002733 return 0;
2734 }
2735
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002736 dev_info(dev, "Setting identity map [0x%Lx - 0x%Lx]\n", start, end);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002737
David Woodhouse5595b522009-12-02 09:21:55 +00002738 if (end < start) {
2739 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2740 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2741 dmi_get_system_info(DMI_BIOS_VENDOR),
2742 dmi_get_system_info(DMI_BIOS_VERSION),
2743 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002744 return -EIO;
David Woodhouse5595b522009-12-02 09:21:55 +00002745 }
2746
David Woodhouse2ff729f2009-08-26 14:25:41 +01002747 if (end >> agaw_to_width(domain->agaw)) {
2748 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2749 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2750 agaw_to_width(domain->agaw),
2751 dmi_get_system_info(DMI_BIOS_VENDOR),
2752 dmi_get_system_info(DMI_BIOS_VERSION),
2753 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002754 return -EIO;
David Woodhouse2ff729f2009-08-26 14:25:41 +01002755 }
David Woodhouse19943b02009-08-04 16:19:20 +01002756
Joerg Roedeld66ce542015-09-23 19:00:10 +02002757 return iommu_domain_identity_map(domain, start, end);
2758}
2759
2760static int iommu_prepare_identity_map(struct device *dev,
2761 unsigned long long start,
2762 unsigned long long end)
2763{
2764 struct dmar_domain *domain;
2765 int ret;
2766
2767 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
2768 if (!domain)
2769 return -ENOMEM;
2770
2771 ret = domain_prepare_identity_map(dev, domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002772 if (ret)
Joerg Roedeld66ce542015-09-23 19:00:10 +02002773 domain_exit(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002774
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002775 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002776}
2777
2778static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002779 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002780{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002781 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002782 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002783 return iommu_prepare_identity_map(dev, rmrr->base_address,
2784 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002785}
2786
Suresh Siddhad3f13812011-08-23 17:05:25 -07002787#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002788static inline void iommu_prepare_isa(void)
2789{
2790 struct pci_dev *pdev;
2791 int ret;
2792
2793 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2794 if (!pdev)
2795 return;
2796
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002797 pr_info("Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002798 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002799
2800 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002801 pr_err("Failed to create 0-16MiB identity map - floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002802
Yijing Wang9b27e822014-05-20 20:37:52 +08002803 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002804}
2805#else
2806static inline void iommu_prepare_isa(void)
2807{
2808 return;
2809}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002810#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002811
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002812static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002813
Matt Kraai071e1372009-08-23 22:30:22 -07002814static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002815{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002816 int nid, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002817
Jiang Liuab8dfe22014-07-11 14:19:27 +08002818 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002819 if (!si_domain)
2820 return -EFAULT;
2821
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002822 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2823 domain_exit(si_domain);
2824 return -EFAULT;
2825 }
2826
Joerg Roedel0dc79712015-07-21 15:40:06 +02002827 pr_debug("Identity mapping domain allocated\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002828
David Woodhouse19943b02009-08-04 16:19:20 +01002829 if (hw)
2830 return 0;
2831
David Woodhousec7ab48d2009-06-26 19:10:36 +01002832 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002833 unsigned long start_pfn, end_pfn;
2834 int i;
2835
2836 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2837 ret = iommu_domain_identity_map(si_domain,
2838 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2839 if (ret)
2840 return ret;
2841 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002842 }
2843
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002844 return 0;
2845}
2846
David Woodhouse9b226622014-03-09 14:03:28 -07002847static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002848{
2849 struct device_domain_info *info;
2850
2851 if (likely(!iommu_identity_mapping))
2852 return 0;
2853
David Woodhouse9b226622014-03-09 14:03:28 -07002854 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002855 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2856 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002857
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002858 return 0;
2859}
2860
Joerg Roedel28ccce02015-07-21 14:45:31 +02002861static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002862{
David Woodhouse0ac72662014-03-09 13:19:22 -07002863 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002864 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002865 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002866
David Woodhouse5913c9b2014-03-09 16:27:31 -07002867 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002868 if (!iommu)
2869 return -ENODEV;
2870
Joerg Roedel5db31562015-07-22 12:40:43 +02002871 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002872 if (ndomain != domain)
2873 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002874
2875 return 0;
2876}
2877
David Woodhouse0b9d9752014-03-09 15:48:15 -07002878static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002879{
2880 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002881 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002882 int i;
2883
Jiang Liu0e242612014-02-19 14:07:34 +08002884 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002885 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002886 /*
2887 * Return TRUE if this RMRR contains the device that
2888 * is passed in.
2889 */
2890 for_each_active_dev_scope(rmrr->devices,
2891 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002892 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002893 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002894 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002895 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002896 }
Jiang Liu0e242612014-02-19 14:07:34 +08002897 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002898 return false;
2899}
2900
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002901/*
2902 * There are a couple cases where we need to restrict the functionality of
2903 * devices associated with RMRRs. The first is when evaluating a device for
2904 * identity mapping because problems exist when devices are moved in and out
2905 * of domains and their respective RMRR information is lost. This means that
2906 * a device with associated RMRRs will never be in a "passthrough" domain.
2907 * The second is use of the device through the IOMMU API. This interface
2908 * expects to have full control of the IOVA space for the device. We cannot
2909 * satisfy both the requirement that RMRR access is maintained and have an
2910 * unencumbered IOVA space. We also have no ability to quiesce the device's
2911 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2912 * We therefore prevent devices associated with an RMRR from participating in
2913 * the IOMMU API, which eliminates them from device assignment.
2914 *
2915 * In both cases we assume that PCI USB devices with RMRRs have them largely
2916 * for historical reasons and that the RMRR space is not actively used post
2917 * boot. This exclusion may change if vendors begin to abuse it.
David Woodhouse18436af2015-03-25 15:05:47 +00002918 *
2919 * The same exception is made for graphics devices, with the requirement that
2920 * any use of the RMRR regions will be torn down before assigning the device
2921 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002922 */
2923static bool device_is_rmrr_locked(struct device *dev)
2924{
2925 if (!device_has_rmrr(dev))
2926 return false;
2927
2928 if (dev_is_pci(dev)) {
2929 struct pci_dev *pdev = to_pci_dev(dev);
2930
David Woodhouse18436af2015-03-25 15:05:47 +00002931 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002932 return false;
2933 }
2934
2935 return true;
2936}
2937
David Woodhouse3bdb2592014-03-09 16:03:08 -07002938static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002939{
David Woodhouse3bdb2592014-03-09 16:03:08 -07002940 if (dev_is_pci(dev)) {
2941 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002942
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002943 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002944 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002945
Lu Baolu89a60792018-10-23 15:45:01 +08002946 /*
2947 * Prevent any device marked as untrusted from getting
2948 * placed into the statically identity mapping domain.
2949 */
2950 if (pdev->untrusted)
2951 return 0;
2952
David Woodhouse3bdb2592014-03-09 16:03:08 -07002953 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2954 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002955
David Woodhouse3bdb2592014-03-09 16:03:08 -07002956 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2957 return 1;
2958
2959 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2960 return 0;
2961
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))
2981 return 0;
2982 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2983 return 0;
2984 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2985 return 0;
2986 } else {
2987 if (device_has_rmrr(dev))
2988 return 0;
2989 }
David Woodhouse6941af22009-07-04 18:24:27 +01002990
David Woodhouse3dfc8132009-07-04 19:11:08 +01002991 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002992 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002993 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002994 * take them out of the 1:1 domain later.
2995 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002996 if (!startup) {
2997 /*
2998 * If the device's dma_mask is less than the system's memory
2999 * size then this is not a candidate for identity mapping.
3000 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07003001 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05003002
David Woodhouse3bdb2592014-03-09 16:03:08 -07003003 if (dev->coherent_dma_mask &&
3004 dev->coherent_dma_mask < dma_mask)
3005 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05003006
David Woodhouse3bdb2592014-03-09 16:03:08 -07003007 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05003008 }
David Woodhouse6941af22009-07-04 18:24:27 +01003009
3010 return 1;
3011}
3012
David Woodhousecf04eee2014-03-21 16:49:04 +00003013static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
3014{
3015 int ret;
3016
3017 if (!iommu_should_identity_map(dev, 1))
3018 return 0;
3019
Joerg Roedel28ccce02015-07-21 14:45:31 +02003020 ret = domain_add_dev_info(si_domain, dev);
David Woodhousecf04eee2014-03-21 16:49:04 +00003021 if (!ret)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003022 dev_info(dev, "%s identity mapping\n",
3023 hw ? "Hardware" : "Software");
David Woodhousecf04eee2014-03-21 16:49:04 +00003024 else if (ret == -ENODEV)
3025 /* device not associated with an iommu */
3026 ret = 0;
3027
3028 return ret;
3029}
3030
3031
Matt Kraai071e1372009-08-23 22:30:22 -07003032static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003033{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003034 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00003035 struct dmar_drhd_unit *drhd;
3036 struct intel_iommu *iommu;
3037 struct device *dev;
3038 int i;
3039 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003040
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003041 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00003042 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
3043 if (ret)
3044 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003045 }
3046
David Woodhousecf04eee2014-03-21 16:49:04 +00003047 for_each_active_iommu(iommu, drhd)
3048 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
3049 struct acpi_device_physical_node *pn;
3050 struct acpi_device *adev;
3051
3052 if (dev->bus != &acpi_bus_type)
3053 continue;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003054
David Woodhousecf04eee2014-03-21 16:49:04 +00003055 adev= to_acpi_device(dev);
3056 mutex_lock(&adev->physical_node_lock);
3057 list_for_each_entry(pn, &adev->physical_node_list, node) {
3058 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
3059 if (ret)
3060 break;
3061 }
3062 mutex_unlock(&adev->physical_node_lock);
3063 if (ret)
3064 return ret;
3065 }
3066
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003067 return 0;
3068}
3069
Jiang Liuffebeb42014-11-09 22:48:02 +08003070static void intel_iommu_init_qi(struct intel_iommu *iommu)
3071{
3072 /*
3073 * Start from the sane iommu hardware state.
3074 * If the queued invalidation is already initialized by us
3075 * (for example, while enabling interrupt-remapping) then
3076 * we got the things already rolling from a sane state.
3077 */
3078 if (!iommu->qi) {
3079 /*
3080 * Clear any previous faults.
3081 */
3082 dmar_fault(-1, iommu);
3083 /*
3084 * Disable queued invalidation if supported and already enabled
3085 * before OS handover.
3086 */
3087 dmar_disable_qi(iommu);
3088 }
3089
3090 if (dmar_enable_qi(iommu)) {
3091 /*
3092 * Queued Invalidate not enabled, use Register Based Invalidate
3093 */
3094 iommu->flush.flush_context = __iommu_flush_context;
3095 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003096 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08003097 iommu->name);
3098 } else {
3099 iommu->flush.flush_context = qi_flush_context;
3100 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003101 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08003102 }
3103}
3104
Joerg Roedel091d42e2015-06-12 11:56:10 +02003105static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04003106 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02003107 struct context_entry **tbl,
3108 int bus, bool ext)
3109{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003110 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003111 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04003112 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003113 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003114 phys_addr_t old_ce_phys;
3115
3116 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04003117 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003118
3119 for (devfn = 0; devfn < 256; devfn++) {
3120 /* First calculate the correct index */
3121 idx = (ext ? devfn * 2 : devfn) % 256;
3122
3123 if (idx == 0) {
3124 /* First save what we may have and clean up */
3125 if (new_ce) {
3126 tbl[tbl_idx] = new_ce;
3127 __iommu_flush_cache(iommu, new_ce,
3128 VTD_PAGE_SIZE);
3129 pos = 1;
3130 }
3131
3132 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08003133 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003134
3135 ret = 0;
3136 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003137 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003138 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003139 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003140
3141 if (!old_ce_phys) {
3142 if (ext && devfn == 0) {
3143 /* No LCTP, try UCTP */
3144 devfn = 0x7f;
3145 continue;
3146 } else {
3147 goto out;
3148 }
3149 }
3150
3151 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003152 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3153 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003154 if (!old_ce)
3155 goto out;
3156
3157 new_ce = alloc_pgtable_page(iommu->node);
3158 if (!new_ce)
3159 goto out_unmap;
3160
3161 ret = 0;
3162 }
3163
3164 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003165 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003166
Joerg Roedelcf484d02015-06-12 12:21:46 +02003167 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003168 continue;
3169
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003170 did = context_domain_id(&ce);
3171 if (did >= 0 && did < cap_ndoms(iommu->cap))
3172 set_bit(did, iommu->domain_ids);
3173
Joerg Roedelcf484d02015-06-12 12:21:46 +02003174 /*
3175 * We need a marker for copied context entries. This
3176 * marker needs to work for the old format as well as
3177 * for extended context entries.
3178 *
3179 * Bit 67 of the context entry is used. In the old
3180 * format this bit is available to software, in the
3181 * extended format it is the PGE bit, but PGE is ignored
3182 * by HW if PASIDs are disabled (and thus still
3183 * available).
3184 *
3185 * So disable PASIDs first and then mark the entry
3186 * copied. This means that we don't copy PASID
3187 * translations from the old kernel, but this is fine as
3188 * faults there are not fatal.
3189 */
3190 context_clear_pasid_enable(&ce);
3191 context_set_copied(&ce);
3192
Joerg Roedel091d42e2015-06-12 11:56:10 +02003193 new_ce[idx] = ce;
3194 }
3195
3196 tbl[tbl_idx + pos] = new_ce;
3197
3198 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3199
3200out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003201 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003202
3203out:
3204 return ret;
3205}
3206
3207static int copy_translation_tables(struct intel_iommu *iommu)
3208{
3209 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003210 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003211 phys_addr_t old_rt_phys;
3212 int ctxt_table_entries;
3213 unsigned long flags;
3214 u64 rtaddr_reg;
3215 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003216 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003217
3218 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3219 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003220 new_ext = !!ecap_ecs(iommu->ecap);
3221
3222 /*
3223 * The RTT bit can only be changed when translation is disabled,
3224 * but disabling translation means to open a window for data
3225 * corruption. So bail out and don't copy anything if we would
3226 * have to change the bit.
3227 */
3228 if (new_ext != ext)
3229 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003230
3231 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3232 if (!old_rt_phys)
3233 return -EINVAL;
3234
Dan Williamsdfddb962015-10-09 18:16:46 -04003235 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003236 if (!old_rt)
3237 return -ENOMEM;
3238
3239 /* This is too big for the stack - allocate it from slab */
3240 ctxt_table_entries = ext ? 512 : 256;
3241 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003242 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003243 if (!ctxt_tbls)
3244 goto out_unmap;
3245
3246 for (bus = 0; bus < 256; bus++) {
3247 ret = copy_context_table(iommu, &old_rt[bus],
3248 ctxt_tbls, bus, ext);
3249 if (ret) {
3250 pr_err("%s: Failed to copy context table for bus %d\n",
3251 iommu->name, bus);
3252 continue;
3253 }
3254 }
3255
3256 spin_lock_irqsave(&iommu->lock, flags);
3257
3258 /* Context tables are copied, now write them to the root_entry table */
3259 for (bus = 0; bus < 256; bus++) {
3260 int idx = ext ? bus * 2 : bus;
3261 u64 val;
3262
3263 if (ctxt_tbls[idx]) {
3264 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3265 iommu->root_entry[bus].lo = val;
3266 }
3267
3268 if (!ext || !ctxt_tbls[idx + 1])
3269 continue;
3270
3271 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3272 iommu->root_entry[bus].hi = val;
3273 }
3274
3275 spin_unlock_irqrestore(&iommu->lock, flags);
3276
3277 kfree(ctxt_tbls);
3278
3279 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3280
3281 ret = 0;
3282
3283out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003284 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003285
3286 return ret;
3287}
3288
Joseph Cihulab7792602011-05-03 00:08:37 -07003289static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003290{
3291 struct dmar_drhd_unit *drhd;
3292 struct dmar_rmrr_unit *rmrr;
Joerg Roedela87f4912015-06-12 12:32:54 +02003293 bool copied_tables = false;
David Woodhouse832bd852014-03-07 15:08:36 +00003294 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003295 struct intel_iommu *iommu;
Joerg Roedel13cf0172017-08-11 11:40:10 +02003296 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003297
3298 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003299 * for each drhd
3300 * allocate root
3301 * initialize and program root entry to not present
3302 * endfor
3303 */
3304 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003305 /*
3306 * lock not needed as this is only incremented in the single
3307 * threaded kernel __init code path all other access are read
3308 * only
3309 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003310 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003311 g_num_of_iommus++;
3312 continue;
3313 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003314 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003315 }
3316
Jiang Liuffebeb42014-11-09 22:48:02 +08003317 /* Preallocate enough resources for IOMMU hot-addition */
3318 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3319 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3320
Weidong Hand9630fe2008-12-08 11:06:32 +08003321 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3322 GFP_KERNEL);
3323 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003324 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003325 ret = -ENOMEM;
3326 goto error;
3327 }
3328
Jiang Liu7c919772014-01-06 14:18:18 +08003329 for_each_active_iommu(iommu, drhd) {
Lu Baolu56283172018-07-14 15:46:54 +08003330 /*
3331 * Find the max pasid size of all IOMMU's in the system.
3332 * We need to ensure the system pasid table is no bigger
3333 * than the smallest supported.
3334 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003335 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003336 u32 temp = 2 << ecap_pss(iommu->ecap);
3337
3338 intel_pasid_max_id = min_t(u32, temp,
3339 intel_pasid_max_id);
3340 }
3341
Weidong Hand9630fe2008-12-08 11:06:32 +08003342 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003343
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003344 intel_iommu_init_qi(iommu);
3345
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003346 ret = iommu_init_domains(iommu);
3347 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003348 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003349
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003350 init_translation_status(iommu);
3351
Joerg Roedel091d42e2015-06-12 11:56:10 +02003352 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3353 iommu_disable_translation(iommu);
3354 clear_translation_pre_enabled(iommu);
3355 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3356 iommu->name);
3357 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003358
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003359 /*
3360 * TBD:
3361 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003362 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003363 */
3364 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003365 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003366 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003367
Joerg Roedel091d42e2015-06-12 11:56:10 +02003368 if (translation_pre_enabled(iommu)) {
3369 pr_info("Translation already enabled - trying to copy translation structures\n");
3370
3371 ret = copy_translation_tables(iommu);
3372 if (ret) {
3373 /*
3374 * We found the IOMMU with translation
3375 * enabled - but failed to copy over the
3376 * old root-entry table. Try to proceed
3377 * by disabling translation now and
3378 * allocating a clean root-entry table.
3379 * This might cause DMAR faults, but
3380 * probably the dump will still succeed.
3381 */
3382 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3383 iommu->name);
3384 iommu_disable_translation(iommu);
3385 clear_translation_pre_enabled(iommu);
3386 } else {
3387 pr_info("Copied translation tables from previous kernel for %s\n",
3388 iommu->name);
Joerg Roedela87f4912015-06-12 12:32:54 +02003389 copied_tables = true;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003390 }
3391 }
3392
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003393 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003394 hw_pass_through = 0;
David Woodhouse8a94ade2015-03-24 14:54:56 +00003395#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003396 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08003397 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00003398#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003399 }
3400
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003401 /*
3402 * Now that qi is enabled on all iommus, set the root entry and flush
3403 * caches. This is required on some Intel X58 chipsets, otherwise the
3404 * flush_context function will loop forever and the boot hangs.
3405 */
3406 for_each_active_iommu(iommu, drhd) {
3407 iommu_flush_write_buffer(iommu);
3408 iommu_set_root_entry(iommu);
3409 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3410 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3411 }
3412
David Woodhouse19943b02009-08-04 16:19:20 +01003413 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07003414 iommu_identity_mapping |= IDENTMAP_ALL;
3415
Suresh Siddhad3f13812011-08-23 17:05:25 -07003416#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07003417 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01003418#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003419
Ashok Raj21e722c2017-01-30 09:39:53 -08003420 check_tylersburg_isoch();
3421
Joerg Roedel86080cc2015-06-12 12:27:16 +02003422 if (iommu_identity_mapping) {
3423 ret = si_domain_init(hw_pass_through);
3424 if (ret)
3425 goto free_iommu;
3426 }
3427
David Woodhousee0fc7e02009-09-30 09:12:17 -07003428
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003429 /*
Joerg Roedela87f4912015-06-12 12:32:54 +02003430 * If we copied translations from a previous kernel in the kdump
3431 * case, we can not assign the devices to domains now, as that
3432 * would eliminate the old mappings. So skip this part and defer
3433 * the assignment to device driver initialization time.
3434 */
3435 if (copied_tables)
3436 goto domains_done;
3437
3438 /*
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003439 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003440 * identity mappings for rmrr, gfx, and isa and may fall back to static
3441 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003442 */
David Woodhouse19943b02009-08-04 16:19:20 +01003443 if (iommu_identity_mapping) {
3444 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
3445 if (ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003446 pr_crit("Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08003447 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003448 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003449 }
David Woodhouse19943b02009-08-04 16:19:20 +01003450 /*
3451 * For each rmrr
3452 * for each dev attached to rmrr
3453 * do
3454 * locate drhd for dev, alloc domain for dev
3455 * allocate free domain
3456 * allocate page table entries for rmrr
3457 * if context not allocated for bus
3458 * allocate and init context
3459 * set present in root table for this bus
3460 * init context with domain, translation etc
3461 * endfor
3462 * endfor
3463 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003464 pr_info("Setting RMRR:\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003465 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08003466 /* some BIOS lists non-exist devices in DMAR table. */
3467 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00003468 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07003469 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01003470 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003471 pr_err("Mapping reserved region failed\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003472 }
3473 }
3474
3475 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07003476
Joerg Roedela87f4912015-06-12 12:32:54 +02003477domains_done:
3478
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003479 /*
3480 * for each drhd
3481 * enable fault log
3482 * global invalidate context cache
3483 * global invalidate iotlb
3484 * enable translation
3485 */
Jiang Liu7c919772014-01-06 14:18:18 +08003486 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003487 if (drhd->ignored) {
3488 /*
3489 * we always have to disable PMRs or DMA may fail on
3490 * this device
3491 */
3492 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003493 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003494 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003495 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003496
3497 iommu_flush_write_buffer(iommu);
3498
David Woodhousea222a7f2015-10-07 23:35:18 +01003499#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003500 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01003501 ret = intel_svm_enable_prq(iommu);
3502 if (ret)
3503 goto free_iommu;
3504 }
3505#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003506 ret = dmar_set_interrupt(iommu);
3507 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003508 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003509
Joerg Roedel8939ddf2015-06-12 14:40:01 +02003510 if (!translation_pre_enabled(iommu))
3511 iommu_enable_translation(iommu);
3512
David Woodhouseb94996c2009-09-19 15:28:12 -07003513 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003514 }
3515
3516 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003517
3518free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003519 for_each_active_iommu(iommu, drhd) {
3520 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003521 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003522 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003523
Weidong Hand9630fe2008-12-08 11:06:32 +08003524 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003525
Jiang Liu989d51f2014-02-19 14:07:21 +08003526error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003527 return ret;
3528}
3529
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003530/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003531static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003532 struct dmar_domain *domain,
3533 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003534{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06003535 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003536
David Woodhouse875764d2009-06-28 21:20:51 +01003537 /* Restrict dma_mask to the width that the iommu can handle */
3538 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
Robin Murphy8f6429c2015-07-16 19:40:12 +01003539 /* Ensure we reserve the whole size-aligned region */
3540 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003541
3542 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003543 /*
3544 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003545 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003546 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003547 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003548 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003549 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003550 if (iova_pfn)
3551 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003552 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003553 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3554 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003555 if (unlikely(!iova_pfn)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003556 dev_err(dev, "Allocating %ld-page iova failed", nrpages);
Omer Peleg2aac6302016-04-20 11:33:57 +03003557 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003558 }
3559
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003560 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003561}
3562
Lu Baolu9ddbfb42018-07-14 15:46:57 +08003563struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003564{
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003565 struct dmar_domain *domain, *tmp;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003566 struct dmar_rmrr_unit *rmrr;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003567 struct device *i_dev;
3568 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003569
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003570 domain = find_domain(dev);
3571 if (domain)
3572 goto out;
3573
3574 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3575 if (!domain)
3576 goto out;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003577
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003578 /* We have a new domain - setup possible RMRRs for the device */
3579 rcu_read_lock();
3580 for_each_rmrr_units(rmrr) {
3581 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3582 i, i_dev) {
3583 if (i_dev != dev)
3584 continue;
3585
3586 ret = domain_prepare_identity_map(dev, domain,
3587 rmrr->base_address,
3588 rmrr->end_address);
3589 if (ret)
3590 dev_err(dev, "Mapping reserved region failed\n");
3591 }
3592 }
3593 rcu_read_unlock();
3594
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003595 tmp = set_domain_for_dev(dev, domain);
3596 if (!tmp || domain != tmp) {
3597 domain_exit(domain);
3598 domain = tmp;
3599 }
3600
3601out:
3602
3603 if (!domain)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003604 dev_err(dev, "Allocating domain failed\n");
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003605
3606
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003607 return domain;
3608}
3609
David Woodhouseecb509e2014-03-09 16:29:55 -07003610/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01003611static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003612{
3613 int found;
3614
David Woodhouse3d891942014-03-06 15:59:26 +00003615 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003616 return 1;
3617
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003618 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003619 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003620
David Woodhouse9b226622014-03-09 14:03:28 -07003621 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003622 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07003623 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003624 return 1;
3625 else {
3626 /*
3627 * 32 bit DMA is removed from si_domain and fall back
3628 * to non-identity mapping.
3629 */
Bjorn Helgaas71753232019-02-08 16:06:15 -06003630 dmar_remove_one_dev_info(dev);
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003631 dev_info(dev, "32bit DMA uses non-identity mapping\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003632 return 0;
3633 }
3634 } else {
3635 /*
3636 * In case of a detached 64 bit DMA device from vm, the device
3637 * is put into si_domain for identity mapping.
3638 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003639 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003640 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02003641 ret = domain_add_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003642 if (!ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003643 dev_info(dev, "64bit DMA uses identity mapping\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003644 return 1;
3645 }
3646 }
3647 }
3648
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003649 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003650}
3651
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003652static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3653 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003654{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003655 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003656 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003657 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003658 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003659 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003660 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003661 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003662
3663 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003664
David Woodhouse5040a912014-03-09 16:14:00 -07003665 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003666 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003667
David Woodhouse5040a912014-03-09 16:14:00 -07003668 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003669 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003670 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003671
Weidong Han8c11e792008-12-08 15:29:22 +08003672 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003673 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003674
Omer Peleg2aac6302016-04-20 11:33:57 +03003675 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3676 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003677 goto error;
3678
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003679 /*
3680 * Check if DMAR supports zero-length reads on write only
3681 * mappings..
3682 */
3683 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003684 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003685 prot |= DMA_PTE_READ;
3686 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3687 prot |= DMA_PTE_WRITE;
3688 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003689 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003690 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003691 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003692 * is not a big problem
3693 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003694 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003695 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003696 if (ret)
3697 goto error;
3698
Omer Peleg2aac6302016-04-20 11:33:57 +03003699 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003700 start_paddr += paddr & ~PAGE_MASK;
3701 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003702
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003703error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003704 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003705 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003706 dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n",
3707 size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003708 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003709}
3710
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003711static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3712 unsigned long offset, size_t size,
3713 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003714 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003715{
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003716 return __intel_map_single(dev, page_to_phys(page) + offset, size,
3717 dir, *dev->dma_mask);
3718}
3719
3720static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3721 size_t size, enum dma_data_direction dir,
3722 unsigned long attrs)
3723{
3724 return __intel_map_single(dev, phys_addr, size, dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003725}
3726
Omer Peleg769530e2016-04-20 11:33:25 +03003727static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003728{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003730 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003731 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003732 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003733 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003734 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003735
David Woodhouse73676832009-07-04 14:08:36 +01003736 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003737 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003738
David Woodhouse1525a292014-03-06 16:19:30 +00003739 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003740 BUG_ON(!domain);
3741
Weidong Han8c11e792008-12-08 15:29:22 +08003742 iommu = domain_get_iommu(domain);
3743
Omer Peleg2aac6302016-04-20 11:33:57 +03003744 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003745
Omer Peleg769530e2016-04-20 11:33:25 +03003746 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003747 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003748 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003749
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003750 dev_dbg(dev, "Device unmapping: pfn %lx-%lx\n", start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003751
David Woodhouseea8ea462014-03-05 17:09:32 +00003752 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003753
mark gross5e0d2a62008-03-04 15:22:08 -08003754 if (intel_iommu_strict) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003755 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003756 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003757 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003758 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003759 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003760 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003761 queue_iova(&domain->iovad, iova_pfn, nrpages,
3762 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003763 /*
3764 * queue up the release of the unmap to save the 1/6th of the
3765 * cpu used up by the iotlb flush operation...
3766 */
mark gross5e0d2a62008-03-04 15:22:08 -08003767 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003768}
3769
Jiang Liud41a4ad2014-07-11 14:19:34 +08003770static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3771 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003772 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003773{
Omer Peleg769530e2016-04-20 11:33:25 +03003774 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003775}
3776
David Woodhouse5040a912014-03-09 16:14:00 -07003777static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003778 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003779 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003780{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003781 struct page *page = NULL;
3782 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003783
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003784 size = PAGE_ALIGN(size);
3785 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003786
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003787 if (!iommu_no_mapping(dev))
3788 flags &= ~(GFP_DMA | GFP_DMA32);
3789 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3790 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
3791 flags |= GFP_DMA;
3792 else
3793 flags |= GFP_DMA32;
3794 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003795
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003796 if (gfpflags_allow_blocking(flags)) {
3797 unsigned int count = size >> PAGE_SHIFT;
3798
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003799 page = dma_alloc_from_contiguous(dev, count, order,
3800 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003801 if (page && iommu_no_mapping(dev) &&
3802 page_to_phys(page) + size > dev->coherent_dma_mask) {
3803 dma_release_from_contiguous(dev, page, count);
3804 page = NULL;
3805 }
3806 }
3807
3808 if (!page)
3809 page = alloc_pages(flags, order);
3810 if (!page)
3811 return NULL;
3812 memset(page_address(page), 0, size);
3813
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003814 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3815 DMA_BIDIRECTIONAL,
3816 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003817 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003818 return page_address(page);
3819 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3820 __free_pages(page, order);
3821
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003822 return NULL;
3823}
3824
David Woodhouse5040a912014-03-09 16:14:00 -07003825static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003826 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003827{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003828 int order;
3829 struct page *page = virt_to_page(vaddr);
3830
3831 size = PAGE_ALIGN(size);
3832 order = get_order(size);
3833
3834 intel_unmap(dev, dma_handle, size);
3835 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3836 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003837}
3838
David Woodhouse5040a912014-03-09 16:14:00 -07003839static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003840 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003841 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003842{
Omer Peleg769530e2016-04-20 11:33:25 +03003843 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3844 unsigned long nrpages = 0;
3845 struct scatterlist *sg;
3846 int i;
3847
3848 for_each_sg(sglist, sg, nelems, i) {
3849 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3850 }
3851
3852 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003853}
3854
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003855static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003856 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003857{
3858 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003859 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003860
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003861 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003862 BUG_ON(!sg_page(sg));
Robin Murphy29a90b72017-09-28 15:14:01 +01003863 sg->dma_address = sg_phys(sg);
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003864 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003865 }
3866 return nelems;
3867}
3868
David Woodhouse5040a912014-03-09 16:14:00 -07003869static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003870 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003871{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003872 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003873 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003874 size_t size = 0;
3875 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003876 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003877 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003878 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003879 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003880 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003881
3882 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003883 if (iommu_no_mapping(dev))
3884 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003885
David Woodhouse5040a912014-03-09 16:14:00 -07003886 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003887 if (!domain)
3888 return 0;
3889
Weidong Han8c11e792008-12-08 15:29:22 +08003890 iommu = domain_get_iommu(domain);
3891
David Woodhouseb536d242009-06-28 14:49:31 +01003892 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003893 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003894
Omer Peleg2aac6302016-04-20 11:33:57 +03003895 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003896 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003897 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003898 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003899 return 0;
3900 }
3901
3902 /*
3903 * Check if DMAR supports zero-length reads on write only
3904 * mappings..
3905 */
3906 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003907 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003908 prot |= DMA_PTE_READ;
3909 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3910 prot |= DMA_PTE_WRITE;
3911
Omer Peleg2aac6302016-04-20 11:33:57 +03003912 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003913
Fenghua Yuf5329592009-08-04 15:09:37 -07003914 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003915 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003916 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003917 start_vpfn + size - 1,
3918 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003919 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003920 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003921 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003922
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003923 return nelems;
3924}
3925
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003926static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003927 .alloc = intel_alloc_coherent,
3928 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003929 .map_sg = intel_map_sg,
3930 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003931 .map_page = intel_map_page,
3932 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003933 .map_resource = intel_map_resource,
3934 .unmap_resource = intel_unmap_page,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003935 .dma_supported = dma_direct_supported,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003936};
3937
3938static inline int iommu_domain_cache_init(void)
3939{
3940 int ret = 0;
3941
3942 iommu_domain_cache = kmem_cache_create("iommu_domain",
3943 sizeof(struct dmar_domain),
3944 0,
3945 SLAB_HWCACHE_ALIGN,
3946
3947 NULL);
3948 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003949 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003950 ret = -ENOMEM;
3951 }
3952
3953 return ret;
3954}
3955
3956static inline int iommu_devinfo_cache_init(void)
3957{
3958 int ret = 0;
3959
3960 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3961 sizeof(struct device_domain_info),
3962 0,
3963 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003964 NULL);
3965 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003966 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003967 ret = -ENOMEM;
3968 }
3969
3970 return ret;
3971}
3972
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003973static int __init iommu_init_mempool(void)
3974{
3975 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003976 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003977 if (ret)
3978 return ret;
3979
3980 ret = iommu_domain_cache_init();
3981 if (ret)
3982 goto domain_error;
3983
3984 ret = iommu_devinfo_cache_init();
3985 if (!ret)
3986 return ret;
3987
3988 kmem_cache_destroy(iommu_domain_cache);
3989domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003990 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003991
3992 return -ENOMEM;
3993}
3994
3995static void __init iommu_exit_mempool(void)
3996{
3997 kmem_cache_destroy(iommu_devinfo_cache);
3998 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003999 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004000}
4001
Dan Williams556ab452010-07-23 15:47:56 -07004002static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
4003{
4004 struct dmar_drhd_unit *drhd;
4005 u32 vtbar;
4006 int rc;
4007
4008 /* We know that this device on this chipset has its own IOMMU.
4009 * If we find it under a different IOMMU, then the BIOS is lying
4010 * to us. Hope that the IOMMU for this device is actually
4011 * disabled, and it needs no translation...
4012 */
4013 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
4014 if (rc) {
4015 /* "can't" happen */
4016 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
4017 return;
4018 }
4019 vtbar &= 0xffff0000;
4020
4021 /* we know that the this iommu should be at offset 0xa000 from vtbar */
4022 drhd = dmar_find_matched_drhd_unit(pdev);
4023 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
4024 TAINT_FIRMWARE_WORKAROUND,
4025 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
4026 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
4027}
4028DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
4029
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004030static void __init init_no_remapping_devices(void)
4031{
4032 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004033 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004034 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004035
4036 for_each_drhd_unit(drhd) {
4037 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004038 for_each_active_dev_scope(drhd->devices,
4039 drhd->devices_cnt, i, dev)
4040 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004041 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004042 if (i == drhd->devices_cnt)
4043 drhd->ignored = 1;
4044 }
4045 }
4046
Jiang Liu7c919772014-01-06 14:18:18 +08004047 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004048 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004049 continue;
4050
Jiang Liub683b232014-02-19 14:07:32 +08004051 for_each_active_dev_scope(drhd->devices,
4052 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004053 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004054 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004055 if (i < drhd->devices_cnt)
4056 continue;
4057
David Woodhousec0771df2011-10-14 20:59:46 +01004058 /* This IOMMU has *only* gfx devices. Either bypass it or
4059 set the gfx_mapped flag, as appropriate */
4060 if (dmar_map_gfx) {
4061 intel_iommu_gfx_mapped = 1;
4062 } else {
4063 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08004064 for_each_active_dev_scope(drhd->devices,
4065 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004066 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004067 }
4068 }
4069}
4070
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004071#ifdef CONFIG_SUSPEND
4072static int init_iommu_hw(void)
4073{
4074 struct dmar_drhd_unit *drhd;
4075 struct intel_iommu *iommu = NULL;
4076
4077 for_each_active_iommu(iommu, drhd)
4078 if (iommu->qi)
4079 dmar_reenable_qi(iommu);
4080
Joseph Cihulab7792602011-05-03 00:08:37 -07004081 for_each_iommu(iommu, drhd) {
4082 if (drhd->ignored) {
4083 /*
4084 * we always have to disable PMRs or DMA may fail on
4085 * this device
4086 */
4087 if (force_on)
4088 iommu_disable_protect_mem_regions(iommu);
4089 continue;
4090 }
4091
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004092 iommu_flush_write_buffer(iommu);
4093
4094 iommu_set_root_entry(iommu);
4095
4096 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004097 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004098 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4099 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004100 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004101 }
4102
4103 return 0;
4104}
4105
4106static void iommu_flush_all(void)
4107{
4108 struct dmar_drhd_unit *drhd;
4109 struct intel_iommu *iommu;
4110
4111 for_each_active_iommu(iommu, drhd) {
4112 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004113 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004114 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004115 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004116 }
4117}
4118
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004119static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004120{
4121 struct dmar_drhd_unit *drhd;
4122 struct intel_iommu *iommu = NULL;
4123 unsigned long flag;
4124
4125 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004126 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004127 GFP_ATOMIC);
4128 if (!iommu->iommu_state)
4129 goto nomem;
4130 }
4131
4132 iommu_flush_all();
4133
4134 for_each_active_iommu(iommu, drhd) {
4135 iommu_disable_translation(iommu);
4136
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004137 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004138
4139 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4140 readl(iommu->reg + DMAR_FECTL_REG);
4141 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4142 readl(iommu->reg + DMAR_FEDATA_REG);
4143 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4144 readl(iommu->reg + DMAR_FEADDR_REG);
4145 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4146 readl(iommu->reg + DMAR_FEUADDR_REG);
4147
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004148 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004149 }
4150 return 0;
4151
4152nomem:
4153 for_each_active_iommu(iommu, drhd)
4154 kfree(iommu->iommu_state);
4155
4156 return -ENOMEM;
4157}
4158
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004159static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004160{
4161 struct dmar_drhd_unit *drhd;
4162 struct intel_iommu *iommu = NULL;
4163 unsigned long flag;
4164
4165 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004166 if (force_on)
4167 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4168 else
4169 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004170 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004171 }
4172
4173 for_each_active_iommu(iommu, drhd) {
4174
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004175 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004176
4177 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4178 iommu->reg + DMAR_FECTL_REG);
4179 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4180 iommu->reg + DMAR_FEDATA_REG);
4181 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4182 iommu->reg + DMAR_FEADDR_REG);
4183 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4184 iommu->reg + DMAR_FEUADDR_REG);
4185
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004186 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004187 }
4188
4189 for_each_active_iommu(iommu, drhd)
4190 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004191}
4192
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004193static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004194 .resume = iommu_resume,
4195 .suspend = iommu_suspend,
4196};
4197
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004198static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004199{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004200 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004201}
4202
4203#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004204static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004205#endif /* CONFIG_PM */
4206
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004207
Jiang Liuc2a0b532014-11-09 22:47:56 +08004208int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004209{
4210 struct acpi_dmar_reserved_memory *rmrr;
Eric Auger0659b8d2017-01-19 20:57:53 +00004211 int prot = DMA_PTE_READ|DMA_PTE_WRITE;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004212 struct dmar_rmrr_unit *rmrru;
Eric Auger0659b8d2017-01-19 20:57:53 +00004213 size_t length;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004214
4215 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4216 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004217 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004218
4219 rmrru->hdr = header;
4220 rmrr = (struct acpi_dmar_reserved_memory *)header;
4221 rmrru->base_address = rmrr->base_address;
4222 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004223
4224 length = rmrr->end_address - rmrr->base_address + 1;
4225 rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
4226 IOMMU_RESV_DIRECT);
4227 if (!rmrru->resv)
4228 goto free_rmrru;
4229
Jiang Liu2e455282014-02-19 14:07:36 +08004230 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4231 ((void *)rmrr) + rmrr->header.length,
4232 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004233 if (rmrru->devices_cnt && rmrru->devices == NULL)
4234 goto free_all;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004235
Jiang Liu2e455282014-02-19 14:07:36 +08004236 list_add(&rmrru->list, &dmar_rmrr_units);
4237
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004238 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004239free_all:
4240 kfree(rmrru->resv);
4241free_rmrru:
4242 kfree(rmrru);
4243out:
4244 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004245}
4246
Jiang Liu6b197242014-11-09 22:47:58 +08004247static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4248{
4249 struct dmar_atsr_unit *atsru;
4250 struct acpi_dmar_atsr *tmp;
4251
4252 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4253 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4254 if (atsr->segment != tmp->segment)
4255 continue;
4256 if (atsr->header.length != tmp->header.length)
4257 continue;
4258 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4259 return atsru;
4260 }
4261
4262 return NULL;
4263}
4264
4265int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004266{
4267 struct acpi_dmar_atsr *atsr;
4268 struct dmar_atsr_unit *atsru;
4269
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004270 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004271 return 0;
4272
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004273 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004274 atsru = dmar_find_atsr(atsr);
4275 if (atsru)
4276 return 0;
4277
4278 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004279 if (!atsru)
4280 return -ENOMEM;
4281
Jiang Liu6b197242014-11-09 22:47:58 +08004282 /*
4283 * If memory is allocated from slab by ACPI _DSM method, we need to
4284 * copy the memory content because the memory buffer will be freed
4285 * on return.
4286 */
4287 atsru->hdr = (void *)(atsru + 1);
4288 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004289 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004290 if (!atsru->include_all) {
4291 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4292 (void *)atsr + atsr->header.length,
4293 &atsru->devices_cnt);
4294 if (atsru->devices_cnt && atsru->devices == NULL) {
4295 kfree(atsru);
4296 return -ENOMEM;
4297 }
4298 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004299
Jiang Liu0e242612014-02-19 14:07:34 +08004300 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004301
4302 return 0;
4303}
4304
Jiang Liu9bdc5312014-01-06 14:18:27 +08004305static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4306{
4307 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4308 kfree(atsru);
4309}
4310
Jiang Liu6b197242014-11-09 22:47:58 +08004311int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4312{
4313 struct acpi_dmar_atsr *atsr;
4314 struct dmar_atsr_unit *atsru;
4315
4316 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4317 atsru = dmar_find_atsr(atsr);
4318 if (atsru) {
4319 list_del_rcu(&atsru->list);
4320 synchronize_rcu();
4321 intel_iommu_free_atsr(atsru);
4322 }
4323
4324 return 0;
4325}
4326
4327int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4328{
4329 int i;
4330 struct device *dev;
4331 struct acpi_dmar_atsr *atsr;
4332 struct dmar_atsr_unit *atsru;
4333
4334 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4335 atsru = dmar_find_atsr(atsr);
4336 if (!atsru)
4337 return 0;
4338
Linus Torvalds194dc872016-07-27 20:03:31 -07004339 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004340 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4341 i, dev)
4342 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004343 }
Jiang Liu6b197242014-11-09 22:47:58 +08004344
4345 return 0;
4346}
4347
Jiang Liuffebeb42014-11-09 22:48:02 +08004348static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4349{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004350 int sp, ret;
Jiang Liuffebeb42014-11-09 22:48:02 +08004351 struct intel_iommu *iommu = dmaru->iommu;
4352
4353 if (g_iommus[iommu->seq_id])
4354 return 0;
4355
4356 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004357 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004358 iommu->name);
4359 return -ENXIO;
4360 }
4361 if (!ecap_sc_support(iommu->ecap) &&
4362 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004363 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004364 iommu->name);
4365 return -ENXIO;
4366 }
4367 sp = domain_update_iommu_superpage(iommu) - 1;
4368 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004369 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004370 iommu->name);
4371 return -ENXIO;
4372 }
4373
4374 /*
4375 * Disable translation if already enabled prior to OS handover.
4376 */
4377 if (iommu->gcmd & DMA_GCMD_TE)
4378 iommu_disable_translation(iommu);
4379
4380 g_iommus[iommu->seq_id] = iommu;
4381 ret = iommu_init_domains(iommu);
4382 if (ret == 0)
4383 ret = iommu_alloc_root_entry(iommu);
4384 if (ret)
4385 goto out;
4386
David Woodhouse8a94ade2015-03-24 14:54:56 +00004387#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004388 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08004389 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004390#endif
4391
Jiang Liuffebeb42014-11-09 22:48:02 +08004392 if (dmaru->ignored) {
4393 /*
4394 * we always have to disable PMRs or DMA may fail on this device
4395 */
4396 if (force_on)
4397 iommu_disable_protect_mem_regions(iommu);
4398 return 0;
4399 }
4400
4401 intel_iommu_init_qi(iommu);
4402 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004403
4404#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004405 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004406 ret = intel_svm_enable_prq(iommu);
4407 if (ret)
4408 goto disable_iommu;
4409 }
4410#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004411 ret = dmar_set_interrupt(iommu);
4412 if (ret)
4413 goto disable_iommu;
4414
4415 iommu_set_root_entry(iommu);
4416 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4417 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4418 iommu_enable_translation(iommu);
4419
Jiang Liuffebeb42014-11-09 22:48:02 +08004420 iommu_disable_protect_mem_regions(iommu);
4421 return 0;
4422
4423disable_iommu:
4424 disable_dmar_iommu(iommu);
4425out:
4426 free_dmar_iommu(iommu);
4427 return ret;
4428}
4429
Jiang Liu6b197242014-11-09 22:47:58 +08004430int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4431{
Jiang Liuffebeb42014-11-09 22:48:02 +08004432 int ret = 0;
4433 struct intel_iommu *iommu = dmaru->iommu;
4434
4435 if (!intel_iommu_enabled)
4436 return 0;
4437 if (iommu == NULL)
4438 return -EINVAL;
4439
4440 if (insert) {
4441 ret = intel_iommu_add(dmaru);
4442 } else {
4443 disable_dmar_iommu(iommu);
4444 free_dmar_iommu(iommu);
4445 }
4446
4447 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004448}
4449
Jiang Liu9bdc5312014-01-06 14:18:27 +08004450static void intel_iommu_free_dmars(void)
4451{
4452 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4453 struct dmar_atsr_unit *atsru, *atsr_n;
4454
4455 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4456 list_del(&rmrru->list);
4457 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004458 kfree(rmrru->resv);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004459 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004460 }
4461
Jiang Liu9bdc5312014-01-06 14:18:27 +08004462 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4463 list_del(&atsru->list);
4464 intel_iommu_free_atsr(atsru);
4465 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004466}
4467
4468int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4469{
Jiang Liub683b232014-02-19 14:07:32 +08004470 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004471 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004472 struct pci_dev *bridge = NULL;
4473 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004474 struct acpi_dmar_atsr *atsr;
4475 struct dmar_atsr_unit *atsru;
4476
4477 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004478 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004479 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004480 /* If it's an integrated device, allow ATS */
4481 if (!bridge)
4482 return 1;
4483 /* Connected via non-PCIe: no ATS */
4484 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004485 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004486 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004487 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004488 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004489 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004490 }
4491
Jiang Liu0e242612014-02-19 14:07:34 +08004492 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004493 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4494 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4495 if (atsr->segment != pci_domain_nr(dev->bus))
4496 continue;
4497
Jiang Liub683b232014-02-19 14:07:32 +08004498 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004499 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004500 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004501
4502 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004503 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004504 }
Jiang Liub683b232014-02-19 14:07:32 +08004505 ret = 0;
4506out:
Jiang Liu0e242612014-02-19 14:07:34 +08004507 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004508
Jiang Liub683b232014-02-19 14:07:32 +08004509 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004510}
4511
Jiang Liu59ce0512014-02-19 14:07:35 +08004512int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4513{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004514 int ret;
Jiang Liu59ce0512014-02-19 14:07:35 +08004515 struct dmar_rmrr_unit *rmrru;
4516 struct dmar_atsr_unit *atsru;
4517 struct acpi_dmar_atsr *atsr;
4518 struct acpi_dmar_reserved_memory *rmrr;
4519
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004520 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004521 return 0;
4522
4523 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4524 rmrr = container_of(rmrru->hdr,
4525 struct acpi_dmar_reserved_memory, header);
4526 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4527 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4528 ((void *)rmrr) + rmrr->header.length,
4529 rmrr->segment, rmrru->devices,
4530 rmrru->devices_cnt);
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004531 if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004532 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004533 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004534 dmar_remove_dev_scope(info, rmrr->segment,
4535 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004536 }
4537 }
4538
4539 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4540 if (atsru->include_all)
4541 continue;
4542
4543 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4544 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4545 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4546 (void *)atsr + atsr->header.length,
4547 atsr->segment, atsru->devices,
4548 atsru->devices_cnt);
4549 if (ret > 0)
4550 break;
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004551 else if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004552 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004553 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004554 if (dmar_remove_dev_scope(info, atsr->segment,
4555 atsru->devices, atsru->devices_cnt))
4556 break;
4557 }
4558 }
4559
4560 return 0;
4561}
4562
Fenghua Yu99dcade2009-11-11 07:23:06 -08004563/*
4564 * Here we only respond to action of unbound device from driver.
4565 *
4566 * Added device is not attached to its DMAR domain here yet. That will happen
4567 * when mapping the device to iova.
4568 */
4569static int device_notifier(struct notifier_block *nb,
4570 unsigned long action, void *data)
4571{
4572 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004573 struct dmar_domain *domain;
4574
David Woodhouse3d891942014-03-06 15:59:26 +00004575 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004576 return 0;
4577
Lu Baolu117266f2019-02-25 10:46:36 +08004578 if (action == BUS_NOTIFY_REMOVED_DEVICE) {
4579 domain = find_domain(dev);
4580 if (!domain)
4581 return 0;
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004582
Lu Baolu117266f2019-02-25 10:46:36 +08004583 dmar_remove_one_dev_info(dev);
4584 if (!domain_type_is_vm_or_si(domain) &&
4585 list_empty(&domain->devices))
4586 domain_exit(domain);
4587 } else if (action == BUS_NOTIFY_ADD_DEVICE) {
4588 if (iommu_should_identity_map(dev, 1))
4589 domain_add_dev_info(si_domain, dev);
4590 }
Alex Williamsona97590e2011-03-04 14:52:16 -07004591
Fenghua Yu99dcade2009-11-11 07:23:06 -08004592 return 0;
4593}
4594
4595static struct notifier_block device_nb = {
4596 .notifier_call = device_notifier,
4597};
4598
Jiang Liu75f05562014-02-19 14:07:37 +08004599static int intel_iommu_memory_notifier(struct notifier_block *nb,
4600 unsigned long val, void *v)
4601{
4602 struct memory_notify *mhp = v;
4603 unsigned long long start, end;
4604 unsigned long start_vpfn, last_vpfn;
4605
4606 switch (val) {
4607 case MEM_GOING_ONLINE:
4608 start = mhp->start_pfn << PAGE_SHIFT;
4609 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4610 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004611 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004612 start, end);
4613 return NOTIFY_BAD;
4614 }
4615 break;
4616
4617 case MEM_OFFLINE:
4618 case MEM_CANCEL_ONLINE:
4619 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4620 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4621 while (start_vpfn <= last_vpfn) {
4622 struct iova *iova;
4623 struct dmar_drhd_unit *drhd;
4624 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004625 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004626
4627 iova = find_iova(&si_domain->iovad, start_vpfn);
4628 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004629 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004630 start_vpfn);
4631 break;
4632 }
4633
4634 iova = split_and_remove_iova(&si_domain->iovad, iova,
4635 start_vpfn, last_vpfn);
4636 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004637 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004638 start_vpfn, last_vpfn);
4639 return NOTIFY_BAD;
4640 }
4641
David Woodhouseea8ea462014-03-05 17:09:32 +00004642 freelist = domain_unmap(si_domain, iova->pfn_lo,
4643 iova->pfn_hi);
4644
Jiang Liu75f05562014-02-19 14:07:37 +08004645 rcu_read_lock();
4646 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004647 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004648 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004649 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004650 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004651 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004652
4653 start_vpfn = iova->pfn_hi + 1;
4654 free_iova_mem(iova);
4655 }
4656 break;
4657 }
4658
4659 return NOTIFY_OK;
4660}
4661
4662static struct notifier_block intel_iommu_memory_nb = {
4663 .notifier_call = intel_iommu_memory_notifier,
4664 .priority = 0
4665};
4666
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004667static void free_all_cpu_cached_iovas(unsigned int cpu)
4668{
4669 int i;
4670
4671 for (i = 0; i < g_num_of_iommus; i++) {
4672 struct intel_iommu *iommu = g_iommus[i];
4673 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004674 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004675
4676 if (!iommu)
4677 continue;
4678
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004679 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004680 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004681
4682 if (!domain)
4683 continue;
4684 free_cpu_cached_iovas(cpu, &domain->iovad);
4685 }
4686 }
4687}
4688
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004689static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004690{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004691 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004692 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004693}
4694
Joerg Roedel161b28a2017-03-28 17:04:52 +02004695static void intel_disable_iommus(void)
4696{
4697 struct intel_iommu *iommu = NULL;
4698 struct dmar_drhd_unit *drhd;
4699
4700 for_each_iommu(iommu, drhd)
4701 iommu_disable_translation(iommu);
4702}
4703
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004704static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4705{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004706 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4707
4708 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004709}
4710
Alex Williamsona5459cf2014-06-12 16:12:31 -06004711static ssize_t intel_iommu_show_version(struct device *dev,
4712 struct device_attribute *attr,
4713 char *buf)
4714{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004715 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004716 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4717 return sprintf(buf, "%d:%d\n",
4718 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4719}
4720static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4721
4722static ssize_t intel_iommu_show_address(struct device *dev,
4723 struct device_attribute *attr,
4724 char *buf)
4725{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004726 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004727 return sprintf(buf, "%llx\n", iommu->reg_phys);
4728}
4729static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4730
4731static ssize_t intel_iommu_show_cap(struct device *dev,
4732 struct device_attribute *attr,
4733 char *buf)
4734{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004735 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004736 return sprintf(buf, "%llx\n", iommu->cap);
4737}
4738static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4739
4740static ssize_t intel_iommu_show_ecap(struct device *dev,
4741 struct device_attribute *attr,
4742 char *buf)
4743{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004744 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004745 return sprintf(buf, "%llx\n", iommu->ecap);
4746}
4747static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4748
Alex Williamson2238c082015-07-14 15:24:53 -06004749static ssize_t intel_iommu_show_ndoms(struct device *dev,
4750 struct device_attribute *attr,
4751 char *buf)
4752{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004753 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004754 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4755}
4756static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4757
4758static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4759 struct device_attribute *attr,
4760 char *buf)
4761{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004762 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004763 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4764 cap_ndoms(iommu->cap)));
4765}
4766static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4767
Alex Williamsona5459cf2014-06-12 16:12:31 -06004768static struct attribute *intel_iommu_attrs[] = {
4769 &dev_attr_version.attr,
4770 &dev_attr_address.attr,
4771 &dev_attr_cap.attr,
4772 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004773 &dev_attr_domains_supported.attr,
4774 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004775 NULL,
4776};
4777
4778static struct attribute_group intel_iommu_group = {
4779 .name = "intel-iommu",
4780 .attrs = intel_iommu_attrs,
4781};
4782
4783const struct attribute_group *intel_iommu_groups[] = {
4784 &intel_iommu_group,
4785 NULL,
4786};
4787
Lu Baolu89a60792018-10-23 15:45:01 +08004788static int __init platform_optin_force_iommu(void)
4789{
4790 struct pci_dev *pdev = NULL;
4791 bool has_untrusted_dev = false;
4792
4793 if (!dmar_platform_optin() || no_platform_optin)
4794 return 0;
4795
4796 for_each_pci_dev(pdev) {
4797 if (pdev->untrusted) {
4798 has_untrusted_dev = true;
4799 break;
4800 }
4801 }
4802
4803 if (!has_untrusted_dev)
4804 return 0;
4805
4806 if (no_iommu || dmar_disabled)
4807 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4808
4809 /*
4810 * If Intel-IOMMU is disabled by default, we will apply identity
4811 * map for all devices except those marked as being untrusted.
4812 */
4813 if (dmar_disabled)
4814 iommu_identity_mapping |= IDENTMAP_ALL;
4815
4816 dmar_disabled = 0;
4817#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
4818 swiotlb = 0;
4819#endif
4820 no_iommu = 0;
4821
4822 return 1;
4823}
4824
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004825int __init intel_iommu_init(void)
4826{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004827 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004828 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004829 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004830
Lu Baolu89a60792018-10-23 15:45:01 +08004831 /*
4832 * Intel IOMMU is required for a TXT/tboot launch or platform
4833 * opt in, so enforce that.
4834 */
4835 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004836
Jiang Liu3a5670e2014-02-19 14:07:33 +08004837 if (iommu_init_mempool()) {
4838 if (force_on)
4839 panic("tboot: Failed to initialize iommu memory\n");
4840 return -ENOMEM;
4841 }
4842
4843 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004844 if (dmar_table_init()) {
4845 if (force_on)
4846 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004847 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004848 }
4849
Suresh Siddhac2c72862011-08-23 17:05:19 -07004850 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004851 if (force_on)
4852 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004853 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004854 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004855
Joerg Roedelec154bf2017-10-06 15:00:53 +02004856 up_write(&dmar_global_lock);
4857
4858 /*
4859 * The bus notifier takes the dmar_global_lock, so lockdep will
4860 * complain later when we register it under the lock.
4861 */
4862 dmar_register_bus_notifier();
4863
4864 down_write(&dmar_global_lock);
4865
Joerg Roedel161b28a2017-03-28 17:04:52 +02004866 if (no_iommu || dmar_disabled) {
4867 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004868 * We exit the function here to ensure IOMMU's remapping and
4869 * mempool aren't setup, which means that the IOMMU's PMRs
4870 * won't be disabled via the call to init_dmars(). So disable
4871 * it explicitly here. The PMRs were setup by tboot prior to
4872 * calling SENTER, but the kernel is expected to reset/tear
4873 * down the PMRs.
4874 */
4875 if (intel_iommu_tboot_noforce) {
4876 for_each_iommu(iommu, drhd)
4877 iommu_disable_protect_mem_regions(iommu);
4878 }
4879
4880 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004881 * Make sure the IOMMUs are switched off, even when we
4882 * boot into a kexec kernel and the previous kernel left
4883 * them enabled
4884 */
4885 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004886 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004887 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004888
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004889 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004890 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004891
4892 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004893 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004894
Joseph Cihula51a63e62011-03-21 11:04:24 -07004895 if (dmar_init_reserved_ranges()) {
4896 if (force_on)
4897 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004898 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004899 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004900
4901 init_no_remapping_devices();
4902
Joseph Cihulab7792602011-05-03 00:08:37 -07004903 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004904 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004905 if (force_on)
4906 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004907 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004908 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004909 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004910 up_write(&dmar_global_lock);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004911 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004912
Christoph Hellwig4fac8072017-12-24 13:57:08 +01004913#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004914 swiotlb = 0;
4915#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004916 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004917
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004918 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004919
Joerg Roedel39ab9552017-02-01 16:56:46 +01004920 for_each_active_iommu(iommu, drhd) {
4921 iommu_device_sysfs_add(&iommu->iommu, NULL,
4922 intel_iommu_groups,
4923 "%s", iommu->name);
4924 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4925 iommu_device_register(&iommu->iommu);
4926 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06004927
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004928 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004929 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004930 if (si_domain && !hw_pass_through)
4931 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004932 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4933 intel_iommu_cpu_dead);
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004934 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07004935 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004936
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004937 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004938
4939out_free_reserved_range:
4940 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004941out_free_dmar:
4942 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004943 up_write(&dmar_global_lock);
4944 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004945 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004946}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004947
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004948static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004949{
4950 struct intel_iommu *iommu = opaque;
4951
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004952 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004953 return 0;
4954}
4955
4956/*
4957 * NB - intel-iommu lacks any sort of reference counting for the users of
4958 * dependent devices. If multiple endpoints have intersecting dependent
4959 * devices, unbinding the driver from any one of them will possibly leave
4960 * the others unable to operate.
4961 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004962static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004963{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004964 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004965 return;
4966
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004967 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004968}
4969
Joerg Roedel127c7612015-07-23 17:44:46 +02004970static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004971{
Weidong Hanc7151a82008-12-08 22:51:37 +08004972 struct intel_iommu *iommu;
4973 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004974
Joerg Roedel55d94042015-07-22 16:50:40 +02004975 assert_spin_locked(&device_domain_lock);
4976
Joerg Roedelb608ac32015-07-21 18:19:08 +02004977 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004978 return;
4979
Joerg Roedel127c7612015-07-23 17:44:46 +02004980 iommu = info->iommu;
4981
4982 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08004983 if (dev_is_pci(info->dev) && sm_supported(iommu))
4984 intel_pasid_tear_down_entry(iommu, info->dev,
4985 PASID_RID2PASID);
4986
Joerg Roedel127c7612015-07-23 17:44:46 +02004987 iommu_disable_dev_iotlb(info);
4988 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08004989 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02004990 }
4991
Joerg Roedelb608ac32015-07-21 18:19:08 +02004992 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004993
Joerg Roedeld160aca2015-07-22 11:52:53 +02004994 spin_lock_irqsave(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004995 domain_detach_iommu(info->domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004996 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004997
4998 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004999}
5000
Bjorn Helgaas71753232019-02-08 16:06:15 -06005001static void dmar_remove_one_dev_info(struct device *dev)
Joerg Roedel55d94042015-07-22 16:50:40 +02005002{
Joerg Roedel127c7612015-07-23 17:44:46 +02005003 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02005004 unsigned long flags;
5005
Weidong Hanc7151a82008-12-08 22:51:37 +08005006 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005007 info = dev->archdata.iommu;
5008 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005009 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005010}
5011
5012static int md_domain_init(struct dmar_domain *domain, int guest_width)
5013{
5014 int adjust_width;
5015
Zhen Leiaa3ac942017-09-21 16:52:45 +01005016 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005017 domain_reserve_special_ranges(domain);
5018
5019 /* calculate AGAW */
5020 domain->gaw = guest_width;
5021 adjust_width = guestwidth_to_adjustwidth(guest_width);
5022 domain->agaw = width_to_agaw(adjust_width);
5023
Weidong Han5e98c4b2008-12-08 23:03:27 +08005024 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08005025 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01005026 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005027 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08005028
5029 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07005030 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005031 if (!domain->pgd)
5032 return -ENOMEM;
5033 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5034 return 0;
5035}
5036
Joerg Roedel00a77de2015-03-26 13:43:08 +01005037static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005038{
Joerg Roedel5d450802008-12-03 14:52:32 +01005039 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005040 struct iommu_domain *domain;
5041
5042 if (type != IOMMU_DOMAIN_UNMANAGED)
5043 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005044
Jiang Liuab8dfe22014-07-11 14:19:27 +08005045 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01005046 if (!dmar_domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005047 pr_err("Can't allocate dmar_domain\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01005048 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005049 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07005050 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005051 pr_err("Domain initialization failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08005052 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01005053 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005054 }
Allen Kay8140a952011-10-14 12:32:17 -07005055 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005056
Joerg Roedel00a77de2015-03-26 13:43:08 +01005057 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01005058 domain->geometry.aperture_start = 0;
5059 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5060 domain->geometry.force_aperture = true;
5061
Joerg Roedel00a77de2015-03-26 13:43:08 +01005062 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03005063}
Kay, Allen M38717942008-09-09 18:37:29 +03005064
Joerg Roedel00a77de2015-03-26 13:43:08 +01005065static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005066{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005067 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005068}
Kay, Allen M38717942008-09-09 18:37:29 +03005069
Lu Baolu67b8e022019-03-25 09:30:32 +08005070/*
5071 * Check whether a @domain could be attached to the @dev through the
5072 * aux-domain attach/detach APIs.
5073 */
5074static inline bool
5075is_aux_domain(struct device *dev, struct iommu_domain *domain)
5076{
5077 struct device_domain_info *info = dev->archdata.iommu;
5078
5079 return info && info->auxd_enabled &&
5080 domain->type == IOMMU_DOMAIN_UNMANAGED;
5081}
5082
5083static void auxiliary_link_device(struct dmar_domain *domain,
5084 struct device *dev)
5085{
5086 struct device_domain_info *info = dev->archdata.iommu;
5087
5088 assert_spin_locked(&device_domain_lock);
5089 if (WARN_ON(!info))
5090 return;
5091
5092 domain->auxd_refcnt++;
5093 list_add(&domain->auxd, &info->auxiliary_domains);
5094}
5095
5096static void auxiliary_unlink_device(struct dmar_domain *domain,
5097 struct device *dev)
5098{
5099 struct device_domain_info *info = dev->archdata.iommu;
5100
5101 assert_spin_locked(&device_domain_lock);
5102 if (WARN_ON(!info))
5103 return;
5104
5105 list_del(&domain->auxd);
5106 domain->auxd_refcnt--;
5107
5108 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5109 intel_pasid_free_id(domain->default_pasid);
5110}
5111
5112static int aux_domain_add_dev(struct dmar_domain *domain,
5113 struct device *dev)
5114{
5115 int ret;
5116 u8 bus, devfn;
5117 unsigned long flags;
5118 struct intel_iommu *iommu;
5119
5120 iommu = device_to_iommu(dev, &bus, &devfn);
5121 if (!iommu)
5122 return -ENODEV;
5123
5124 if (domain->default_pasid <= 0) {
5125 int pasid;
5126
5127 pasid = intel_pasid_alloc_id(domain, PASID_MIN,
5128 pci_max_pasids(to_pci_dev(dev)),
5129 GFP_KERNEL);
5130 if (pasid <= 0) {
5131 pr_err("Can't allocate default pasid\n");
5132 return -ENODEV;
5133 }
5134 domain->default_pasid = pasid;
5135 }
5136
5137 spin_lock_irqsave(&device_domain_lock, flags);
5138 /*
5139 * iommu->lock must be held to attach domain to iommu and setup the
5140 * pasid entry for second level translation.
5141 */
5142 spin_lock(&iommu->lock);
5143 ret = domain_attach_iommu(domain, iommu);
5144 if (ret)
5145 goto attach_failed;
5146
5147 /* Setup the PASID entry for mediated devices: */
5148 ret = intel_pasid_setup_second_level(iommu, domain, dev,
5149 domain->default_pasid);
5150 if (ret)
5151 goto table_failed;
5152 spin_unlock(&iommu->lock);
5153
5154 auxiliary_link_device(domain, dev);
5155
5156 spin_unlock_irqrestore(&device_domain_lock, flags);
5157
5158 return 0;
5159
5160table_failed:
5161 domain_detach_iommu(domain, iommu);
5162attach_failed:
5163 spin_unlock(&iommu->lock);
5164 spin_unlock_irqrestore(&device_domain_lock, flags);
5165 if (!domain->auxd_refcnt && domain->default_pasid > 0)
5166 intel_pasid_free_id(domain->default_pasid);
5167
5168 return ret;
5169}
5170
5171static void aux_domain_remove_dev(struct dmar_domain *domain,
5172 struct device *dev)
5173{
5174 struct device_domain_info *info;
5175 struct intel_iommu *iommu;
5176 unsigned long flags;
5177
5178 if (!is_aux_domain(dev, &domain->domain))
5179 return;
5180
5181 spin_lock_irqsave(&device_domain_lock, flags);
5182 info = dev->archdata.iommu;
5183 iommu = info->iommu;
5184
5185 auxiliary_unlink_device(domain, dev);
5186
5187 spin_lock(&iommu->lock);
5188 intel_pasid_tear_down_entry(iommu, dev, domain->default_pasid);
5189 domain_detach_iommu(domain, iommu);
5190 spin_unlock(&iommu->lock);
5191
5192 spin_unlock_irqrestore(&device_domain_lock, flags);
5193}
5194
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005195static int prepare_domain_attach_device(struct iommu_domain *domain,
5196 struct device *dev)
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 struct intel_iommu *iommu;
5200 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005201 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005202
David Woodhouse156baca2014-03-09 14:00:57 -07005203 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005204 if (!iommu)
5205 return -ENODEV;
5206
5207 /* check if this iommu agaw is sufficient for max mapped address */
5208 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005209 if (addr_width > cap_mgaw(iommu->cap))
5210 addr_width = cap_mgaw(iommu->cap);
5211
5212 if (dmar_domain->max_addr > (1LL << addr_width)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005213 dev_err(dev, "%s: iommu width (%d) is not "
5214 "sufficient for the mapped address (%llx)\n",
5215 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005216 return -EFAULT;
5217 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005218 dmar_domain->gaw = addr_width;
5219
5220 /*
5221 * Knock out extra levels of page tables if necessary
5222 */
5223 while (iommu->agaw < dmar_domain->agaw) {
5224 struct dma_pte *pte;
5225
5226 pte = dmar_domain->pgd;
5227 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005228 dmar_domain->pgd = (struct dma_pte *)
5229 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005230 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005231 }
5232 dmar_domain->agaw--;
5233 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005234
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005235 return 0;
5236}
5237
5238static int intel_iommu_attach_device(struct iommu_domain *domain,
5239 struct device *dev)
5240{
5241 int ret;
5242
5243 if (device_is_rmrr_locked(dev)) {
5244 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5245 return -EPERM;
5246 }
5247
Lu Baolu67b8e022019-03-25 09:30:32 +08005248 if (is_aux_domain(dev, domain))
5249 return -EPERM;
5250
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005251 /* normally dev is not mapped */
5252 if (unlikely(domain_context_mapped(dev))) {
5253 struct dmar_domain *old_domain;
5254
5255 old_domain = find_domain(dev);
5256 if (old_domain) {
5257 rcu_read_lock();
5258 dmar_remove_one_dev_info(dev);
5259 rcu_read_unlock();
5260
5261 if (!domain_type_is_vm_or_si(old_domain) &&
5262 list_empty(&old_domain->devices))
5263 domain_exit(old_domain);
5264 }
5265 }
5266
5267 ret = prepare_domain_attach_device(domain, dev);
5268 if (ret)
5269 return ret;
5270
5271 return domain_add_dev_info(to_dmar_domain(domain), dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005272}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005273
Lu Baolu67b8e022019-03-25 09:30:32 +08005274static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
5275 struct device *dev)
5276{
5277 int ret;
5278
5279 if (!is_aux_domain(dev, domain))
5280 return -EPERM;
5281
5282 ret = prepare_domain_attach_device(domain, dev);
5283 if (ret)
5284 return ret;
5285
5286 return aux_domain_add_dev(to_dmar_domain(domain), dev);
5287}
5288
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005289static void intel_iommu_detach_device(struct iommu_domain *domain,
5290 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005291{
Bjorn Helgaas71753232019-02-08 16:06:15 -06005292 dmar_remove_one_dev_info(dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005293}
Kay, Allen M38717942008-09-09 18:37:29 +03005294
Lu Baolu67b8e022019-03-25 09:30:32 +08005295static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
5296 struct device *dev)
5297{
5298 aux_domain_remove_dev(to_dmar_domain(domain), dev);
5299}
5300
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005301static int intel_iommu_map(struct iommu_domain *domain,
5302 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005303 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03005304{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005305 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005306 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005307 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005308 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005309
Joerg Roedeldde57a22008-12-03 15:04:09 +01005310 if (iommu_prot & IOMMU_READ)
5311 prot |= DMA_PTE_READ;
5312 if (iommu_prot & IOMMU_WRITE)
5313 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005314 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5315 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005316
David Woodhouse163cc522009-06-28 00:51:17 +01005317 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005318 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005319 u64 end;
5320
5321 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005322 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005323 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005324 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005325 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005326 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005327 return -EFAULT;
5328 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005329 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005330 }
David Woodhousead051222009-06-28 14:22:28 +01005331 /* Round up size to next multiple of PAGE_SIZE, if it and
5332 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005333 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005334 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5335 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005336 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005337}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005338
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005339static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00005340 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005341{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005342 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005343 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005344 unsigned long start_pfn, last_pfn;
5345 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005346 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005347
David Woodhouse5cf0a762014-03-19 16:07:49 +00005348 /* Cope with horrid API which requires us to unmap more than the
5349 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005350 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005351
5352 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5353 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5354
David Woodhouseea8ea462014-03-05 17:09:32 +00005355 start_pfn = iova >> VTD_PAGE_SHIFT;
5356 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5357
5358 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5359
5360 npages = last_pfn - start_pfn + 1;
5361
Shaokun Zhangf746a022018-03-22 18:18:06 +08005362 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005363 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5364 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005365
5366 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005367
David Woodhouse163cc522009-06-28 00:51:17 +01005368 if (dmar_domain->max_addr == iova + size)
5369 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005370
David Woodhouse5cf0a762014-03-19 16:07:49 +00005371 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005372}
Kay, Allen M38717942008-09-09 18:37:29 +03005373
Joerg Roedeld14d6572008-12-03 15:06:57 +01005374static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305375 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005376{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005377 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005378 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005379 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005380 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005381
David Woodhouse5cf0a762014-03-19 16:07:49 +00005382 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005383 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005384 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005385
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005386 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005387}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005388
Lu Baolu95587a72019-03-25 09:30:30 +08005389static inline bool scalable_mode_support(void)
5390{
5391 struct dmar_drhd_unit *drhd;
5392 struct intel_iommu *iommu;
5393 bool ret = true;
5394
5395 rcu_read_lock();
5396 for_each_active_iommu(iommu, drhd) {
5397 if (!sm_supported(iommu)) {
5398 ret = false;
5399 break;
5400 }
5401 }
5402 rcu_read_unlock();
5403
5404 return ret;
5405}
5406
5407static inline bool iommu_pasid_support(void)
5408{
5409 struct dmar_drhd_unit *drhd;
5410 struct intel_iommu *iommu;
5411 bool ret = true;
5412
5413 rcu_read_lock();
5414 for_each_active_iommu(iommu, drhd) {
5415 if (!pasid_supported(iommu)) {
5416 ret = false;
5417 break;
5418 }
5419 }
5420 rcu_read_unlock();
5421
5422 return ret;
5423}
5424
Joerg Roedel5d587b82014-09-05 10:50:45 +02005425static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005426{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005427 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005428 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005429 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005430 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005431
Joerg Roedel5d587b82014-09-05 10:50:45 +02005432 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005433}
5434
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005435static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005436{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005437 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005438 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005439 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005440
Alex Williamsona5459cf2014-06-12 16:12:31 -06005441 iommu = device_to_iommu(dev, &bus, &devfn);
5442 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005443 return -ENODEV;
5444
Joerg Roedele3d10af2017-02-01 17:23:22 +01005445 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005446
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005447 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005448
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005449 if (IS_ERR(group))
5450 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005451
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005452 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005453 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005454}
5455
5456static void intel_iommu_remove_device(struct device *dev)
5457{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005458 struct intel_iommu *iommu;
5459 u8 bus, devfn;
5460
5461 iommu = device_to_iommu(dev, &bus, &devfn);
5462 if (!iommu)
5463 return;
5464
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005465 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005466
Joerg Roedele3d10af2017-02-01 17:23:22 +01005467 iommu_device_unlink(&iommu->iommu, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005468}
5469
Eric Auger0659b8d2017-01-19 20:57:53 +00005470static void intel_iommu_get_resv_regions(struct device *device,
5471 struct list_head *head)
5472{
5473 struct iommu_resv_region *reg;
5474 struct dmar_rmrr_unit *rmrr;
5475 struct device *i_dev;
5476 int i;
5477
5478 rcu_read_lock();
5479 for_each_rmrr_units(rmrr) {
5480 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5481 i, i_dev) {
5482 if (i_dev != device)
5483 continue;
5484
5485 list_add_tail(&rmrr->resv->list, head);
5486 }
5487 }
5488 rcu_read_unlock();
5489
5490 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5491 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005492 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005493 if (!reg)
5494 return;
5495 list_add_tail(&reg->list, head);
5496}
5497
5498static void intel_iommu_put_resv_regions(struct device *dev,
5499 struct list_head *head)
5500{
5501 struct iommu_resv_region *entry, *next;
5502
5503 list_for_each_entry_safe(entry, next, head, list) {
Gerald Schaefer198bc322019-01-16 20:11:44 +01005504 if (entry->type == IOMMU_RESV_MSI)
Eric Auger0659b8d2017-01-19 20:57:53 +00005505 kfree(entry);
5506 }
Kay, Allen M38717942008-09-09 18:37:29 +03005507}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005508
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005509int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005510{
5511 struct device_domain_info *info;
5512 struct context_entry *context;
5513 struct dmar_domain *domain;
5514 unsigned long flags;
5515 u64 ctx_lo;
5516 int ret;
5517
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005518 domain = get_valid_domain_for_dev(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005519 if (!domain)
5520 return -EINVAL;
5521
5522 spin_lock_irqsave(&device_domain_lock, flags);
5523 spin_lock(&iommu->lock);
5524
5525 ret = -EINVAL;
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005526 info = dev->archdata.iommu;
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005527 if (!info || !info->pasid_supported)
5528 goto out;
5529
5530 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5531 if (WARN_ON(!context))
5532 goto out;
5533
5534 ctx_lo = context[0].lo;
5535
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005536 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005537 ctx_lo |= CONTEXT_PASIDE;
5538 context[0].lo = ctx_lo;
5539 wmb();
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005540 iommu->flush.flush_context(iommu,
5541 domain->iommu_did[iommu->seq_id],
5542 PCI_DEVID(info->bus, info->devfn),
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005543 DMA_CCMD_MASK_NOBIT,
5544 DMA_CCMD_DEVICE_INVL);
5545 }
5546
5547 /* Enable PASID support in the device, if it wasn't already */
5548 if (!info->pasid_enabled)
5549 iommu_enable_dev_iotlb(info);
5550
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005551 ret = 0;
5552
5553 out:
5554 spin_unlock(&iommu->lock);
5555 spin_unlock_irqrestore(&device_domain_lock, flags);
5556
5557 return ret;
5558}
5559
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005560#ifdef CONFIG_INTEL_IOMMU_SVM
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005561struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5562{
5563 struct intel_iommu *iommu;
5564 u8 bus, devfn;
5565
5566 if (iommu_dummy(dev)) {
5567 dev_warn(dev,
5568 "No IOMMU translation for device; cannot enable SVM\n");
5569 return NULL;
5570 }
5571
5572 iommu = device_to_iommu(dev, &bus, &devfn);
5573 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07005574 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005575 return NULL;
5576 }
5577
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005578 return iommu;
5579}
5580#endif /* CONFIG_INTEL_IOMMU_SVM */
5581
Lu Baolu95587a72019-03-25 09:30:30 +08005582static int intel_iommu_enable_auxd(struct device *dev)
5583{
5584 struct device_domain_info *info;
5585 struct intel_iommu *iommu;
5586 unsigned long flags;
5587 u8 bus, devfn;
5588 int ret;
5589
5590 iommu = device_to_iommu(dev, &bus, &devfn);
5591 if (!iommu || dmar_disabled)
5592 return -EINVAL;
5593
5594 if (!sm_supported(iommu) || !pasid_supported(iommu))
5595 return -EINVAL;
5596
5597 ret = intel_iommu_enable_pasid(iommu, dev);
5598 if (ret)
5599 return -ENODEV;
5600
5601 spin_lock_irqsave(&device_domain_lock, flags);
5602 info = dev->archdata.iommu;
5603 info->auxd_enabled = 1;
5604 spin_unlock_irqrestore(&device_domain_lock, flags);
5605
5606 return 0;
5607}
5608
5609static int intel_iommu_disable_auxd(struct device *dev)
5610{
5611 struct device_domain_info *info;
5612 unsigned long flags;
5613
5614 spin_lock_irqsave(&device_domain_lock, flags);
5615 info = dev->archdata.iommu;
5616 if (!WARN_ON(!info))
5617 info->auxd_enabled = 0;
5618 spin_unlock_irqrestore(&device_domain_lock, flags);
5619
5620 return 0;
5621}
5622
5623/*
5624 * A PCI express designated vendor specific extended capability is defined
5625 * in the section 3.7 of Intel scalable I/O virtualization technical spec
5626 * for system software and tools to detect endpoint devices supporting the
5627 * Intel scalable IO virtualization without host driver dependency.
5628 *
5629 * Returns the address of the matching extended capability structure within
5630 * the device's PCI configuration space or 0 if the device does not support
5631 * it.
5632 */
5633static int siov_find_pci_dvsec(struct pci_dev *pdev)
5634{
5635 int pos;
5636 u16 vendor, id;
5637
5638 pos = pci_find_next_ext_capability(pdev, 0, 0x23);
5639 while (pos) {
5640 pci_read_config_word(pdev, pos + 4, &vendor);
5641 pci_read_config_word(pdev, pos + 8, &id);
5642 if (vendor == PCI_VENDOR_ID_INTEL && id == 5)
5643 return pos;
5644
5645 pos = pci_find_next_ext_capability(pdev, pos, 0x23);
5646 }
5647
5648 return 0;
5649}
5650
5651static bool
5652intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat)
5653{
5654 if (feat == IOMMU_DEV_FEAT_AUX) {
5655 int ret;
5656
5657 if (!dev_is_pci(dev) || dmar_disabled ||
5658 !scalable_mode_support() || !iommu_pasid_support())
5659 return false;
5660
5661 ret = pci_pasid_features(to_pci_dev(dev));
5662 if (ret < 0)
5663 return false;
5664
5665 return !!siov_find_pci_dvsec(to_pci_dev(dev));
5666 }
5667
5668 return false;
5669}
5670
5671static int
5672intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
5673{
5674 if (feat == IOMMU_DEV_FEAT_AUX)
5675 return intel_iommu_enable_auxd(dev);
5676
5677 return -ENODEV;
5678}
5679
5680static int
5681intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
5682{
5683 if (feat == IOMMU_DEV_FEAT_AUX)
5684 return intel_iommu_disable_auxd(dev);
5685
5686 return -ENODEV;
5687}
5688
5689static bool
5690intel_iommu_dev_feat_enabled(struct device *dev, enum iommu_dev_features feat)
5691{
5692 struct device_domain_info *info = dev->archdata.iommu;
5693
5694 if (feat == IOMMU_DEV_FEAT_AUX)
5695 return scalable_mode_support() && info && info->auxd_enabled;
5696
5697 return false;
5698}
5699
Joerg Roedelb0119e82017-02-01 13:23:08 +01005700const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00005701 .capable = intel_iommu_capable,
5702 .domain_alloc = intel_iommu_domain_alloc,
5703 .domain_free = intel_iommu_domain_free,
5704 .attach_dev = intel_iommu_attach_device,
5705 .detach_dev = intel_iommu_detach_device,
Lu Baolu67b8e022019-03-25 09:30:32 +08005706 .aux_attach_dev = intel_iommu_aux_attach_device,
5707 .aux_detach_dev = intel_iommu_aux_detach_device,
Eric Auger0659b8d2017-01-19 20:57:53 +00005708 .map = intel_iommu_map,
5709 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00005710 .iova_to_phys = intel_iommu_iova_to_phys,
5711 .add_device = intel_iommu_add_device,
5712 .remove_device = intel_iommu_remove_device,
5713 .get_resv_regions = intel_iommu_get_resv_regions,
5714 .put_resv_regions = intel_iommu_put_resv_regions,
5715 .device_group = pci_device_group,
Lu Baolu95587a72019-03-25 09:30:30 +08005716 .dev_has_feat = intel_iommu_dev_has_feat,
5717 .dev_feat_enabled = intel_iommu_dev_feat_enabled,
5718 .dev_enable_feat = intel_iommu_dev_enable_feat,
5719 .dev_disable_feat = intel_iommu_dev_disable_feat,
Eric Auger0659b8d2017-01-19 20:57:53 +00005720 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005721};
David Woodhouse9af88142009-02-13 23:18:03 +00005722
Daniel Vetter94526182013-01-20 23:50:13 +01005723static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
5724{
5725 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005726 pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01005727 dmar_map_gfx = 0;
5728}
5729
5730DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
5731DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
5732DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
5733DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
5734DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
5735DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
5736DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
5737
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005738static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00005739{
5740 /*
5741 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01005742 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00005743 */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005744 pci_info(dev, "Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00005745 rwbf_quirk = 1;
5746}
5747
5748DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01005749DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
5750DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
5751DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
5752DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
5753DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
5754DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07005755
Adam Jacksoneecfd572010-08-25 21:17:34 +01005756#define GGC 0x52
5757#define GGC_MEMORY_SIZE_MASK (0xf << 8)
5758#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
5759#define GGC_MEMORY_SIZE_1M (0x1 << 8)
5760#define GGC_MEMORY_SIZE_2M (0x3 << 8)
5761#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
5762#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
5763#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
5764#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
5765
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005766static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01005767{
5768 unsigned short ggc;
5769
Adam Jacksoneecfd572010-08-25 21:17:34 +01005770 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01005771 return;
5772
Adam Jacksoneecfd572010-08-25 21:17:34 +01005773 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005774 pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01005775 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005776 } else if (dmar_map_gfx) {
5777 /* we have to ensure the gfx device is idle before we flush */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005778 pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005779 intel_iommu_strict = 1;
5780 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01005781}
5782DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
5783DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
5784DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
5785DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
5786
David Woodhousee0fc7e02009-09-30 09:12:17 -07005787/* On Tylersburg chipsets, some BIOSes have been known to enable the
5788 ISOCH DMAR unit for the Azalia sound device, but not give it any
5789 TLB entries, which causes it to deadlock. Check for that. We do
5790 this in a function called from init_dmars(), instead of in a PCI
5791 quirk, because we don't want to print the obnoxious "BIOS broken"
5792 message if VT-d is actually disabled.
5793*/
5794static void __init check_tylersburg_isoch(void)
5795{
5796 struct pci_dev *pdev;
5797 uint32_t vtisochctrl;
5798
5799 /* If there's no Azalia in the system anyway, forget it. */
5800 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
5801 if (!pdev)
5802 return;
5803 pci_dev_put(pdev);
5804
5805 /* System Management Registers. Might be hidden, in which case
5806 we can't do the sanity check. But that's OK, because the
5807 known-broken BIOSes _don't_ actually hide it, so far. */
5808 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
5809 if (!pdev)
5810 return;
5811
5812 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
5813 pci_dev_put(pdev);
5814 return;
5815 }
5816
5817 pci_dev_put(pdev);
5818
5819 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
5820 if (vtisochctrl & 1)
5821 return;
5822
5823 /* Drop all bits other than the number of TLB entries */
5824 vtisochctrl &= 0x1c;
5825
5826 /* If we have the recommended number of TLB entries (16), fine. */
5827 if (vtisochctrl == 0x10)
5828 return;
5829
5830 /* Zero TLB entries? You get to ride the short bus to school. */
5831 if (!vtisochctrl) {
5832 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5833 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5834 dmi_get_system_info(DMI_BIOS_VENDOR),
5835 dmi_get_system_info(DMI_BIOS_VERSION),
5836 dmi_get_system_info(DMI_PRODUCT_VERSION));
5837 iommu_identity_mapping |= IDENTMAP_AZALIA;
5838 return;
5839 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005840
5841 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005842 vtisochctrl);
5843}