blob: c5426e847255367bd1076dd4bed0766297fb99ff [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
22
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070023#include <linux/init.h>
24#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080025#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040026#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070027#include <linux/slab.h>
28#include <linux/irq.h>
29#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070030#include <linux/spinlock.h>
31#include <linux/pci.h>
32#include <linux/dmar.h>
33#include <linux/dma-mapping.h>
34#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080035#include <linux/memory.h>
mark gross5e0d2a62008-03-04 15:22:08 -080036#include <linux/timer.h>
Dan Williamsdfddb962015-10-09 18:16:46 -040037#include <linux/io.h>
Kay, Allen M38717942008-09-09 18:37:29 +030038#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010039#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030040#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010041#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070042#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100043#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020044#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080045#include <linux/memblock.h>
Akinobu Mita36746432014-06-04 16:06:51 -070046#include <linux/dma-contiguous.h>
Joerg Roedel091d42e2015-06-12 11:56:10 +020047#include <linux/crash_dump.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070048#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070049#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090050#include <asm/iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070051
Joerg Roedel078e1ee2012-09-26 12:44:43 +020052#include "irq_remapping.h"
53
Fenghua Yu5b6985c2008-10-16 18:02:32 -070054#define ROOT_SIZE VTD_PAGE_SIZE
55#define CONTEXT_SIZE VTD_PAGE_SIZE
56
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070057#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000058#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070059#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070060#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070061
62#define IOAPIC_RANGE_START (0xfee00000)
63#define IOAPIC_RANGE_END (0xfeefffff)
64#define IOVA_START_ADDR (0x1000)
65
66#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
67
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070068#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080069#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070070
David Woodhouse2ebe3152009-09-19 07:34:04 -070071#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
72#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
73
74/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
75 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
76#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
77 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
78#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070079
Robin Murphy1b722502015-01-12 17:51:15 +000080/* IO virtual address start page frame number */
81#define IOVA_START_PFN (1)
82
Mark McLoughlinf27be032008-11-20 15:49:43 +000083#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
Yang Hongyang284901a2009-04-06 19:01:15 -070084#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
Yang Hongyang6a355282009-04-06 19:01:13 -070085#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
mark gross5e0d2a62008-03-04 15:22:08 -080086
Andrew Mortondf08cdc2010-09-22 13:05:11 -070087/* page table handling */
88#define LEVEL_STRIDE (9)
89#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
90
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020091/*
92 * This bitmap is used to advertise the page sizes our hardware support
93 * to the IOMMU core, which will then use this information to split
94 * physically contiguous memory regions it is mapping into page sizes
95 * that we support.
96 *
97 * Traditionally the IOMMU core just handed us the mappings directly,
98 * after making sure the size is an order of a 4KiB page and that the
99 * mapping has natural alignment.
100 *
101 * To retain this behavior, we currently advertise that we support
102 * all page sizes that are an order of 4KiB.
103 *
104 * If at some point we'd like to utilize the IOMMU core's new behavior,
105 * we could change this to advertise the real page sizes we support.
106 */
107#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
108
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700109static inline int agaw_to_level(int agaw)
110{
111 return agaw + 2;
112}
113
114static inline int agaw_to_width(int agaw)
115{
Jiang Liu5c645b32014-01-06 14:18:12 +0800116 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700117}
118
119static inline int width_to_agaw(int width)
120{
Jiang Liu5c645b32014-01-06 14:18:12 +0800121 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700122}
123
124static inline unsigned int level_to_offset_bits(int level)
125{
126 return (level - 1) * LEVEL_STRIDE;
127}
128
129static inline int pfn_level_offset(unsigned long pfn, int level)
130{
131 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
132}
133
134static inline unsigned long level_mask(int level)
135{
136 return -1UL << level_to_offset_bits(level);
137}
138
139static inline unsigned long level_size(int level)
140{
141 return 1UL << level_to_offset_bits(level);
142}
143
144static inline unsigned long align_to_level(unsigned long pfn, int level)
145{
146 return (pfn + level_size(level) - 1) & level_mask(level);
147}
David Woodhousefd18de52009-05-10 23:57:41 +0100148
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100149static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
150{
Jiang Liu5c645b32014-01-06 14:18:12 +0800151 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100152}
153
David Woodhousedd4e8312009-06-27 16:21:20 +0100154/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
155 are never going to work. */
156static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
157{
158 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
159}
160
161static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
162{
163 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
164}
165static inline unsigned long page_to_dma_pfn(struct page *pg)
166{
167 return mm_to_dma_pfn(page_to_pfn(pg));
168}
169static inline unsigned long virt_to_dma_pfn(void *p)
170{
171 return page_to_dma_pfn(virt_to_page(p));
172}
173
Weidong Hand9630fe2008-12-08 11:06:32 +0800174/* global iommu list, set NULL for ignored DMAR units */
175static struct intel_iommu **g_iommus;
176
David Woodhousee0fc7e02009-09-30 09:12:17 -0700177static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000178static int rwbf_quirk;
179
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000180/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700181 * set to 1 to panic kernel if can't successfully enable VT-d
182 * (used when kernel is launched w/ TXT)
183 */
184static int force_on = 0;
185
186/*
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000187 * 0: Present
188 * 1-11: Reserved
189 * 12-63: Context Ptr (12 - (haw-1))
190 * 64-127: Reserved
191 */
192struct root_entry {
David Woodhouse03ecc322015-02-13 14:35:21 +0000193 u64 lo;
194 u64 hi;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000195};
196#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000197
Joerg Roedel091d42e2015-06-12 11:56:10 +0200198/*
199 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
200 * if marked present.
201 */
202static phys_addr_t root_entry_lctp(struct root_entry *re)
203{
204 if (!(re->lo & 1))
205 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000206
Joerg Roedel091d42e2015-06-12 11:56:10 +0200207 return re->lo & VTD_PAGE_MASK;
208}
209
210/*
211 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
212 * if marked present.
213 */
214static phys_addr_t root_entry_uctp(struct root_entry *re)
215{
216 if (!(re->hi & 1))
217 return 0;
218
219 return re->hi & VTD_PAGE_MASK;
220}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000221/*
222 * low 64 bits:
223 * 0: present
224 * 1: fault processing disable
225 * 2-3: translation type
226 * 12-63: address space root
227 * high 64 bits:
228 * 0-2: address width
229 * 3-6: aval
230 * 8-23: domain id
231 */
232struct context_entry {
233 u64 lo;
234 u64 hi;
235};
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000236
Joerg Roedelcf484d02015-06-12 12:21:46 +0200237static inline void context_clear_pasid_enable(struct context_entry *context)
238{
239 context->lo &= ~(1ULL << 11);
240}
241
242static inline bool context_pasid_enabled(struct context_entry *context)
243{
244 return !!(context->lo & (1ULL << 11));
245}
246
247static inline void context_set_copied(struct context_entry *context)
248{
249 context->hi |= (1ull << 3);
250}
251
252static inline bool context_copied(struct context_entry *context)
253{
254 return !!(context->hi & (1ULL << 3));
255}
256
257static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000258{
259 return (context->lo & 1);
260}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200261
262static inline bool context_present(struct context_entry *context)
263{
264 return context_pasid_enabled(context) ?
265 __context_present(context) :
266 __context_present(context) && !context_copied(context);
267}
268
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000269static inline void context_set_present(struct context_entry *context)
270{
271 context->lo |= 1;
272}
273
274static inline void context_set_fault_enable(struct context_entry *context)
275{
276 context->lo &= (((u64)-1) << 2) | 1;
277}
278
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000279static inline void context_set_translation_type(struct context_entry *context,
280 unsigned long value)
281{
282 context->lo &= (((u64)-1) << 4) | 3;
283 context->lo |= (value & 3) << 2;
284}
285
286static inline void context_set_address_root(struct context_entry *context,
287 unsigned long value)
288{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800289 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000290 context->lo |= value & VTD_PAGE_MASK;
291}
292
293static inline void context_set_address_width(struct context_entry *context,
294 unsigned long value)
295{
296 context->hi |= value & 7;
297}
298
299static inline void context_set_domain_id(struct context_entry *context,
300 unsigned long value)
301{
302 context->hi |= (value & ((1 << 16) - 1)) << 8;
303}
304
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200305static inline int context_domain_id(struct context_entry *c)
306{
307 return((c->hi >> 8) & 0xffff);
308}
309
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000310static inline void context_clear_entry(struct context_entry *context)
311{
312 context->lo = 0;
313 context->hi = 0;
314}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000315
Mark McLoughlin622ba122008-11-20 15:49:46 +0000316/*
317 * 0: readable
318 * 1: writable
319 * 2-6: reserved
320 * 7: super page
Sheng Yang9cf066972009-03-18 15:33:07 +0800321 * 8-10: available
322 * 11: snoop behavior
Mark McLoughlin622ba122008-11-20 15:49:46 +0000323 * 12-63: Host physcial address
324 */
325struct dma_pte {
326 u64 val;
327};
Mark McLoughlin622ba122008-11-20 15:49:46 +0000328
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000329static inline void dma_clear_pte(struct dma_pte *pte)
330{
331 pte->val = 0;
332}
333
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000334static inline u64 dma_pte_addr(struct dma_pte *pte)
335{
David Woodhousec85994e2009-07-01 19:21:24 +0100336#ifdef CONFIG_64BIT
337 return pte->val & VTD_PAGE_MASK;
338#else
339 /* Must have a full atomic 64-bit read */
David Woodhouse1a8bd482010-08-10 01:38:53 +0100340 return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
David Woodhousec85994e2009-07-01 19:21:24 +0100341#endif
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000342}
343
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000344static inline bool dma_pte_present(struct dma_pte *pte)
345{
346 return (pte->val & 3) != 0;
347}
Mark McLoughlin622ba122008-11-20 15:49:46 +0000348
Allen Kay4399c8b2011-10-14 12:32:46 -0700349static inline bool dma_pte_superpage(struct dma_pte *pte)
350{
Joerg Roedelc3c75eb2014-07-04 11:19:10 +0200351 return (pte->val & DMA_PTE_LARGE_PAGE);
Allen Kay4399c8b2011-10-14 12:32:46 -0700352}
353
David Woodhouse75e6bf92009-07-02 11:21:16 +0100354static inline int first_pte_in_page(struct dma_pte *pte)
355{
356 return !((unsigned long)pte & ~VTD_PAGE_MASK);
357}
358
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700359/*
360 * This domain is a statically identity mapping domain.
361 * 1. This domain creats a static 1:1 mapping to all usable memory.
362 * 2. It maps to each iommu if successful.
363 * 3. Each iommu mapps to this domain if successful.
364 */
David Woodhouse19943b02009-08-04 16:19:20 +0100365static struct dmar_domain *si_domain;
366static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700367
Joerg Roedel28ccce02015-07-21 14:45:31 +0200368/*
369 * Domain represents a virtual machine, more than one devices
Weidong Han1ce28fe2008-12-08 16:35:39 +0800370 * across iommus may be owned in one domain, e.g. kvm guest.
371 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800372#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800373
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700374/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800375#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700376
Joerg Roedel29a27712015-07-21 17:17:12 +0200377#define for_each_domain_iommu(idx, domain) \
378 for (idx = 0; idx < g_num_of_iommus; idx++) \
379 if (domain->iommu_refcnt[idx])
380
Mark McLoughlin99126f72008-11-20 15:49:47 +0000381struct dmar_domain {
Suresh Siddha4c923d42009-10-02 11:01:24 -0700382 int nid; /* node id */
Joerg Roedel29a27712015-07-21 17:17:12 +0200383
384 unsigned iommu_refcnt[DMAR_UNITS_SUPPORTED];
385 /* Refcount of devices per iommu */
386
Mark McLoughlin99126f72008-11-20 15:49:47 +0000387
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +0200388 u16 iommu_did[DMAR_UNITS_SUPPORTED];
389 /* Domain ids per IOMMU. Use u16 since
390 * domain ids are 16 bit wide according
391 * to VT-d spec, section 9.3 */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000392
Joerg Roedel00a77de2015-03-26 13:43:08 +0100393 struct list_head devices; /* all devices' list */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000394 struct iova_domain iovad; /* iova's that belong to this domain */
395
396 struct dma_pte *pgd; /* virtual address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000397 int gaw; /* max guest address width */
398
399 /* adjusted guest address width, 0 is level 2 30-bit */
400 int agaw;
401
Weidong Han3b5410e2008-12-08 09:17:15 +0800402 int flags; /* flags to find out type of domain */
Weidong Han8e6040972008-12-08 15:49:06 +0800403
404 int iommu_coherency;/* indicate coherency of iommu access */
Sheng Yang58c610b2009-03-18 15:33:05 +0800405 int iommu_snooping; /* indicate snooping control feature*/
Weidong Hanc7151a82008-12-08 22:51:37 +0800406 int iommu_count; /* reference count of iommu */
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100407 int iommu_superpage;/* Level of superpages supported:
408 0 == 4KiB (no superpages), 1 == 2MiB,
409 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
Weidong Hanfe40f1e2008-12-08 23:10:23 +0800410 u64 max_addr; /* maximum mapped address */
Joerg Roedel00a77de2015-03-26 13:43:08 +0100411
412 struct iommu_domain domain; /* generic domain data structure for
413 iommu core */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000414};
415
Mark McLoughlina647dac2008-11-20 15:49:48 +0000416/* PCI domain-device relationship */
417struct device_domain_info {
418 struct list_head link; /* link to domain siblings */
419 struct list_head global; /* link to global list */
David Woodhouse276dbf992009-04-04 01:45:37 +0100420 u8 bus; /* PCI bus number */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000421 u8 devfn; /* PCI devfn number */
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -0500422 struct {
423 u8 enabled:1;
424 u8 qdep;
425 } ats; /* ATS state */
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000426 struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
Yu Zhao93a23a72009-05-18 13:51:37 +0800427 struct intel_iommu *iommu; /* IOMMU used by this device */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000428 struct dmar_domain *domain; /* pointer to domain */
429};
430
Jiang Liub94e4112014-02-19 14:07:25 +0800431struct dmar_rmrr_unit {
432 struct list_head list; /* list of rmrr units */
433 struct acpi_dmar_header *hdr; /* ACPI header */
434 u64 base_address; /* reserved base address*/
435 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000436 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800437 int devices_cnt; /* target device count */
438};
439
440struct dmar_atsr_unit {
441 struct list_head list; /* list of ATSR units */
442 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000443 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800444 int devices_cnt; /* target device count */
445 u8 include_all:1; /* include all ports */
446};
447
448static LIST_HEAD(dmar_atsr_units);
449static LIST_HEAD(dmar_rmrr_units);
450
451#define for_each_rmrr_units(rmrr) \
452 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
453
mark gross5e0d2a62008-03-04 15:22:08 -0800454static void flush_unmaps_timeout(unsigned long data);
455
Jiang Liub707cb02014-01-06 14:18:26 +0800456static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
mark gross5e0d2a62008-03-04 15:22:08 -0800457
mark gross80b20dd2008-04-18 13:53:58 -0700458#define HIGH_WATER_MARK 250
459struct deferred_flush_tables {
460 int next;
461 struct iova *iova[HIGH_WATER_MARK];
462 struct dmar_domain *domain[HIGH_WATER_MARK];
David Woodhouseea8ea462014-03-05 17:09:32 +0000463 struct page *freelist[HIGH_WATER_MARK];
mark gross80b20dd2008-04-18 13:53:58 -0700464};
465
466static struct deferred_flush_tables *deferred_flush;
467
mark gross5e0d2a62008-03-04 15:22:08 -0800468/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800469static int g_num_of_iommus;
470
471static DEFINE_SPINLOCK(async_umap_flush_lock);
472static LIST_HEAD(unmaps_to_do);
473
474static int timer_on;
475static long list_size;
mark gross5e0d2a62008-03-04 15:22:08 -0800476
Jiang Liu92d03cc2014-02-19 14:07:28 +0800477static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700478static void domain_remove_dev_info(struct dmar_domain *domain);
Joerg Roedele6de0f82015-07-22 16:30:36 +0200479static void dmar_remove_one_dev_info(struct dmar_domain *domain,
480 struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200481static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Joerg Roedel2452d9d2015-07-23 16:20:14 +0200482static void domain_context_clear(struct intel_iommu *iommu,
483 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800484static int domain_detach_iommu(struct dmar_domain *domain,
485 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700486
Suresh Siddhad3f13812011-08-23 17:05:25 -0700487#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800488int dmar_disabled = 0;
489#else
490int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700491#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800492
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200493int intel_iommu_enabled = 0;
494EXPORT_SYMBOL_GPL(intel_iommu_enabled);
495
David Woodhouse2d9e6672010-06-15 10:57:57 +0100496static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700497static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800498static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100499static int intel_iommu_superpage = 1;
David Woodhousec83b2f22015-06-12 10:15:49 +0100500static int intel_iommu_ecs = 1;
501
502/* We only actually use ECS when PASID support (on the new bit 40)
503 * is also advertised. Some early implementations — the ones with
504 * PASID support on bit 28 — have issues even when we *only* use
505 * extended root/context tables. */
506#define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \
507 ecap_pasid(iommu->ecap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700508
David Woodhousec0771df2011-10-14 20:59:46 +0100509int intel_iommu_gfx_mapped;
510EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
511
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700512#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
513static DEFINE_SPINLOCK(device_domain_lock);
514static LIST_HEAD(device_domain_list);
515
Thierry Redingb22f6432014-06-27 09:03:12 +0200516static const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100517
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200518static bool translation_pre_enabled(struct intel_iommu *iommu)
519{
520 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
521}
522
Joerg Roedel091d42e2015-06-12 11:56:10 +0200523static void clear_translation_pre_enabled(struct intel_iommu *iommu)
524{
525 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
526}
527
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200528static void init_translation_status(struct intel_iommu *iommu)
529{
530 u32 gsts;
531
532 gsts = readl(iommu->reg + DMAR_GSTS_REG);
533 if (gsts & DMA_GSTS_TES)
534 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
535}
536
Joerg Roedel00a77de2015-03-26 13:43:08 +0100537/* Convert generic 'struct iommu_domain to private struct dmar_domain */
538static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
539{
540 return container_of(dom, struct dmar_domain, domain);
541}
542
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700543static int __init intel_iommu_setup(char *str)
544{
545 if (!str)
546 return -EINVAL;
547 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800548 if (!strncmp(str, "on", 2)) {
549 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200550 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800551 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700552 dmar_disabled = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200553 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700554 } else if (!strncmp(str, "igfx_off", 8)) {
555 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200556 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700557 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200558 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700559 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800560 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200561 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800562 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100563 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200564 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100565 intel_iommu_superpage = 0;
David Woodhousec83b2f22015-06-12 10:15:49 +0100566 } else if (!strncmp(str, "ecs_off", 7)) {
567 printk(KERN_INFO
568 "Intel-IOMMU: disable extended context table support\n");
569 intel_iommu_ecs = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700570 }
571
572 str += strcspn(str, ",");
573 while (*str == ',')
574 str++;
575 }
576 return 0;
577}
578__setup("intel_iommu=", intel_iommu_setup);
579
580static struct kmem_cache *iommu_domain_cache;
581static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700582
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200583static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
584{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200585 struct dmar_domain **domains;
586 int idx = did >> 8;
587
588 domains = iommu->domains[idx];
589 if (!domains)
590 return NULL;
591
592 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200593}
594
595static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
596 struct dmar_domain *domain)
597{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200598 struct dmar_domain **domains;
599 int idx = did >> 8;
600
601 if (!iommu->domains[idx]) {
602 size_t size = 256 * sizeof(struct dmar_domain *);
603 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
604 }
605
606 domains = iommu->domains[idx];
607 if (WARN_ON(!domains))
608 return;
609 else
610 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200611}
612
Suresh Siddha4c923d42009-10-02 11:01:24 -0700613static inline void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700614{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700615 struct page *page;
616 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700617
Suresh Siddha4c923d42009-10-02 11:01:24 -0700618 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
619 if (page)
620 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700621 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700622}
623
624static inline void free_pgtable_page(void *vaddr)
625{
626 free_page((unsigned long)vaddr);
627}
628
629static inline void *alloc_domain_mem(void)
630{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900631 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700632}
633
Kay, Allen M38717942008-09-09 18:37:29 +0300634static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700635{
636 kmem_cache_free(iommu_domain_cache, vaddr);
637}
638
639static inline void * alloc_devinfo_mem(void)
640{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900641 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700642}
643
644static inline void free_devinfo_mem(void *vaddr)
645{
646 kmem_cache_free(iommu_devinfo_cache, vaddr);
647}
648
Jiang Liuab8dfe22014-07-11 14:19:27 +0800649static inline int domain_type_is_vm(struct dmar_domain *domain)
650{
651 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
652}
653
Joerg Roedel28ccce02015-07-21 14:45:31 +0200654static inline int domain_type_is_si(struct dmar_domain *domain)
655{
656 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
657}
658
Jiang Liuab8dfe22014-07-11 14:19:27 +0800659static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
660{
661 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
662 DOMAIN_FLAG_STATIC_IDENTITY);
663}
Weidong Han1b573682008-12-08 15:34:06 +0800664
Jiang Liu162d1b12014-07-11 14:19:35 +0800665static inline int domain_pfn_supported(struct dmar_domain *domain,
666 unsigned long pfn)
667{
668 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
669
670 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
671}
672
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700673static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800674{
675 unsigned long sagaw;
676 int agaw = -1;
677
678 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700679 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800680 agaw >= 0; agaw--) {
681 if (test_bit(agaw, &sagaw))
682 break;
683 }
684
685 return agaw;
686}
687
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700688/*
689 * Calculate max SAGAW for each iommu.
690 */
691int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
692{
693 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
694}
695
696/*
697 * calculate agaw for each iommu.
698 * "SAGAW" may be different across iommus, use a default agaw, and
699 * get a supported less agaw for iommus that don't support the default agaw.
700 */
701int iommu_calculate_agaw(struct intel_iommu *iommu)
702{
703 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
704}
705
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700706/* This functionin only returns single iommu in a domain */
Weidong Han8c11e792008-12-08 15:29:22 +0800707static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
708{
709 int iommu_id;
710
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700711 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800712 BUG_ON(domain_type_is_vm_or_si(domain));
Joerg Roedel29a27712015-07-21 17:17:12 +0200713 for_each_domain_iommu(iommu_id, domain)
714 break;
715
Weidong Han8c11e792008-12-08 15:29:22 +0800716 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
717 return NULL;
718
719 return g_iommus[iommu_id];
720}
721
Weidong Han8e6040972008-12-08 15:49:06 +0800722static void domain_update_iommu_coherency(struct dmar_domain *domain)
723{
David Woodhoused0501962014-03-11 17:10:29 -0700724 struct dmar_drhd_unit *drhd;
725 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100726 bool found = false;
727 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800728
David Woodhoused0501962014-03-11 17:10:29 -0700729 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800730
Joerg Roedel29a27712015-07-21 17:17:12 +0200731 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100732 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800733 if (!ecap_coherent(g_iommus[i]->ecap)) {
734 domain->iommu_coherency = 0;
735 break;
736 }
Weidong Han8e6040972008-12-08 15:49:06 +0800737 }
David Woodhoused0501962014-03-11 17:10:29 -0700738 if (found)
739 return;
740
741 /* No hardware attached; use lowest common denominator */
742 rcu_read_lock();
743 for_each_active_iommu(iommu, drhd) {
744 if (!ecap_coherent(iommu->ecap)) {
745 domain->iommu_coherency = 0;
746 break;
747 }
748 }
749 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800750}
751
Jiang Liu161f6932014-07-11 14:19:37 +0800752static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100753{
Allen Kay8140a952011-10-14 12:32:17 -0700754 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800755 struct intel_iommu *iommu;
756 int ret = 1;
757
758 rcu_read_lock();
759 for_each_active_iommu(iommu, drhd) {
760 if (iommu != skip) {
761 if (!ecap_sc_support(iommu->ecap)) {
762 ret = 0;
763 break;
764 }
765 }
766 }
767 rcu_read_unlock();
768
769 return ret;
770}
771
772static int domain_update_iommu_superpage(struct intel_iommu *skip)
773{
774 struct dmar_drhd_unit *drhd;
775 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700776 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100777
778 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800779 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100780 }
781
Allen Kay8140a952011-10-14 12:32:17 -0700782 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800783 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700784 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800785 if (iommu != skip) {
786 mask &= cap_super_page_val(iommu->cap);
787 if (!mask)
788 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100789 }
790 }
Jiang Liu0e242612014-02-19 14:07:34 +0800791 rcu_read_unlock();
792
Jiang Liu161f6932014-07-11 14:19:37 +0800793 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100794}
795
Sheng Yang58c610b2009-03-18 15:33:05 +0800796/* Some capabilities may be different across iommus */
797static void domain_update_iommu_cap(struct dmar_domain *domain)
798{
799 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800800 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
801 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800802}
803
David Woodhouse03ecc322015-02-13 14:35:21 +0000804static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu,
805 u8 bus, u8 devfn, int alloc)
806{
807 struct root_entry *root = &iommu->root_entry[bus];
808 struct context_entry *context;
809 u64 *entry;
810
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200811 entry = &root->lo;
David Woodhousec83b2f22015-06-12 10:15:49 +0100812 if (ecs_enabled(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000813 if (devfn >= 0x80) {
814 devfn -= 0x80;
815 entry = &root->hi;
816 }
817 devfn *= 2;
818 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000819 if (*entry & 1)
820 context = phys_to_virt(*entry & VTD_PAGE_MASK);
821 else {
822 unsigned long phy_addr;
823 if (!alloc)
824 return NULL;
825
826 context = alloc_pgtable_page(iommu->node);
827 if (!context)
828 return NULL;
829
830 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
831 phy_addr = virt_to_phys((void *)context);
832 *entry = phy_addr | 1;
833 __iommu_flush_cache(iommu, entry, sizeof(*entry));
834 }
835 return &context[devfn];
836}
837
David Woodhouse4ed6a542015-05-11 14:59:20 +0100838static int iommu_dummy(struct device *dev)
839{
840 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
841}
842
David Woodhouse156baca2014-03-09 14:00:57 -0700843static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800844{
845 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800846 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700847 struct device *tmp;
848 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800849 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800850 int i;
851
David Woodhouse4ed6a542015-05-11 14:59:20 +0100852 if (iommu_dummy(dev))
853 return NULL;
854
David Woodhouse156baca2014-03-09 14:00:57 -0700855 if (dev_is_pci(dev)) {
856 pdev = to_pci_dev(dev);
857 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100858 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700859 dev = &ACPI_COMPANION(dev)->dev;
860
Jiang Liu0e242612014-02-19 14:07:34 +0800861 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800862 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700863 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100864 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800865
Jiang Liub683b232014-02-19 14:07:32 +0800866 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700867 drhd->devices_cnt, i, tmp) {
868 if (tmp == dev) {
869 *bus = drhd->devices[i].bus;
870 *devfn = drhd->devices[i].devfn;
871 goto out;
872 }
873
874 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000875 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700876
877 ptmp = to_pci_dev(tmp);
878 if (ptmp->subordinate &&
879 ptmp->subordinate->number <= pdev->bus->number &&
880 ptmp->subordinate->busn_res.end >= pdev->bus->number)
881 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100882 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800883
David Woodhouse156baca2014-03-09 14:00:57 -0700884 if (pdev && drhd->include_all) {
885 got_pdev:
886 *bus = pdev->bus->number;
887 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800888 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700889 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800890 }
Jiang Liub683b232014-02-19 14:07:32 +0800891 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700892 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800893 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800894
Jiang Liub683b232014-02-19 14:07:32 +0800895 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800896}
897
Weidong Han5331fe62008-12-08 23:00:00 +0800898static void domain_flush_cache(struct dmar_domain *domain,
899 void *addr, int size)
900{
901 if (!domain->iommu_coherency)
902 clflush_cache_range(addr, size);
903}
904
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700905static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
906{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700907 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000908 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700909 unsigned long flags;
910
911 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000912 context = iommu_context_addr(iommu, bus, devfn, 0);
913 if (context)
914 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700915 spin_unlock_irqrestore(&iommu->lock, flags);
916 return ret;
917}
918
919static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
920{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700921 struct context_entry *context;
922 unsigned long flags;
923
924 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000925 context = iommu_context_addr(iommu, bus, devfn, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700926 if (context) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000927 context_clear_entry(context);
928 __iommu_flush_cache(iommu, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700929 }
930 spin_unlock_irqrestore(&iommu->lock, flags);
931}
932
933static void free_context_table(struct intel_iommu *iommu)
934{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700935 int i;
936 unsigned long flags;
937 struct context_entry *context;
938
939 spin_lock_irqsave(&iommu->lock, flags);
940 if (!iommu->root_entry) {
941 goto out;
942 }
943 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000944 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700945 if (context)
946 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000947
David Woodhousec83b2f22015-06-12 10:15:49 +0100948 if (!ecs_enabled(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000949 continue;
950
951 context = iommu_context_addr(iommu, i, 0x80, 0);
952 if (context)
953 free_pgtable_page(context);
954
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700955 }
956 free_pgtable_page(iommu->root_entry);
957 iommu->root_entry = NULL;
958out:
959 spin_unlock_irqrestore(&iommu->lock, flags);
960}
961
David Woodhouseb026fd22009-06-28 10:37:25 +0100962static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000963 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700964{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700965 struct dma_pte *parent, *pte = NULL;
966 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700967 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700968
969 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200970
Jiang Liu162d1b12014-07-11 14:19:35 +0800971 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200972 /* Address beyond IOMMU's addressing capabilities. */
973 return NULL;
974
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700975 parent = domain->pgd;
976
David Woodhouse5cf0a762014-03-19 16:07:49 +0000977 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700978 void *tmp_page;
979
David Woodhouseb026fd22009-06-28 10:37:25 +0100980 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700981 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000982 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100983 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000984 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700985 break;
986
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000987 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100988 uint64_t pteval;
989
Suresh Siddha4c923d42009-10-02 11:01:24 -0700990 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700991
David Woodhouse206a73c12009-07-01 19:30:28 +0100992 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700993 return NULL;
David Woodhouse206a73c12009-07-01 19:30:28 +0100994
David Woodhousec85994e2009-07-01 19:21:24 +0100995 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400996 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 +0800997 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100998 /* Someone else set it while we were thinking; use theirs. */
999 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +08001000 else
David Woodhousec85994e2009-07-01 19:21:24 +01001001 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001002 }
David Woodhouse5cf0a762014-03-19 16:07:49 +00001003 if (level == 1)
1004 break;
1005
Mark McLoughlin19c239c2008-11-21 16:56:53 +00001006 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001007 level--;
1008 }
1009
David Woodhouse5cf0a762014-03-19 16:07:49 +00001010 if (!*target_level)
1011 *target_level = level;
1012
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001013 return pte;
1014}
1015
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001016
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001017/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +01001018static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
1019 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001020 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001021{
1022 struct dma_pte *parent, *pte = NULL;
1023 int total = agaw_to_level(domain->agaw);
1024 int offset;
1025
1026 parent = domain->pgd;
1027 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +01001028 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001029 pte = &parent[offset];
1030 if (level == total)
1031 return pte;
1032
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001033 if (!dma_pte_present(pte)) {
1034 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001035 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001036 }
1037
Yijing Wange16922a2014-05-20 20:37:51 +08001038 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001039 *large_page = total;
1040 return pte;
1041 }
1042
Mark McLoughlin19c239c2008-11-21 16:56:53 +00001043 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001044 total--;
1045 }
1046 return NULL;
1047}
1048
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001049/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +00001050static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf2009-06-27 22:09:11 +01001051 unsigned long start_pfn,
1052 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001053{
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001054 unsigned int large_page = 1;
David Woodhouse310a5ab2009-06-28 18:52:20 +01001055 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001056
Jiang Liu162d1b12014-07-11 14:19:35 +08001057 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1058 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001059 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +01001060
David Woodhouse04b18e62009-06-27 19:15:01 +01001061 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -07001062 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001063 large_page = 1;
1064 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001065 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001066 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001067 continue;
1068 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001069 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +01001070 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001071 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001072 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +01001073 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
1074
David Woodhouse310a5ab2009-06-28 18:52:20 +01001075 domain_flush_cache(domain, first_pte,
1076 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -07001077
1078 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001079}
1080
Alex Williamson3269ee02013-06-15 10:27:19 -06001081static void dma_pte_free_level(struct dmar_domain *domain, int level,
1082 struct dma_pte *pte, unsigned long pfn,
1083 unsigned long start_pfn, unsigned long last_pfn)
1084{
1085 pfn = max(start_pfn, pfn);
1086 pte = &pte[pfn_level_offset(pfn, level)];
1087
1088 do {
1089 unsigned long level_pfn;
1090 struct dma_pte *level_pte;
1091
1092 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
1093 goto next;
1094
1095 level_pfn = pfn & level_mask(level - 1);
1096 level_pte = phys_to_virt(dma_pte_addr(pte));
1097
1098 if (level > 2)
1099 dma_pte_free_level(domain, level - 1, level_pte,
1100 level_pfn, start_pfn, last_pfn);
1101
1102 /* If range covers entire pagetable, free it */
1103 if (!(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001104 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001105 dma_clear_pte(pte);
1106 domain_flush_cache(domain, pte, sizeof(*pte));
1107 free_pgtable_page(level_pte);
1108 }
1109next:
1110 pfn += level_size(level);
1111 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1112}
1113
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001114/* free page table pages. last level pte should already be cleared */
1115static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001116 unsigned long start_pfn,
1117 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001118{
Jiang Liu162d1b12014-07-11 14:19:35 +08001119 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1120 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001121 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001122
Jiang Liud41a4ad2014-07-11 14:19:34 +08001123 dma_pte_clear_range(domain, start_pfn, last_pfn);
1124
David Woodhousef3a0a522009-06-30 03:40:07 +01001125 /* We don't need lock here; nobody else touches the iova range */
Alex Williamson3269ee02013-06-15 10:27:19 -06001126 dma_pte_free_level(domain, agaw_to_level(domain->agaw),
1127 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001128
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001129 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001130 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001131 free_pgtable_page(domain->pgd);
1132 domain->pgd = NULL;
1133 }
1134}
1135
David Woodhouseea8ea462014-03-05 17:09:32 +00001136/* When a page at a given level is being unlinked from its parent, we don't
1137 need to *modify* it at all. All we need to do is make a list of all the
1138 pages which can be freed just as soon as we've flushed the IOTLB and we
1139 know the hardware page-walk will no longer touch them.
1140 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1141 be freed. */
1142static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1143 int level, struct dma_pte *pte,
1144 struct page *freelist)
1145{
1146 struct page *pg;
1147
1148 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1149 pg->freelist = freelist;
1150 freelist = pg;
1151
1152 if (level == 1)
1153 return freelist;
1154
Jiang Liuadeb2592014-04-09 10:20:39 +08001155 pte = page_address(pg);
1156 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001157 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1158 freelist = dma_pte_list_pagetables(domain, level - 1,
1159 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001160 pte++;
1161 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001162
1163 return freelist;
1164}
1165
1166static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1167 struct dma_pte *pte, unsigned long pfn,
1168 unsigned long start_pfn,
1169 unsigned long last_pfn,
1170 struct page *freelist)
1171{
1172 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1173
1174 pfn = max(start_pfn, pfn);
1175 pte = &pte[pfn_level_offset(pfn, level)];
1176
1177 do {
1178 unsigned long level_pfn;
1179
1180 if (!dma_pte_present(pte))
1181 goto next;
1182
1183 level_pfn = pfn & level_mask(level);
1184
1185 /* If range covers entire pagetable, free it */
1186 if (start_pfn <= level_pfn &&
1187 last_pfn >= level_pfn + level_size(level) - 1) {
1188 /* These suborbinate page tables are going away entirely. Don't
1189 bother to clear them; we're just going to *free* them. */
1190 if (level > 1 && !dma_pte_superpage(pte))
1191 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1192
1193 dma_clear_pte(pte);
1194 if (!first_pte)
1195 first_pte = pte;
1196 last_pte = pte;
1197 } else if (level > 1) {
1198 /* Recurse down into a level that isn't *entirely* obsolete */
1199 freelist = dma_pte_clear_level(domain, level - 1,
1200 phys_to_virt(dma_pte_addr(pte)),
1201 level_pfn, start_pfn, last_pfn,
1202 freelist);
1203 }
1204next:
1205 pfn += level_size(level);
1206 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1207
1208 if (first_pte)
1209 domain_flush_cache(domain, first_pte,
1210 (void *)++last_pte - (void *)first_pte);
1211
1212 return freelist;
1213}
1214
1215/* We can't just free the pages because the IOMMU may still be walking
1216 the page tables, and may have cached the intermediate levels. The
1217 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001218static struct page *domain_unmap(struct dmar_domain *domain,
1219 unsigned long start_pfn,
1220 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001221{
David Woodhouseea8ea462014-03-05 17:09:32 +00001222 struct page *freelist = NULL;
1223
Jiang Liu162d1b12014-07-11 14:19:35 +08001224 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1225 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001226 BUG_ON(start_pfn > last_pfn);
1227
1228 /* we don't need lock here; nobody else touches the iova range */
1229 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1230 domain->pgd, 0, start_pfn, last_pfn, NULL);
1231
1232 /* free pgd */
1233 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1234 struct page *pgd_page = virt_to_page(domain->pgd);
1235 pgd_page->freelist = freelist;
1236 freelist = pgd_page;
1237
1238 domain->pgd = NULL;
1239 }
1240
1241 return freelist;
1242}
1243
Joerg Roedelb6904202015-08-13 11:32:18 +02001244static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001245{
1246 struct page *pg;
1247
1248 while ((pg = freelist)) {
1249 freelist = pg->freelist;
1250 free_pgtable_page(page_address(pg));
1251 }
1252}
1253
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001254/* iommu handling */
1255static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1256{
1257 struct root_entry *root;
1258 unsigned long flags;
1259
Suresh Siddha4c923d42009-10-02 11:01:24 -07001260 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001261 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001262 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001263 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001264 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001265 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001266
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001267 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001268
1269 spin_lock_irqsave(&iommu->lock, flags);
1270 iommu->root_entry = root;
1271 spin_unlock_irqrestore(&iommu->lock, flags);
1272
1273 return 0;
1274}
1275
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001276static void iommu_set_root_entry(struct intel_iommu *iommu)
1277{
David Woodhouse03ecc322015-02-13 14:35:21 +00001278 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001279 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001280 unsigned long flag;
1281
David Woodhouse03ecc322015-02-13 14:35:21 +00001282 addr = virt_to_phys(iommu->root_entry);
David Woodhousec83b2f22015-06-12 10:15:49 +01001283 if (ecs_enabled(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +00001284 addr |= DMA_RTADDR_RTT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001285
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001286 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001287 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001288
David Woodhousec416daa2009-05-10 20:30:58 +01001289 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001290
1291 /* Make sure hardware complete it */
1292 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001293 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001294
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001295 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001296}
1297
1298static void iommu_flush_write_buffer(struct intel_iommu *iommu)
1299{
1300 u32 val;
1301 unsigned long flag;
1302
David Woodhouse9af88142009-02-13 23:18:03 +00001303 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001304 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001305
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001306 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001307 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001308
1309 /* Make sure hardware complete it */
1310 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001311 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001312
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001313 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001314}
1315
1316/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001317static void __iommu_flush_context(struct intel_iommu *iommu,
1318 u16 did, u16 source_id, u8 function_mask,
1319 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001320{
1321 u64 val = 0;
1322 unsigned long flag;
1323
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001324 switch (type) {
1325 case DMA_CCMD_GLOBAL_INVL:
1326 val = DMA_CCMD_GLOBAL_INVL;
1327 break;
1328 case DMA_CCMD_DOMAIN_INVL:
1329 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1330 break;
1331 case DMA_CCMD_DEVICE_INVL:
1332 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1333 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1334 break;
1335 default:
1336 BUG();
1337 }
1338 val |= DMA_CCMD_ICC;
1339
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001340 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001341 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1342
1343 /* Make sure hardware complete it */
1344 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1345 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1346
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001347 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001348}
1349
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001350/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001351static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1352 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001353{
1354 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1355 u64 val = 0, val_iva = 0;
1356 unsigned long flag;
1357
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001358 switch (type) {
1359 case DMA_TLB_GLOBAL_FLUSH:
1360 /* global flush doesn't need set IVA_REG */
1361 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1362 break;
1363 case DMA_TLB_DSI_FLUSH:
1364 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1365 break;
1366 case DMA_TLB_PSI_FLUSH:
1367 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001368 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001369 val_iva = size_order | addr;
1370 break;
1371 default:
1372 BUG();
1373 }
1374 /* Note: set drain read/write */
1375#if 0
1376 /*
1377 * This is probably to be super secure.. Looks like we can
1378 * ignore it without any impact.
1379 */
1380 if (cap_read_drain(iommu->cap))
1381 val |= DMA_TLB_READ_DRAIN;
1382#endif
1383 if (cap_write_drain(iommu->cap))
1384 val |= DMA_TLB_WRITE_DRAIN;
1385
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001386 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001387 /* Note: Only uses first TLB reg currently */
1388 if (val_iva)
1389 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1390 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1391
1392 /* Make sure hardware complete it */
1393 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1394 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1395
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001396 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001397
1398 /* check IOTLB invalidation granularity */
1399 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001400 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001401 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001402 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001403 (unsigned long long)DMA_TLB_IIRG(type),
1404 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001405}
1406
David Woodhouse64ae8922014-03-09 12:52:30 -07001407static struct device_domain_info *
1408iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1409 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001410{
Quentin Lambert2f119c72015-02-06 10:59:53 +01001411 bool found = false;
Yu Zhao93a23a72009-05-18 13:51:37 +08001412 struct device_domain_info *info;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001413 struct pci_dev *pdev;
Yu Zhao93a23a72009-05-18 13:51:37 +08001414
Joerg Roedel55d94042015-07-22 16:50:40 +02001415 assert_spin_locked(&device_domain_lock);
1416
Yu Zhao93a23a72009-05-18 13:51:37 +08001417 if (!ecap_dev_iotlb_support(iommu->ecap))
1418 return NULL;
1419
1420 if (!iommu->qi)
1421 return NULL;
1422
Yu Zhao93a23a72009-05-18 13:51:37 +08001423 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001424 if (info->iommu == iommu && info->bus == bus &&
1425 info->devfn == devfn) {
Quentin Lambert2f119c72015-02-06 10:59:53 +01001426 found = true;
Yu Zhao93a23a72009-05-18 13:51:37 +08001427 break;
1428 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001429
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001430 if (!found || !info->dev || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001431 return NULL;
1432
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001433 pdev = to_pci_dev(info->dev);
1434
1435 if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
Yu Zhao93a23a72009-05-18 13:51:37 +08001436 return NULL;
1437
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001438 if (!dmar_find_matched_atsr_unit(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001439 return NULL;
1440
Yu Zhao93a23a72009-05-18 13:51:37 +08001441 return info;
1442}
1443
1444static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1445{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001446 struct pci_dev *pdev;
1447
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001448 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001449 return;
1450
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001451 pdev = to_pci_dev(info->dev);
1452 if (pci_enable_ats(pdev, VTD_PAGE_SHIFT))
1453 return;
1454
1455 info->ats.enabled = 1;
1456 info->ats.qdep = pci_ats_queue_depth(pdev);
Yu Zhao93a23a72009-05-18 13:51:37 +08001457}
1458
1459static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1460{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001461 if (!info->ats.enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001462 return;
1463
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001464 pci_disable_ats(to_pci_dev(info->dev));
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001465 info->ats.enabled = 0;
Yu Zhao93a23a72009-05-18 13:51:37 +08001466}
1467
1468static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1469 u64 addr, unsigned mask)
1470{
1471 u16 sid, qdep;
1472 unsigned long flags;
1473 struct device_domain_info *info;
1474
1475 spin_lock_irqsave(&device_domain_lock, flags);
1476 list_for_each_entry(info, &domain->devices, link) {
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001477 if (!info->ats.enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001478 continue;
1479
1480 sid = info->bus << 8 | info->devfn;
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001481 qdep = info->ats.qdep;
Yu Zhao93a23a72009-05-18 13:51:37 +08001482 qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
1483 }
1484 spin_unlock_irqrestore(&device_domain_lock, flags);
1485}
1486
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001487static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1488 struct dmar_domain *domain,
1489 unsigned long pfn, unsigned int pages,
1490 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001491{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001492 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001493 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001494 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001495
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001496 BUG_ON(pages == 0);
1497
David Woodhouseea8ea462014-03-05 17:09:32 +00001498 if (ih)
1499 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001500 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001501 * Fallback to domain selective flush if no PSI support or the size is
1502 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001503 * PSI requires page size to be 2 ^ x, and the base address is naturally
1504 * aligned to the size
1505 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001506 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1507 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001508 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001509 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001510 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001511 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001512
1513 /*
Nadav Amit82653632010-04-01 13:24:40 +03001514 * In caching mode, changes of pages from non-present to present require
1515 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001516 */
Nadav Amit82653632010-04-01 13:24:40 +03001517 if (!cap_caching_mode(iommu->cap) || !map)
Joerg Roedel9452d5b2015-07-21 10:00:56 +02001518 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1519 addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001520}
1521
mark grossf8bab732008-02-08 04:18:38 -08001522static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1523{
1524 u32 pmen;
1525 unsigned long flags;
1526
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001527 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001528 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1529 pmen &= ~DMA_PMEN_EPM;
1530 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1531
1532 /* wait for the protected region status bit to clear */
1533 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1534 readl, !(pmen & DMA_PMEN_PRS), pmen);
1535
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001536 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001537}
1538
Jiang Liu2a41cce2014-07-11 14:19:33 +08001539static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001540{
1541 u32 sts;
1542 unsigned long flags;
1543
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001544 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001545 iommu->gcmd |= DMA_GCMD_TE;
1546 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001547
1548 /* Make sure hardware complete it */
1549 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001550 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001551
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001552 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001553}
1554
Jiang Liu2a41cce2014-07-11 14:19:33 +08001555static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001556{
1557 u32 sts;
1558 unsigned long flag;
1559
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001560 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001561 iommu->gcmd &= ~DMA_GCMD_TE;
1562 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1563
1564 /* Make sure hardware complete it */
1565 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001566 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001567
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001568 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001569}
1570
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001571
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001572static int iommu_init_domains(struct intel_iommu *iommu)
1573{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001574 u32 ndomains, nlongs;
1575 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001576
1577 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001578 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001579 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001580 nlongs = BITS_TO_LONGS(ndomains);
1581
Donald Dutile94a91b52009-08-20 16:51:34 -04001582 spin_lock_init(&iommu->lock);
1583
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001584 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1585 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001586 pr_err("%s: Allocating domain id array failed\n",
1587 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001588 return -ENOMEM;
1589 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001590
1591 size = ((ndomains >> 8) + 1) * sizeof(struct dmar_domain **);
1592 iommu->domains = kzalloc(size, GFP_KERNEL);
1593
1594 if (iommu->domains) {
1595 size = 256 * sizeof(struct dmar_domain *);
1596 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1597 }
1598
1599 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001600 pr_err("%s: Allocating domain array failed\n",
1601 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001602 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001603 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001604 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001605 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001606 return -ENOMEM;
1607 }
1608
Joerg Roedel8bf47812015-07-21 10:41:21 +02001609
1610
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001611 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001612 * If Caching mode is set, then invalid translations are tagged
1613 * with domain-id 0, hence we need to pre-allocate it. We also
1614 * use domain-id 0 as a marker for non-allocated domain-id, so
1615 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001616 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001617 set_bit(0, iommu->domain_ids);
1618
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001619 return 0;
1620}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001621
Jiang Liuffebeb42014-11-09 22:48:02 +08001622static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001623{
Joerg Roedel29a27712015-07-21 17:17:12 +02001624 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001625 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001626
Joerg Roedel29a27712015-07-21 17:17:12 +02001627 if (!iommu->domains || !iommu->domain_ids)
1628 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001629
Joerg Roedel55d94042015-07-22 16:50:40 +02001630 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001631 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
1632 struct dmar_domain *domain;
1633
1634 if (info->iommu != iommu)
1635 continue;
1636
1637 if (!info->dev || !info->domain)
1638 continue;
1639
1640 domain = info->domain;
1641
Joerg Roedele6de0f82015-07-22 16:30:36 +02001642 dmar_remove_one_dev_info(domain, info->dev);
Joerg Roedel29a27712015-07-21 17:17:12 +02001643
1644 if (!domain_type_is_vm_or_si(domain))
1645 domain_exit(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001646 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001647 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001648
1649 if (iommu->gcmd & DMA_GCMD_TE)
1650 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001651}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001652
Jiang Liuffebeb42014-11-09 22:48:02 +08001653static void free_dmar_iommu(struct intel_iommu *iommu)
1654{
1655 if ((iommu->domains) && (iommu->domain_ids)) {
Joerg Roedel8bf47812015-07-21 10:41:21 +02001656 int elems = (cap_ndoms(iommu->cap) >> 8) + 1;
1657 int i;
1658
1659 for (i = 0; i < elems; i++)
1660 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001661 kfree(iommu->domains);
1662 kfree(iommu->domain_ids);
1663 iommu->domains = NULL;
1664 iommu->domain_ids = NULL;
1665 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001666
Weidong Hand9630fe2008-12-08 11:06:32 +08001667 g_iommus[iommu->seq_id] = NULL;
1668
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001669 /* free context mapping */
1670 free_context_table(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001671}
1672
Jiang Liuab8dfe22014-07-11 14:19:27 +08001673static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001674{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001675 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001676
1677 domain = alloc_domain_mem();
1678 if (!domain)
1679 return NULL;
1680
Jiang Liuab8dfe22014-07-11 14:19:27 +08001681 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001682 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001683 domain->flags = flags;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001684 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001685
1686 return domain;
1687}
1688
Joerg Roedeld160aca2015-07-22 11:52:53 +02001689/* Must be called with iommu->lock */
1690static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001691 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001692{
Jiang Liu44bde612014-07-11 14:19:29 +08001693 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001694 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001695
Joerg Roedel55d94042015-07-22 16:50:40 +02001696 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001697 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001698
Joerg Roedel29a27712015-07-21 17:17:12 +02001699 domain->iommu_refcnt[iommu->seq_id] += 1;
1700 domain->iommu_count += 1;
1701 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001702 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001703 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1704
1705 if (num >= ndomains) {
1706 pr_err("%s: No free domain ids\n", iommu->name);
1707 domain->iommu_refcnt[iommu->seq_id] -= 1;
1708 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001709 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001710 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711
Joerg Roedeld160aca2015-07-22 11:52:53 +02001712 set_bit(num, iommu->domain_ids);
1713 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001714
Joerg Roedeld160aca2015-07-22 11:52:53 +02001715 domain->iommu_did[iommu->seq_id] = num;
1716 domain->nid = iommu->node;
1717
Jiang Liufb170fb2014-07-11 14:19:28 +08001718 domain_update_iommu_cap(domain);
1719 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001720
Joerg Roedel55d94042015-07-22 16:50:40 +02001721 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001722}
1723
1724static int domain_detach_iommu(struct dmar_domain *domain,
1725 struct intel_iommu *iommu)
1726{
Joerg Roedeld160aca2015-07-22 11:52:53 +02001727 int num, count = INT_MAX;
Jiang Liufb170fb2014-07-11 14:19:28 +08001728
Joerg Roedel55d94042015-07-22 16:50:40 +02001729 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001730 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001731
Joerg Roedel29a27712015-07-21 17:17:12 +02001732 domain->iommu_refcnt[iommu->seq_id] -= 1;
1733 count = --domain->iommu_count;
1734 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001735 num = domain->iommu_did[iommu->seq_id];
1736 clear_bit(num, iommu->domain_ids);
1737 set_iommu_domain(iommu, num, NULL);
1738
Jiang Liufb170fb2014-07-11 14:19:28 +08001739 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001740 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001741 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001742
1743 return count;
1744}
1745
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001746static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001747static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001748
Joseph Cihula51a63e62011-03-21 11:04:24 -07001749static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001750{
1751 struct pci_dev *pdev = NULL;
1752 struct iova *iova;
1753 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001754
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001755 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN,
1756 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001757
Mark Gross8a443df2008-03-04 14:59:31 -08001758 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1759 &reserved_rbtree_key);
1760
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001761 /* IOAPIC ranges shouldn't be accessed by DMA */
1762 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1763 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001764 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001765 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001766 return -ENODEV;
1767 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001768
1769 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1770 for_each_pci_dev(pdev) {
1771 struct resource *r;
1772
1773 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1774 r = &pdev->resource[i];
1775 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1776 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001777 iova = reserve_iova(&reserved_iova_list,
1778 IOVA_PFN(r->start),
1779 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001780 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001781 pr_err("Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001782 return -ENODEV;
1783 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001784 }
1785 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001786 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001787}
1788
1789static void domain_reserve_special_ranges(struct dmar_domain *domain)
1790{
1791 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1792}
1793
1794static inline int guestwidth_to_adjustwidth(int gaw)
1795{
1796 int agaw;
1797 int r = (gaw - 12) % 9;
1798
1799 if (r == 0)
1800 agaw = gaw;
1801 else
1802 agaw = gaw + 9 - r;
1803 if (agaw > 64)
1804 agaw = 64;
1805 return agaw;
1806}
1807
Joerg Roedeldc534b22015-07-22 12:44:02 +02001808static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1809 int guest_width)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001810{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001811 int adjust_width, agaw;
1812 unsigned long sagaw;
1813
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001814 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
1815 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001816 domain_reserve_special_ranges(domain);
1817
1818 /* calculate AGAW */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001819 if (guest_width > cap_mgaw(iommu->cap))
1820 guest_width = cap_mgaw(iommu->cap);
1821 domain->gaw = guest_width;
1822 adjust_width = guestwidth_to_adjustwidth(guest_width);
1823 agaw = width_to_agaw(adjust_width);
1824 sagaw = cap_sagaw(iommu->cap);
1825 if (!test_bit(agaw, &sagaw)) {
1826 /* hardware doesn't support it, choose a bigger one */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001827 pr_debug("Hardware doesn't support agaw %d\n", agaw);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001828 agaw = find_next_bit(&sagaw, 5, agaw);
1829 if (agaw >= 5)
1830 return -ENODEV;
1831 }
1832 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001833
Weidong Han8e6040972008-12-08 15:49:06 +08001834 if (ecap_coherent(iommu->ecap))
1835 domain->iommu_coherency = 1;
1836 else
1837 domain->iommu_coherency = 0;
1838
Sheng Yang58c610b2009-03-18 15:33:05 +08001839 if (ecap_sc_support(iommu->ecap))
1840 domain->iommu_snooping = 1;
1841 else
1842 domain->iommu_snooping = 0;
1843
David Woodhouse214e39a2014-03-19 10:38:49 +00001844 if (intel_iommu_superpage)
1845 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1846 else
1847 domain->iommu_superpage = 0;
1848
Suresh Siddha4c923d42009-10-02 11:01:24 -07001849 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001850
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001851 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001852 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001853 if (!domain->pgd)
1854 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001855 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001856 return 0;
1857}
1858
1859static void domain_exit(struct dmar_domain *domain)
1860{
David Woodhouseea8ea462014-03-05 17:09:32 +00001861 struct page *freelist = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001862
1863 /* Domain 0 is reserved, so dont process it */
1864 if (!domain)
1865 return;
1866
Alex Williamson7b668352011-05-24 12:02:41 +01001867 /* Flush any lazy unmaps that may reference this domain */
1868 if (!intel_iommu_strict)
1869 flush_unmaps_timeout(0);
1870
Joerg Roedeld160aca2015-07-22 11:52:53 +02001871 /* Remove associated devices and clear attached or cached domains */
1872 rcu_read_lock();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001873 domain_remove_dev_info(domain);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001874 rcu_read_unlock();
Jiang Liu92d03cc2014-02-19 14:07:28 +08001875
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001876 /* destroy iovas */
1877 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001878
David Woodhouseea8ea462014-03-05 17:09:32 +00001879 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001880
David Woodhouseea8ea462014-03-05 17:09:32 +00001881 dma_free_pagelist(freelist);
1882
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001883 free_domain_mem(domain);
1884}
1885
David Woodhouse64ae8922014-03-09 12:52:30 -07001886static int domain_context_mapping_one(struct dmar_domain *domain,
1887 struct intel_iommu *iommu,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001888 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001889{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001890 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02001891 int translation = CONTEXT_TT_MULTI_LEVEL;
1892 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001893 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001894 unsigned long flags;
Weidong Hanea6606b2008-12-08 23:08:15 +08001895 struct dma_pte *pgd;
Joerg Roedel55d94042015-07-22 16:50:40 +02001896 int ret, agaw;
Joerg Roedel28ccce02015-07-21 14:45:31 +02001897
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001898 WARN_ON(did == 0);
1899
Joerg Roedel28ccce02015-07-21 14:45:31 +02001900 if (hw_pass_through && domain_type_is_si(domain))
1901 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001902
1903 pr_debug("Set context mapping for %02x:%02x.%d\n",
1904 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001905
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001906 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08001907
Joerg Roedel55d94042015-07-22 16:50:40 +02001908 spin_lock_irqsave(&device_domain_lock, flags);
1909 spin_lock(&iommu->lock);
1910
1911 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00001912 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001913 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02001914 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001915
Joerg Roedel55d94042015-07-22 16:50:40 +02001916 ret = 0;
1917 if (context_present(context))
1918 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02001919
Weidong Hanea6606b2008-12-08 23:08:15 +08001920 pgd = domain->pgd;
1921
Joerg Roedelde24e552015-07-21 14:53:04 +02001922 context_clear_entry(context);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001923 context_set_domain_id(context, did);
Weidong Hanea6606b2008-12-08 23:08:15 +08001924
Joerg Roedelde24e552015-07-21 14:53:04 +02001925 /*
1926 * Skip top levels of page tables for iommu which has less agaw
1927 * than default. Unnecessary for PT mode.
1928 */
Yu Zhao93a23a72009-05-18 13:51:37 +08001929 if (translation != CONTEXT_TT_PASS_THROUGH) {
Joerg Roedelde24e552015-07-21 14:53:04 +02001930 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
Joerg Roedel55d94042015-07-22 16:50:40 +02001931 ret = -ENOMEM;
Joerg Roedelde24e552015-07-21 14:53:04 +02001932 pgd = phys_to_virt(dma_pte_addr(pgd));
Joerg Roedel55d94042015-07-22 16:50:40 +02001933 if (!dma_pte_present(pgd))
1934 goto out_unlock;
Joerg Roedelde24e552015-07-21 14:53:04 +02001935 }
1936
David Woodhouse64ae8922014-03-09 12:52:30 -07001937 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
Yu Zhao93a23a72009-05-18 13:51:37 +08001938 translation = info ? CONTEXT_TT_DEV_IOTLB :
1939 CONTEXT_TT_MULTI_LEVEL;
Joerg Roedelde24e552015-07-21 14:53:04 +02001940
Yu Zhao93a23a72009-05-18 13:51:37 +08001941 context_set_address_root(context, virt_to_phys(pgd));
1942 context_set_address_width(context, iommu->agaw);
Joerg Roedelde24e552015-07-21 14:53:04 +02001943 } else {
1944 /*
1945 * In pass through mode, AW must be programmed to
1946 * indicate the largest AGAW value supported by
1947 * hardware. And ASR is ignored by hardware.
1948 */
1949 context_set_address_width(context, iommu->msagaw);
Yu Zhao93a23a72009-05-18 13:51:37 +08001950 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001951
1952 context_set_translation_type(context, translation);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001953 context_set_fault_enable(context);
1954 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08001955 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001956
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001957 /*
1958 * It's a non-present to present mapping. If hardware doesn't cache
1959 * non-present entry we only need to flush the write-buffer. If the
1960 * _does_ cache non-present entries, then it does so in the special
1961 * domain #0, which we have to flush:
1962 */
1963 if (cap_caching_mode(iommu->cap)) {
1964 iommu->flush.flush_context(iommu, 0,
1965 (((u16)bus) << 8) | devfn,
1966 DMA_CCMD_MASK_NOBIT,
1967 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001968 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001969 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001970 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001971 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001972 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08001973
Joerg Roedel55d94042015-07-22 16:50:40 +02001974 ret = 0;
1975
1976out_unlock:
1977 spin_unlock(&iommu->lock);
1978 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001979
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001980 return 0;
1981}
1982
Alex Williamson579305f2014-07-03 09:51:43 -06001983struct domain_context_mapping_data {
1984 struct dmar_domain *domain;
1985 struct intel_iommu *iommu;
Alex Williamson579305f2014-07-03 09:51:43 -06001986};
1987
1988static int domain_context_mapping_cb(struct pci_dev *pdev,
1989 u16 alias, void *opaque)
1990{
1991 struct domain_context_mapping_data *data = opaque;
1992
1993 return domain_context_mapping_one(data->domain, data->iommu,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001994 PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06001995}
1996
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001997static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02001998domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001999{
David Woodhouse64ae8922014-03-09 12:52:30 -07002000 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002001 u8 bus, devfn;
Alex Williamson579305f2014-07-03 09:51:43 -06002002 struct domain_context_mapping_data data;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002003
David Woodhousee1f167f2014-03-09 15:24:46 -07002004 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002005 if (!iommu)
2006 return -ENODEV;
2007
Alex Williamson579305f2014-07-03 09:51:43 -06002008 if (!dev_is_pci(dev))
Joerg Roedel28ccce02015-07-21 14:45:31 +02002009 return domain_context_mapping_one(domain, iommu, bus, devfn);
Alex Williamson579305f2014-07-03 09:51:43 -06002010
2011 data.domain = domain;
2012 data.iommu = iommu;
Alex Williamson579305f2014-07-03 09:51:43 -06002013
2014 return pci_for_each_dma_alias(to_pci_dev(dev),
2015 &domain_context_mapping_cb, &data);
2016}
2017
2018static int domain_context_mapped_cb(struct pci_dev *pdev,
2019 u16 alias, void *opaque)
2020{
2021 struct intel_iommu *iommu = opaque;
2022
2023 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002024}
2025
David Woodhousee1f167f2014-03-09 15:24:46 -07002026static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002027{
Weidong Han5331fe62008-12-08 23:00:00 +08002028 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002029 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002030
David Woodhousee1f167f2014-03-09 15:24:46 -07002031 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002032 if (!iommu)
2033 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002034
Alex Williamson579305f2014-07-03 09:51:43 -06002035 if (!dev_is_pci(dev))
2036 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002037
Alex Williamson579305f2014-07-03 09:51:43 -06002038 return !pci_for_each_dma_alias(to_pci_dev(dev),
2039 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002040}
2041
Fenghua Yuf5329592009-08-04 15:09:37 -07002042/* Returns a number of VTD pages, but aligned to MM page size */
2043static inline unsigned long aligned_nrpages(unsigned long host_addr,
2044 size_t size)
2045{
2046 host_addr &= ~PAGE_MASK;
2047 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2048}
2049
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002050/* Return largest possible superpage level for a given mapping */
2051static inline int hardware_largepage_caps(struct dmar_domain *domain,
2052 unsigned long iov_pfn,
2053 unsigned long phy_pfn,
2054 unsigned long pages)
2055{
2056 int support, level = 1;
2057 unsigned long pfnmerge;
2058
2059 support = domain->iommu_superpage;
2060
2061 /* To use a large page, the virtual *and* physical addresses
2062 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2063 of them will mean we have to use smaller pages. So just
2064 merge them and check both at once. */
2065 pfnmerge = iov_pfn | phy_pfn;
2066
2067 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2068 pages >>= VTD_STRIDE_SHIFT;
2069 if (!pages)
2070 break;
2071 pfnmerge >>= VTD_STRIDE_SHIFT;
2072 level++;
2073 support--;
2074 }
2075 return level;
2076}
2077
David Woodhouse9051aa02009-06-29 12:30:54 +01002078static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2079 struct scatterlist *sg, unsigned long phys_pfn,
2080 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002081{
2082 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002083 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002084 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002085 unsigned int largepage_lvl = 0;
2086 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01002087
Jiang Liu162d1b12014-07-11 14:19:35 +08002088 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002089
2090 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2091 return -EINVAL;
2092
2093 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
2094
Jiang Liucc4f14a2014-11-26 09:42:10 +08002095 if (!sg) {
2096 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01002097 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
2098 }
2099
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002100 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002101 uint64_t tmp;
2102
David Woodhousee1605492009-06-29 11:17:38 +01002103 if (!sg_res) {
Fenghua Yuf5329592009-08-04 15:09:37 -07002104 sg_res = aligned_nrpages(sg->offset, sg->length);
David Woodhousee1605492009-06-29 11:17:38 +01002105 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
2106 sg->dma_length = sg->length;
Dan Williamsdb0fa0c2015-08-17 08:13:26 -06002107 pteval = (sg_phys(sg) & PAGE_MASK) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002108 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002109 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002110
David Woodhousee1605492009-06-29 11:17:38 +01002111 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002112 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2113
David Woodhouse5cf0a762014-03-19 16:07:49 +00002114 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002115 if (!pte)
2116 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002117 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002118 if (largepage_lvl > 1) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002119 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002120 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2121 /*
2122 * Ensure that old small page tables are
2123 * removed to make room for superpage,
2124 * if they exist.
2125 */
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002126 dma_pte_free_pagetable(domain, iov_pfn,
Jiang Liud41a4ad2014-07-11 14:19:34 +08002127 iov_pfn + lvl_pages - 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002128 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002129 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002130 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002131
David Woodhousee1605492009-06-29 11:17:38 +01002132 }
2133 /* We don't need lock here, nobody else
2134 * touches the iova range
2135 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002136 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002137 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002138 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002139 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2140 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002141 if (dumps) {
2142 dumps--;
2143 debug_dma_dump_mappings(NULL);
2144 }
2145 WARN_ON(1);
2146 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002147
2148 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2149
2150 BUG_ON(nr_pages < lvl_pages);
2151 BUG_ON(sg_res < lvl_pages);
2152
2153 nr_pages -= lvl_pages;
2154 iov_pfn += lvl_pages;
2155 phys_pfn += lvl_pages;
2156 pteval += lvl_pages * VTD_PAGE_SIZE;
2157 sg_res -= lvl_pages;
2158
2159 /* If the next PTE would be the first in a new page, then we
2160 need to flush the cache on the entries we've just written.
2161 And then we'll need to recalculate 'pte', so clear it and
2162 let it get set again in the if (!pte) block above.
2163
2164 If we're done (!nr_pages) we need to flush the cache too.
2165
2166 Also if we've been setting superpages, we may need to
2167 recalculate 'pte' and switch back to smaller pages for the
2168 end of the mapping, if the trailing size is not enough to
2169 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002170 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002171 if (!nr_pages || first_pte_in_page(pte) ||
2172 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002173 domain_flush_cache(domain, first_pte,
2174 (void *)pte - (void *)first_pte);
2175 pte = NULL;
2176 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002177
2178 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002179 sg = sg_next(sg);
2180 }
2181 return 0;
2182}
2183
David Woodhouse9051aa02009-06-29 12:30:54 +01002184static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2185 struct scatterlist *sg, unsigned long nr_pages,
2186 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002187{
David Woodhouse9051aa02009-06-29 12:30:54 +01002188 return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
2189}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002190
David Woodhouse9051aa02009-06-29 12:30:54 +01002191static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2192 unsigned long phys_pfn, unsigned long nr_pages,
2193 int prot)
2194{
2195 return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002196}
2197
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002198static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002199{
Weidong Hanc7151a82008-12-08 22:51:37 +08002200 if (!iommu)
2201 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002202
2203 clear_context_table(iommu, bus, devfn);
2204 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002205 DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002206 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002207}
2208
David Woodhouse109b9b02012-05-25 17:43:02 +01002209static inline void unlink_domain_info(struct device_domain_info *info)
2210{
2211 assert_spin_locked(&device_domain_lock);
2212 list_del(&info->link);
2213 list_del(&info->global);
2214 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002215 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002216}
2217
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002218static void domain_remove_dev_info(struct dmar_domain *domain)
2219{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002220 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002221 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002222
2223 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002224 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002225 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002226 spin_unlock_irqrestore(&device_domain_lock, flags);
2227}
2228
2229/*
2230 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002231 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002232 */
David Woodhouse1525a292014-03-06 16:19:30 +00002233static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002234{
2235 struct device_domain_info *info;
2236
2237 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002238 info = dev->archdata.iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002239 if (info)
2240 return info->domain;
2241 return NULL;
2242}
2243
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002244static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002245dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2246{
2247 struct device_domain_info *info;
2248
2249 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002250 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002251 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002252 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002253
2254 return NULL;
2255}
2256
Joerg Roedel5db31562015-07-22 12:40:43 +02002257static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2258 int bus, int devfn,
2259 struct device *dev,
2260 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002261{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002262 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002263 struct device_domain_info *info;
2264 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002265 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002266
2267 info = alloc_devinfo_mem();
2268 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002269 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002270
Jiang Liu745f2582014-02-19 14:07:26 +08002271 info->bus = bus;
2272 info->devfn = devfn;
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05002273 info->ats.enabled = 0;
2274 info->ats.qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002275 info->dev = dev;
2276 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002277 info->iommu = iommu;
Jiang Liu745f2582014-02-19 14:07:26 +08002278
2279 spin_lock_irqsave(&device_domain_lock, flags);
2280 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002281 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002282
2283 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002284 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002285 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002286 if (info2) {
2287 found = info2->domain;
2288 info2->dev = dev;
2289 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002290 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002291
Jiang Liu745f2582014-02-19 14:07:26 +08002292 if (found) {
2293 spin_unlock_irqrestore(&device_domain_lock, flags);
2294 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002295 /* Caller must free the original domain */
2296 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002297 }
2298
Joerg Roedeld160aca2015-07-22 11:52:53 +02002299 spin_lock(&iommu->lock);
2300 ret = domain_attach_iommu(domain, iommu);
2301 spin_unlock(&iommu->lock);
2302
2303 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002304 spin_unlock_irqrestore(&device_domain_lock, flags);
2305 return NULL;
2306 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002307
David Woodhouseb718cd32014-03-09 13:11:33 -07002308 list_add(&info->link, &domain->devices);
2309 list_add(&info->global, &device_domain_list);
2310 if (dev)
2311 dev->archdata.iommu = info;
2312 spin_unlock_irqrestore(&device_domain_lock, flags);
2313
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002314 if (dev && domain_context_mapping(domain, dev)) {
2315 pr_err("Domain context map for %s failed\n", dev_name(dev));
Joerg Roedele6de0f82015-07-22 16:30:36 +02002316 dmar_remove_one_dev_info(domain, dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002317 return NULL;
2318 }
2319
David Woodhouseb718cd32014-03-09 13:11:33 -07002320 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002321}
2322
Alex Williamson579305f2014-07-03 09:51:43 -06002323static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2324{
2325 *(u16 *)opaque = alias;
2326 return 0;
2327}
2328
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002329/* domain is initialized */
David Woodhouse146922e2014-03-09 15:44:17 -07002330static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002331{
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002332 struct device_domain_info *info = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002333 struct dmar_domain *domain, *tmp;
2334 struct intel_iommu *iommu;
Joerg Roedel08a7f452015-07-23 18:09:11 +02002335 u16 req_id, dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002336 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002337 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002338
David Woodhouse146922e2014-03-09 15:44:17 -07002339 domain = find_domain(dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002340 if (domain)
2341 return domain;
2342
David Woodhouse146922e2014-03-09 15:44:17 -07002343 iommu = device_to_iommu(dev, &bus, &devfn);
2344 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002345 return NULL;
2346
Joerg Roedel08a7f452015-07-23 18:09:11 +02002347 req_id = ((u16)bus << 8) | devfn;
2348
Alex Williamson579305f2014-07-03 09:51:43 -06002349 if (dev_is_pci(dev)) {
2350 struct pci_dev *pdev = to_pci_dev(dev);
2351
2352 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2353
2354 spin_lock_irqsave(&device_domain_lock, flags);
2355 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2356 PCI_BUS_NUM(dma_alias),
2357 dma_alias & 0xff);
2358 if (info) {
2359 iommu = info->iommu;
2360 domain = info->domain;
2361 }
2362 spin_unlock_irqrestore(&device_domain_lock, flags);
2363
2364 /* DMA alias already has a domain, uses it */
2365 if (info)
2366 goto found_domain;
2367 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002368
David Woodhouse146922e2014-03-09 15:44:17 -07002369 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002370 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002371 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002372 return NULL;
Joerg Roedeldc534b22015-07-22 12:44:02 +02002373 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002374 domain_exit(domain);
2375 return NULL;
2376 }
2377
2378 /* register PCI DMA alias device */
Joerg Roedel08a7f452015-07-23 18:09:11 +02002379 if (req_id != dma_alias && dev_is_pci(dev)) {
Joerg Roedel5db31562015-07-22 12:40:43 +02002380 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2381 dma_alias & 0xff, NULL, domain);
Alex Williamson579305f2014-07-03 09:51:43 -06002382
2383 if (!tmp || tmp != domain) {
2384 domain_exit(domain);
2385 domain = tmp;
2386 }
2387
David Woodhouseb718cd32014-03-09 13:11:33 -07002388 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002389 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002390 }
2391
2392found_domain:
Joerg Roedel5db31562015-07-22 12:40:43 +02002393 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
Alex Williamson579305f2014-07-03 09:51:43 -06002394
2395 if (!tmp || tmp != domain) {
2396 domain_exit(domain);
2397 domain = tmp;
2398 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002399
2400 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002401}
2402
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002403static int iommu_identity_mapping;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002404#define IDENTMAP_ALL 1
2405#define IDENTMAP_GFX 2
2406#define IDENTMAP_AZALIA 4
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002407
David Woodhouseb2132032009-06-26 18:50:28 +01002408static int iommu_domain_identity_map(struct dmar_domain *domain,
2409 unsigned long long start,
2410 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002411{
David Woodhousec5395d52009-06-28 16:35:56 +01002412 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2413 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002414
David Woodhousec5395d52009-06-28 16:35:56 +01002415 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2416 dma_to_mm_pfn(last_vpfn))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002417 pr_err("Reserving iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002418 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002419 }
2420
Joerg Roedelaf1089c2015-07-21 15:45:19 +02002421 pr_debug("Mapping reserved region %llx-%llx\n", start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002422 /*
2423 * RMRR range might have overlap with physical memory range,
2424 * clear it first
2425 */
David Woodhousec5395d52009-06-28 16:35:56 +01002426 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002427
David Woodhousec5395d52009-06-28 16:35:56 +01002428 return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
2429 last_vpfn - first_vpfn + 1,
David Woodhouse61df7442009-06-28 11:55:58 +01002430 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002431}
2432
Joerg Roedeld66ce542015-09-23 19:00:10 +02002433static int domain_prepare_identity_map(struct device *dev,
2434 struct dmar_domain *domain,
2435 unsigned long long start,
2436 unsigned long long end)
David Woodhouseb2132032009-06-26 18:50:28 +01002437{
David Woodhouse19943b02009-08-04 16:19:20 +01002438 /* For _hardware_ passthrough, don't bother. But for software
2439 passthrough, we do it anyway -- it may indicate a memory
2440 range which is reserved in E820, so which didn't get set
2441 up to start with in si_domain */
2442 if (domain == si_domain && hw_pass_through) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002443 pr_warn("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
2444 dev_name(dev), start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002445 return 0;
2446 }
2447
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002448 pr_info("Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
2449 dev_name(dev), start, end);
2450
David Woodhouse5595b522009-12-02 09:21:55 +00002451 if (end < start) {
2452 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2453 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2454 dmi_get_system_info(DMI_BIOS_VENDOR),
2455 dmi_get_system_info(DMI_BIOS_VERSION),
2456 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002457 return -EIO;
David Woodhouse5595b522009-12-02 09:21:55 +00002458 }
2459
David Woodhouse2ff729f2009-08-26 14:25:41 +01002460 if (end >> agaw_to_width(domain->agaw)) {
2461 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2462 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2463 agaw_to_width(domain->agaw),
2464 dmi_get_system_info(DMI_BIOS_VENDOR),
2465 dmi_get_system_info(DMI_BIOS_VERSION),
2466 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002467 return -EIO;
David Woodhouse2ff729f2009-08-26 14:25:41 +01002468 }
David Woodhouse19943b02009-08-04 16:19:20 +01002469
Joerg Roedeld66ce542015-09-23 19:00:10 +02002470 return iommu_domain_identity_map(domain, start, end);
2471}
2472
2473static int iommu_prepare_identity_map(struct device *dev,
2474 unsigned long long start,
2475 unsigned long long end)
2476{
2477 struct dmar_domain *domain;
2478 int ret;
2479
2480 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
2481 if (!domain)
2482 return -ENOMEM;
2483
2484 ret = domain_prepare_identity_map(dev, domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002485 if (ret)
Joerg Roedeld66ce542015-09-23 19:00:10 +02002486 domain_exit(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002487
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002488 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002489}
2490
2491static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002492 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002493{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002494 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002495 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002496 return iommu_prepare_identity_map(dev, rmrr->base_address,
2497 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002498}
2499
Suresh Siddhad3f13812011-08-23 17:05:25 -07002500#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002501static inline void iommu_prepare_isa(void)
2502{
2503 struct pci_dev *pdev;
2504 int ret;
2505
2506 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2507 if (!pdev)
2508 return;
2509
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002510 pr_info("Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002511 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002512
2513 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002514 pr_err("Failed to create 0-16MiB identity map - floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002515
Yijing Wang9b27e822014-05-20 20:37:52 +08002516 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002517}
2518#else
2519static inline void iommu_prepare_isa(void)
2520{
2521 return;
2522}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002523#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002524
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002525static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002526
Matt Kraai071e1372009-08-23 22:30:22 -07002527static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002528{
David Woodhousec7ab48d2009-06-26 19:10:36 +01002529 int nid, ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002530
Jiang Liuab8dfe22014-07-11 14:19:27 +08002531 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002532 if (!si_domain)
2533 return -EFAULT;
2534
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002535 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2536 domain_exit(si_domain);
2537 return -EFAULT;
2538 }
2539
Joerg Roedel0dc79712015-07-21 15:40:06 +02002540 pr_debug("Identity mapping domain allocated\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002541
David Woodhouse19943b02009-08-04 16:19:20 +01002542 if (hw)
2543 return 0;
2544
David Woodhousec7ab48d2009-06-26 19:10:36 +01002545 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002546 unsigned long start_pfn, end_pfn;
2547 int i;
2548
2549 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2550 ret = iommu_domain_identity_map(si_domain,
2551 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2552 if (ret)
2553 return ret;
2554 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002555 }
2556
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002557 return 0;
2558}
2559
David Woodhouse9b226622014-03-09 14:03:28 -07002560static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002561{
2562 struct device_domain_info *info;
2563
2564 if (likely(!iommu_identity_mapping))
2565 return 0;
2566
David Woodhouse9b226622014-03-09 14:03:28 -07002567 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002568 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2569 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002570
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002571 return 0;
2572}
2573
Joerg Roedel28ccce02015-07-21 14:45:31 +02002574static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002575{
David Woodhouse0ac72662014-03-09 13:19:22 -07002576 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002577 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002578 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002579
David Woodhouse5913c9b2014-03-09 16:27:31 -07002580 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002581 if (!iommu)
2582 return -ENODEV;
2583
Joerg Roedel5db31562015-07-22 12:40:43 +02002584 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002585 if (ndomain != domain)
2586 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002587
2588 return 0;
2589}
2590
David Woodhouse0b9d9752014-03-09 15:48:15 -07002591static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002592{
2593 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002594 struct device *tmp;
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002595 int i;
2596
Jiang Liu0e242612014-02-19 14:07:34 +08002597 rcu_read_lock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002598 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002599 /*
2600 * Return TRUE if this RMRR contains the device that
2601 * is passed in.
2602 */
2603 for_each_active_dev_scope(rmrr->devices,
2604 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002605 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002606 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002607 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002608 }
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002609 }
Jiang Liu0e242612014-02-19 14:07:34 +08002610 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002611 return false;
2612}
2613
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002614/*
2615 * There are a couple cases where we need to restrict the functionality of
2616 * devices associated with RMRRs. The first is when evaluating a device for
2617 * identity mapping because problems exist when devices are moved in and out
2618 * of domains and their respective RMRR information is lost. This means that
2619 * a device with associated RMRRs will never be in a "passthrough" domain.
2620 * The second is use of the device through the IOMMU API. This interface
2621 * expects to have full control of the IOVA space for the device. We cannot
2622 * satisfy both the requirement that RMRR access is maintained and have an
2623 * unencumbered IOVA space. We also have no ability to quiesce the device's
2624 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2625 * We therefore prevent devices associated with an RMRR from participating in
2626 * the IOMMU API, which eliminates them from device assignment.
2627 *
2628 * In both cases we assume that PCI USB devices with RMRRs have them largely
2629 * for historical reasons and that the RMRR space is not actively used post
2630 * boot. This exclusion may change if vendors begin to abuse it.
David Woodhouse18436af2015-03-25 15:05:47 +00002631 *
2632 * The same exception is made for graphics devices, with the requirement that
2633 * any use of the RMRR regions will be torn down before assigning the device
2634 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002635 */
2636static bool device_is_rmrr_locked(struct device *dev)
2637{
2638 if (!device_has_rmrr(dev))
2639 return false;
2640
2641 if (dev_is_pci(dev)) {
2642 struct pci_dev *pdev = to_pci_dev(dev);
2643
David Woodhouse18436af2015-03-25 15:05:47 +00002644 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002645 return false;
2646 }
2647
2648 return true;
2649}
2650
David Woodhouse3bdb2592014-03-09 16:03:08 -07002651static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002652{
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002653
David Woodhouse3bdb2592014-03-09 16:03:08 -07002654 if (dev_is_pci(dev)) {
2655 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002656
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002657 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002658 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002659
David Woodhouse3bdb2592014-03-09 16:03:08 -07002660 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2661 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002662
David Woodhouse3bdb2592014-03-09 16:03:08 -07002663 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2664 return 1;
2665
2666 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2667 return 0;
2668
2669 /*
2670 * We want to start off with all devices in the 1:1 domain, and
2671 * take them out later if we find they can't access all of memory.
2672 *
2673 * However, we can't do this for PCI devices behind bridges,
2674 * because all PCI devices behind the same bridge will end up
2675 * with the same source-id on their transactions.
2676 *
2677 * Practically speaking, we can't change things around for these
2678 * devices at run-time, because we can't be sure there'll be no
2679 * DMA transactions in flight for any of their siblings.
2680 *
2681 * So PCI devices (unless they're on the root bus) as well as
2682 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2683 * the 1:1 domain, just in _case_ one of their siblings turns out
2684 * not to be able to map all of memory.
2685 */
2686 if (!pci_is_pcie(pdev)) {
2687 if (!pci_is_root_bus(pdev->bus))
2688 return 0;
2689 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2690 return 0;
2691 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2692 return 0;
2693 } else {
2694 if (device_has_rmrr(dev))
2695 return 0;
2696 }
David Woodhouse6941af22009-07-04 18:24:27 +01002697
David Woodhouse3dfc8132009-07-04 19:11:08 +01002698 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002699 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002700 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002701 * take them out of the 1:1 domain later.
2702 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002703 if (!startup) {
2704 /*
2705 * If the device's dma_mask is less than the system's memory
2706 * size then this is not a candidate for identity mapping.
2707 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002708 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002709
David Woodhouse3bdb2592014-03-09 16:03:08 -07002710 if (dev->coherent_dma_mask &&
2711 dev->coherent_dma_mask < dma_mask)
2712 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002713
David Woodhouse3bdb2592014-03-09 16:03:08 -07002714 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05002715 }
David Woodhouse6941af22009-07-04 18:24:27 +01002716
2717 return 1;
2718}
2719
David Woodhousecf04eee2014-03-21 16:49:04 +00002720static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
2721{
2722 int ret;
2723
2724 if (!iommu_should_identity_map(dev, 1))
2725 return 0;
2726
Joerg Roedel28ccce02015-07-21 14:45:31 +02002727 ret = domain_add_dev_info(si_domain, dev);
David Woodhousecf04eee2014-03-21 16:49:04 +00002728 if (!ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002729 pr_info("%s identity mapping for device %s\n",
2730 hw ? "Hardware" : "Software", dev_name(dev));
David Woodhousecf04eee2014-03-21 16:49:04 +00002731 else if (ret == -ENODEV)
2732 /* device not associated with an iommu */
2733 ret = 0;
2734
2735 return ret;
2736}
2737
2738
Matt Kraai071e1372009-08-23 22:30:22 -07002739static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002740{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002741 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00002742 struct dmar_drhd_unit *drhd;
2743 struct intel_iommu *iommu;
2744 struct device *dev;
2745 int i;
2746 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002747
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002748 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00002749 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
2750 if (ret)
2751 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002752 }
2753
David Woodhousecf04eee2014-03-21 16:49:04 +00002754 for_each_active_iommu(iommu, drhd)
2755 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
2756 struct acpi_device_physical_node *pn;
2757 struct acpi_device *adev;
2758
2759 if (dev->bus != &acpi_bus_type)
2760 continue;
Joerg Roedel86080cc2015-06-12 12:27:16 +02002761
David Woodhousecf04eee2014-03-21 16:49:04 +00002762 adev= to_acpi_device(dev);
2763 mutex_lock(&adev->physical_node_lock);
2764 list_for_each_entry(pn, &adev->physical_node_list, node) {
2765 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
2766 if (ret)
2767 break;
2768 }
2769 mutex_unlock(&adev->physical_node_lock);
2770 if (ret)
2771 return ret;
2772 }
2773
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002774 return 0;
2775}
2776
Jiang Liuffebeb42014-11-09 22:48:02 +08002777static void intel_iommu_init_qi(struct intel_iommu *iommu)
2778{
2779 /*
2780 * Start from the sane iommu hardware state.
2781 * If the queued invalidation is already initialized by us
2782 * (for example, while enabling interrupt-remapping) then
2783 * we got the things already rolling from a sane state.
2784 */
2785 if (!iommu->qi) {
2786 /*
2787 * Clear any previous faults.
2788 */
2789 dmar_fault(-1, iommu);
2790 /*
2791 * Disable queued invalidation if supported and already enabled
2792 * before OS handover.
2793 */
2794 dmar_disable_qi(iommu);
2795 }
2796
2797 if (dmar_enable_qi(iommu)) {
2798 /*
2799 * Queued Invalidate not enabled, use Register Based Invalidate
2800 */
2801 iommu->flush.flush_context = __iommu_flush_context;
2802 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002803 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08002804 iommu->name);
2805 } else {
2806 iommu->flush.flush_context = qi_flush_context;
2807 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002808 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08002809 }
2810}
2811
Joerg Roedel091d42e2015-06-12 11:56:10 +02002812static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04002813 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02002814 struct context_entry **tbl,
2815 int bus, bool ext)
2816{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02002817 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002818 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04002819 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002820 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02002821 phys_addr_t old_ce_phys;
2822
2823 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04002824 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02002825
2826 for (devfn = 0; devfn < 256; devfn++) {
2827 /* First calculate the correct index */
2828 idx = (ext ? devfn * 2 : devfn) % 256;
2829
2830 if (idx == 0) {
2831 /* First save what we may have and clean up */
2832 if (new_ce) {
2833 tbl[tbl_idx] = new_ce;
2834 __iommu_flush_cache(iommu, new_ce,
2835 VTD_PAGE_SIZE);
2836 pos = 1;
2837 }
2838
2839 if (old_ce)
2840 iounmap(old_ce);
2841
2842 ret = 0;
2843 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002844 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002845 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02002846 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002847
2848 if (!old_ce_phys) {
2849 if (ext && devfn == 0) {
2850 /* No LCTP, try UCTP */
2851 devfn = 0x7f;
2852 continue;
2853 } else {
2854 goto out;
2855 }
2856 }
2857
2858 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04002859 old_ce = memremap(old_ce_phys, PAGE_SIZE,
2860 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002861 if (!old_ce)
2862 goto out;
2863
2864 new_ce = alloc_pgtable_page(iommu->node);
2865 if (!new_ce)
2866 goto out_unmap;
2867
2868 ret = 0;
2869 }
2870
2871 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04002872 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02002873
Joerg Roedelcf484d02015-06-12 12:21:46 +02002874 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02002875 continue;
2876
Joerg Roedeldbcd8612015-06-12 12:02:09 +02002877 did = context_domain_id(&ce);
2878 if (did >= 0 && did < cap_ndoms(iommu->cap))
2879 set_bit(did, iommu->domain_ids);
2880
Joerg Roedelcf484d02015-06-12 12:21:46 +02002881 /*
2882 * We need a marker for copied context entries. This
2883 * marker needs to work for the old format as well as
2884 * for extended context entries.
2885 *
2886 * Bit 67 of the context entry is used. In the old
2887 * format this bit is available to software, in the
2888 * extended format it is the PGE bit, but PGE is ignored
2889 * by HW if PASIDs are disabled (and thus still
2890 * available).
2891 *
2892 * So disable PASIDs first and then mark the entry
2893 * copied. This means that we don't copy PASID
2894 * translations from the old kernel, but this is fine as
2895 * faults there are not fatal.
2896 */
2897 context_clear_pasid_enable(&ce);
2898 context_set_copied(&ce);
2899
Joerg Roedel091d42e2015-06-12 11:56:10 +02002900 new_ce[idx] = ce;
2901 }
2902
2903 tbl[tbl_idx + pos] = new_ce;
2904
2905 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
2906
2907out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04002908 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002909
2910out:
2911 return ret;
2912}
2913
2914static int copy_translation_tables(struct intel_iommu *iommu)
2915{
2916 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04002917 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02002918 phys_addr_t old_rt_phys;
2919 int ctxt_table_entries;
2920 unsigned long flags;
2921 u64 rtaddr_reg;
2922 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02002923 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02002924
2925 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
2926 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02002927 new_ext = !!ecap_ecs(iommu->ecap);
2928
2929 /*
2930 * The RTT bit can only be changed when translation is disabled,
2931 * but disabling translation means to open a window for data
2932 * corruption. So bail out and don't copy anything if we would
2933 * have to change the bit.
2934 */
2935 if (new_ext != ext)
2936 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02002937
2938 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
2939 if (!old_rt_phys)
2940 return -EINVAL;
2941
Dan Williamsdfddb962015-10-09 18:16:46 -04002942 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002943 if (!old_rt)
2944 return -ENOMEM;
2945
2946 /* This is too big for the stack - allocate it from slab */
2947 ctxt_table_entries = ext ? 512 : 256;
2948 ret = -ENOMEM;
2949 ctxt_tbls = kzalloc(ctxt_table_entries * sizeof(void *), GFP_KERNEL);
2950 if (!ctxt_tbls)
2951 goto out_unmap;
2952
2953 for (bus = 0; bus < 256; bus++) {
2954 ret = copy_context_table(iommu, &old_rt[bus],
2955 ctxt_tbls, bus, ext);
2956 if (ret) {
2957 pr_err("%s: Failed to copy context table for bus %d\n",
2958 iommu->name, bus);
2959 continue;
2960 }
2961 }
2962
2963 spin_lock_irqsave(&iommu->lock, flags);
2964
2965 /* Context tables are copied, now write them to the root_entry table */
2966 for (bus = 0; bus < 256; bus++) {
2967 int idx = ext ? bus * 2 : bus;
2968 u64 val;
2969
2970 if (ctxt_tbls[idx]) {
2971 val = virt_to_phys(ctxt_tbls[idx]) | 1;
2972 iommu->root_entry[bus].lo = val;
2973 }
2974
2975 if (!ext || !ctxt_tbls[idx + 1])
2976 continue;
2977
2978 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
2979 iommu->root_entry[bus].hi = val;
2980 }
2981
2982 spin_unlock_irqrestore(&iommu->lock, flags);
2983
2984 kfree(ctxt_tbls);
2985
2986 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
2987
2988 ret = 0;
2989
2990out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04002991 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02002992
2993 return ret;
2994}
2995
Joseph Cihulab7792602011-05-03 00:08:37 -07002996static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002997{
2998 struct dmar_drhd_unit *drhd;
2999 struct dmar_rmrr_unit *rmrr;
Joerg Roedela87f4912015-06-12 12:32:54 +02003000 bool copied_tables = false;
David Woodhouse832bd852014-03-07 15:08:36 +00003001 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003002 struct intel_iommu *iommu;
Suresh Siddha9d783ba2009-03-16 17:04:55 -07003003 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003004
3005 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003006 * for each drhd
3007 * allocate root
3008 * initialize and program root entry to not present
3009 * endfor
3010 */
3011 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003012 /*
3013 * lock not needed as this is only incremented in the single
3014 * threaded kernel __init code path all other access are read
3015 * only
3016 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003017 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003018 g_num_of_iommus++;
3019 continue;
3020 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003021 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003022 }
3023
Jiang Liuffebeb42014-11-09 22:48:02 +08003024 /* Preallocate enough resources for IOMMU hot-addition */
3025 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3026 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3027
Weidong Hand9630fe2008-12-08 11:06:32 +08003028 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3029 GFP_KERNEL);
3030 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003031 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003032 ret = -ENOMEM;
3033 goto error;
3034 }
3035
mark gross80b20dd2008-04-18 13:53:58 -07003036 deferred_flush = kzalloc(g_num_of_iommus *
3037 sizeof(struct deferred_flush_tables), GFP_KERNEL);
3038 if (!deferred_flush) {
mark gross5e0d2a62008-03-04 15:22:08 -08003039 ret = -ENOMEM;
Jiang Liu989d51f2014-02-19 14:07:21 +08003040 goto free_g_iommus;
mark gross5e0d2a62008-03-04 15:22:08 -08003041 }
3042
Jiang Liu7c919772014-01-06 14:18:18 +08003043 for_each_active_iommu(iommu, drhd) {
Weidong Hand9630fe2008-12-08 11:06:32 +08003044 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003045
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003046 intel_iommu_init_qi(iommu);
3047
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003048 ret = iommu_init_domains(iommu);
3049 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003050 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003051
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003052 init_translation_status(iommu);
3053
Joerg Roedel091d42e2015-06-12 11:56:10 +02003054 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3055 iommu_disable_translation(iommu);
3056 clear_translation_pre_enabled(iommu);
3057 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3058 iommu->name);
3059 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003060
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003061 /*
3062 * TBD:
3063 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003064 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003065 */
3066 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003067 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003068 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003069
Joerg Roedel091d42e2015-06-12 11:56:10 +02003070 if (translation_pre_enabled(iommu)) {
3071 pr_info("Translation already enabled - trying to copy translation structures\n");
3072
3073 ret = copy_translation_tables(iommu);
3074 if (ret) {
3075 /*
3076 * We found the IOMMU with translation
3077 * enabled - but failed to copy over the
3078 * old root-entry table. Try to proceed
3079 * by disabling translation now and
3080 * allocating a clean root-entry table.
3081 * This might cause DMAR faults, but
3082 * probably the dump will still succeed.
3083 */
3084 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3085 iommu->name);
3086 iommu_disable_translation(iommu);
3087 clear_translation_pre_enabled(iommu);
3088 } else {
3089 pr_info("Copied translation tables from previous kernel for %s\n",
3090 iommu->name);
Joerg Roedela87f4912015-06-12 12:32:54 +02003091 copied_tables = true;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003092 }
3093 }
3094
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003095 iommu_flush_write_buffer(iommu);
3096 iommu_set_root_entry(iommu);
3097 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3098 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3099
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003100 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003101 hw_pass_through = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003102 }
3103
David Woodhouse19943b02009-08-04 16:19:20 +01003104 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07003105 iommu_identity_mapping |= IDENTMAP_ALL;
3106
Suresh Siddhad3f13812011-08-23 17:05:25 -07003107#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07003108 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01003109#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003110
Joerg Roedel86080cc2015-06-12 12:27:16 +02003111 if (iommu_identity_mapping) {
3112 ret = si_domain_init(hw_pass_through);
3113 if (ret)
3114 goto free_iommu;
3115 }
3116
David Woodhousee0fc7e02009-09-30 09:12:17 -07003117 check_tylersburg_isoch();
3118
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003119 /*
Joerg Roedela87f4912015-06-12 12:32:54 +02003120 * If we copied translations from a previous kernel in the kdump
3121 * case, we can not assign the devices to domains now, as that
3122 * would eliminate the old mappings. So skip this part and defer
3123 * the assignment to device driver initialization time.
3124 */
3125 if (copied_tables)
3126 goto domains_done;
3127
3128 /*
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003129 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003130 * identity mappings for rmrr, gfx, and isa and may fall back to static
3131 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003132 */
David Woodhouse19943b02009-08-04 16:19:20 +01003133 if (iommu_identity_mapping) {
3134 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
3135 if (ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003136 pr_crit("Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08003137 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003138 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003139 }
David Woodhouse19943b02009-08-04 16:19:20 +01003140 /*
3141 * For each rmrr
3142 * for each dev attached to rmrr
3143 * do
3144 * locate drhd for dev, alloc domain for dev
3145 * allocate free domain
3146 * allocate page table entries for rmrr
3147 * if context not allocated for bus
3148 * allocate and init context
3149 * set present in root table for this bus
3150 * init context with domain, translation etc
3151 * endfor
3152 * endfor
3153 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003154 pr_info("Setting RMRR:\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003155 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08003156 /* some BIOS lists non-exist devices in DMAR table. */
3157 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00003158 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07003159 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01003160 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003161 pr_err("Mapping reserved region failed\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003162 }
3163 }
3164
3165 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07003166
Joerg Roedela87f4912015-06-12 12:32:54 +02003167domains_done:
3168
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003169 /*
3170 * for each drhd
3171 * enable fault log
3172 * global invalidate context cache
3173 * global invalidate iotlb
3174 * enable translation
3175 */
Jiang Liu7c919772014-01-06 14:18:18 +08003176 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003177 if (drhd->ignored) {
3178 /*
3179 * we always have to disable PMRs or DMA may fail on
3180 * this device
3181 */
3182 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003183 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003184 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003185 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003186
3187 iommu_flush_write_buffer(iommu);
3188
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003189 ret = dmar_set_interrupt(iommu);
3190 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003191 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003192
Joerg Roedel8939ddf2015-06-12 14:40:01 +02003193 if (!translation_pre_enabled(iommu))
3194 iommu_enable_translation(iommu);
3195
David Woodhouseb94996c2009-09-19 15:28:12 -07003196 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003197 }
3198
3199 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003200
3201free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003202 for_each_active_iommu(iommu, drhd) {
3203 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003204 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003205 }
Jiang Liu9bdc5312014-01-06 14:18:27 +08003206 kfree(deferred_flush);
Jiang Liu989d51f2014-02-19 14:07:21 +08003207free_g_iommus:
Weidong Hand9630fe2008-12-08 11:06:32 +08003208 kfree(g_iommus);
Jiang Liu989d51f2014-02-19 14:07:21 +08003209error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003210 return ret;
3211}
3212
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003213/* This takes a number of _MM_ pages, not VTD pages */
David Woodhouse875764d2009-06-28 21:20:51 +01003214static struct iova *intel_alloc_iova(struct device *dev,
3215 struct dmar_domain *domain,
3216 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003217{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003218 struct iova *iova = NULL;
3219
David Woodhouse875764d2009-06-28 21:20:51 +01003220 /* Restrict dma_mask to the width that the iommu can handle */
3221 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
3222
3223 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003224 /*
3225 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003226 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003227 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003228 */
David Woodhouse875764d2009-06-28 21:20:51 +01003229 iova = alloc_iova(&domain->iovad, nrpages,
3230 IOVA_PFN(DMA_BIT_MASK(32)), 1);
3231 if (iova)
3232 return iova;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003233 }
David Woodhouse875764d2009-06-28 21:20:51 +01003234 iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
3235 if (unlikely(!iova)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003236 pr_err("Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07003237 nrpages, dev_name(dev));
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003238 return NULL;
3239 }
3240
3241 return iova;
3242}
3243
David Woodhoused4b709f2014-03-09 16:07:40 -07003244static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003245{
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003246 struct dmar_rmrr_unit *rmrr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003247 struct dmar_domain *domain;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003248 struct device *i_dev;
3249 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003250
David Woodhoused4b709f2014-03-09 16:07:40 -07003251 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003252 if (!domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003253 pr_err("Allocating domain for %s failed\n",
David Woodhoused4b709f2014-03-09 16:07:40 -07003254 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00003255 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003256 }
3257
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003258 /* We have a new domain - setup possible RMRRs for the device */
3259 rcu_read_lock();
3260 for_each_rmrr_units(rmrr) {
3261 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3262 i, i_dev) {
3263 if (i_dev != dev)
3264 continue;
3265
3266 ret = domain_prepare_identity_map(dev, domain,
3267 rmrr->base_address,
3268 rmrr->end_address);
3269 if (ret)
3270 dev_err(dev, "Mapping reserved region failed\n");
3271 }
3272 }
3273 rcu_read_unlock();
3274
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003275 return domain;
3276}
3277
David Woodhoused4b709f2014-03-09 16:07:40 -07003278static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
David Woodhouse147202a2009-07-07 19:43:20 +01003279{
3280 struct device_domain_info *info;
3281
3282 /* No lock here, assumes no domain exit in normal case */
David Woodhoused4b709f2014-03-09 16:07:40 -07003283 info = dev->archdata.iommu;
David Woodhouse147202a2009-07-07 19:43:20 +01003284 if (likely(info))
3285 return info->domain;
3286
3287 return __get_valid_domain_for_dev(dev);
3288}
3289
David Woodhouseecb509e2014-03-09 16:29:55 -07003290/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01003291static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003292{
3293 int found;
3294
David Woodhouse3d891942014-03-06 15:59:26 +00003295 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003296 return 1;
3297
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003298 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003299 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003300
David Woodhouse9b226622014-03-09 14:03:28 -07003301 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003302 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07003303 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003304 return 1;
3305 else {
3306 /*
3307 * 32 bit DMA is removed from si_domain and fall back
3308 * to non-identity mapping.
3309 */
Joerg Roedele6de0f82015-07-22 16:30:36 +02003310 dmar_remove_one_dev_info(si_domain, dev);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003311 pr_info("32bit %s uses non-identity mapping\n",
3312 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003313 return 0;
3314 }
3315 } else {
3316 /*
3317 * In case of a detached 64 bit DMA device from vm, the device
3318 * is put into si_domain for identity mapping.
3319 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003320 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003321 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02003322 ret = domain_add_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003323 if (!ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003324 pr_info("64bit %s uses identity mapping\n",
3325 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003326 return 1;
3327 }
3328 }
3329 }
3330
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003331 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003332}
3333
David Woodhouse5040a912014-03-09 16:14:00 -07003334static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003335 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003336{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003337 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003338 phys_addr_t start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003339 struct iova *iova;
3340 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003341 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003342 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003343 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003344
3345 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003346
David Woodhouse5040a912014-03-09 16:14:00 -07003347 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003348 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003349
David Woodhouse5040a912014-03-09 16:14:00 -07003350 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003351 if (!domain)
3352 return 0;
3353
Weidong Han8c11e792008-12-08 15:29:22 +08003354 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003355 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003356
David Woodhouse5040a912014-03-09 16:14:00 -07003357 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003358 if (!iova)
3359 goto error;
3360
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003361 /*
3362 * Check if DMAR supports zero-length reads on write only
3363 * mappings..
3364 */
3365 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003366 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003367 prot |= DMA_PTE_READ;
3368 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3369 prot |= DMA_PTE_WRITE;
3370 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003371 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003372 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003373 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003374 * is not a big problem
3375 */
David Woodhouse0ab36de2009-06-28 14:01:43 +01003376 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003377 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003378 if (ret)
3379 goto error;
3380
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003381 /* it's a non-present to present mapping. Only flush if caching mode */
3382 if (cap_caching_mode(iommu->cap))
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003383 iommu_flush_iotlb_psi(iommu, domain,
3384 mm_to_dma_pfn(iova->pfn_lo),
3385 size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003386 else
Weidong Han8c11e792008-12-08 15:29:22 +08003387 iommu_flush_write_buffer(iommu);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003388
David Woodhouse03d6a242009-06-28 15:33:46 +01003389 start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
3390 start_paddr += paddr & ~PAGE_MASK;
3391 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003392
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003393error:
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003394 if (iova)
3395 __free_iova(&domain->iovad, iova);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003396 pr_err("Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003397 dev_name(dev), size, (unsigned long long)paddr, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003398 return 0;
3399}
3400
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003401static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3402 unsigned long offset, size_t size,
3403 enum dma_data_direction dir,
3404 struct dma_attrs *attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003405{
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003406 return __intel_map_single(dev, page_to_phys(page) + offset, size,
David Woodhouse46333e32014-03-10 20:01:21 -07003407 dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003408}
3409
mark gross5e0d2a62008-03-04 15:22:08 -08003410static void flush_unmaps(void)
3411{
mark gross80b20dd2008-04-18 13:53:58 -07003412 int i, j;
mark gross5e0d2a62008-03-04 15:22:08 -08003413
mark gross5e0d2a62008-03-04 15:22:08 -08003414 timer_on = 0;
3415
3416 /* just flush them all */
3417 for (i = 0; i < g_num_of_iommus; i++) {
Weidong Hana2bb8452008-12-08 11:24:12 +08003418 struct intel_iommu *iommu = g_iommus[i];
3419 if (!iommu)
3420 continue;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003421
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003422 if (!deferred_flush[i].next)
3423 continue;
3424
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003425 /* In caching mode, global flushes turn emulation expensive */
3426 if (!cap_caching_mode(iommu->cap))
3427 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
Yu Zhao93a23a72009-05-18 13:51:37 +08003428 DMA_TLB_GLOBAL_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003429 for (j = 0; j < deferred_flush[i].next; j++) {
Yu Zhao93a23a72009-05-18 13:51:37 +08003430 unsigned long mask;
3431 struct iova *iova = deferred_flush[i].iova[j];
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003432 struct dmar_domain *domain = deferred_flush[i].domain[j];
Yu Zhao93a23a72009-05-18 13:51:37 +08003433
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003434 /* On real hardware multiple invalidations are expensive */
3435 if (cap_caching_mode(iommu->cap))
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003436 iommu_flush_iotlb_psi(iommu, domain,
Jiang Liua156ef92014-07-11 14:19:36 +08003437 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00003438 !deferred_flush[i].freelist[j], 0);
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003439 else {
Jiang Liua156ef92014-07-11 14:19:36 +08003440 mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003441 iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
3442 (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
3443 }
Yu Zhao93a23a72009-05-18 13:51:37 +08003444 __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003445 if (deferred_flush[i].freelist[j])
3446 dma_free_pagelist(deferred_flush[i].freelist[j]);
mark gross80b20dd2008-04-18 13:53:58 -07003447 }
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003448 deferred_flush[i].next = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003449 }
3450
mark gross5e0d2a62008-03-04 15:22:08 -08003451 list_size = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003452}
3453
3454static void flush_unmaps_timeout(unsigned long data)
3455{
mark gross80b20dd2008-04-18 13:53:58 -07003456 unsigned long flags;
3457
3458 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003459 flush_unmaps();
mark gross80b20dd2008-04-18 13:53:58 -07003460 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003461}
3462
David Woodhouseea8ea462014-03-05 17:09:32 +00003463static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist)
mark gross5e0d2a62008-03-04 15:22:08 -08003464{
3465 unsigned long flags;
mark gross80b20dd2008-04-18 13:53:58 -07003466 int next, iommu_id;
Weidong Han8c11e792008-12-08 15:29:22 +08003467 struct intel_iommu *iommu;
mark gross5e0d2a62008-03-04 15:22:08 -08003468
3469 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross80b20dd2008-04-18 13:53:58 -07003470 if (list_size == HIGH_WATER_MARK)
3471 flush_unmaps();
3472
Weidong Han8c11e792008-12-08 15:29:22 +08003473 iommu = domain_get_iommu(dom);
3474 iommu_id = iommu->seq_id;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003475
mark gross80b20dd2008-04-18 13:53:58 -07003476 next = deferred_flush[iommu_id].next;
3477 deferred_flush[iommu_id].domain[next] = dom;
3478 deferred_flush[iommu_id].iova[next] = iova;
David Woodhouseea8ea462014-03-05 17:09:32 +00003479 deferred_flush[iommu_id].freelist[next] = freelist;
mark gross80b20dd2008-04-18 13:53:58 -07003480 deferred_flush[iommu_id].next++;
mark gross5e0d2a62008-03-04 15:22:08 -08003481
3482 if (!timer_on) {
3483 mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
3484 timer_on = 1;
3485 }
3486 list_size++;
3487 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
3488}
3489
Jiang Liud41a4ad2014-07-11 14:19:34 +08003490static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003491{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003492 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003493 unsigned long start_pfn, last_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003494 struct iova *iova;
Weidong Han8c11e792008-12-08 15:29:22 +08003495 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003496 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003497
David Woodhouse73676832009-07-04 14:08:36 +01003498 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003499 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003500
David Woodhouse1525a292014-03-06 16:19:30 +00003501 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003502 BUG_ON(!domain);
3503
Weidong Han8c11e792008-12-08 15:29:22 +08003504 iommu = domain_get_iommu(domain);
3505
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003506 iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
David Woodhouse85b98272009-07-01 19:27:53 +01003507 if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
3508 (unsigned long long)dev_addr))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003509 return;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003510
David Woodhoused794dc92009-06-28 00:27:49 +01003511 start_pfn = mm_to_dma_pfn(iova->pfn_lo);
3512 last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003513
David Woodhoused794dc92009-06-28 00:27:49 +01003514 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003515 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003516
David Woodhouseea8ea462014-03-05 17:09:32 +00003517 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003518
mark gross5e0d2a62008-03-04 15:22:08 -08003519 if (intel_iommu_strict) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003520 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
David Woodhouseea8ea462014-03-05 17:09:32 +00003521 last_pfn - start_pfn + 1, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003522 /* free iova */
3523 __free_iova(&domain->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003524 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003525 } else {
David Woodhouseea8ea462014-03-05 17:09:32 +00003526 add_unmap(domain, iova, freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003527 /*
3528 * queue up the release of the unmap to save the 1/6th of the
3529 * cpu used up by the iotlb flush operation...
3530 */
mark gross5e0d2a62008-03-04 15:22:08 -08003531 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003532}
3533
Jiang Liud41a4ad2014-07-11 14:19:34 +08003534static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3535 size_t size, enum dma_data_direction dir,
3536 struct dma_attrs *attrs)
3537{
3538 intel_unmap(dev, dev_addr);
3539}
3540
David Woodhouse5040a912014-03-09 16:14:00 -07003541static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003542 dma_addr_t *dma_handle, gfp_t flags,
3543 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003544{
Akinobu Mita36746432014-06-04 16:06:51 -07003545 struct page *page = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003546 int order;
3547
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003548 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003549 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003550
David Woodhouse5040a912014-03-09 16:14:00 -07003551 if (!iommu_no_mapping(dev))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003552 flags &= ~(GFP_DMA | GFP_DMA32);
David Woodhouse5040a912014-03-09 16:14:00 -07003553 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3554 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003555 flags |= GFP_DMA;
3556 else
3557 flags |= GFP_DMA32;
3558 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003559
Akinobu Mita36746432014-06-04 16:06:51 -07003560 if (flags & __GFP_WAIT) {
3561 unsigned int count = size >> PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003562
Akinobu Mita36746432014-06-04 16:06:51 -07003563 page = dma_alloc_from_contiguous(dev, count, order);
3564 if (page && iommu_no_mapping(dev) &&
3565 page_to_phys(page) + size > dev->coherent_dma_mask) {
3566 dma_release_from_contiguous(dev, page, count);
3567 page = NULL;
3568 }
3569 }
3570
3571 if (!page)
3572 page = alloc_pages(flags, order);
3573 if (!page)
3574 return NULL;
3575 memset(page_address(page), 0, size);
3576
3577 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003578 DMA_BIDIRECTIONAL,
David Woodhouse5040a912014-03-09 16:14:00 -07003579 dev->coherent_dma_mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003580 if (*dma_handle)
Akinobu Mita36746432014-06-04 16:06:51 -07003581 return page_address(page);
3582 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3583 __free_pages(page, order);
3584
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003585 return NULL;
3586}
3587
David Woodhouse5040a912014-03-09 16:14:00 -07003588static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003589 dma_addr_t dma_handle, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003590{
3591 int order;
Akinobu Mita36746432014-06-04 16:06:51 -07003592 struct page *page = virt_to_page(vaddr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003593
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003594 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003595 order = get_order(size);
3596
Jiang Liud41a4ad2014-07-11 14:19:34 +08003597 intel_unmap(dev, dma_handle);
Akinobu Mita36746432014-06-04 16:06:51 -07003598 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3599 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003600}
3601
David Woodhouse5040a912014-03-09 16:14:00 -07003602static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003603 int nelems, enum dma_data_direction dir,
3604 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003605{
Jiang Liud41a4ad2014-07-11 14:19:34 +08003606 intel_unmap(dev, sglist[0].dma_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003607}
3608
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003609static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003610 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003611{
3612 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003613 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003614
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003615 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003616 BUG_ON(!sg_page(sg));
Dan Williamsdb0fa0c2015-08-17 08:13:26 -06003617 sg->dma_address = sg_phys(sg);
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003618 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003619 }
3620 return nelems;
3621}
3622
David Woodhouse5040a912014-03-09 16:14:00 -07003623static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003624 enum dma_data_direction dir, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003625{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003626 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003627 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003628 size_t size = 0;
3629 int prot = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003630 struct iova *iova = NULL;
3631 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003632 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003633 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003634 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003635
3636 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003637 if (iommu_no_mapping(dev))
3638 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003639
David Woodhouse5040a912014-03-09 16:14:00 -07003640 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003641 if (!domain)
3642 return 0;
3643
Weidong Han8c11e792008-12-08 15:29:22 +08003644 iommu = domain_get_iommu(domain);
3645
David Woodhouseb536d242009-06-28 14:49:31 +01003646 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003647 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003648
David Woodhouse5040a912014-03-09 16:14:00 -07003649 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
3650 *dev->dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003651 if (!iova) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003652 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003653 return 0;
3654 }
3655
3656 /*
3657 * Check if DMAR supports zero-length reads on write only
3658 * mappings..
3659 */
3660 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003661 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003662 prot |= DMA_PTE_READ;
3663 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3664 prot |= DMA_PTE_WRITE;
3665
David Woodhouseb536d242009-06-28 14:49:31 +01003666 start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
David Woodhousee1605492009-06-29 11:17:38 +01003667
Fenghua Yuf5329592009-08-04 15:09:37 -07003668 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003669 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003670 dma_pte_free_pagetable(domain, start_vpfn,
3671 start_vpfn + size - 1);
David Woodhousee1605492009-06-29 11:17:38 +01003672 __free_iova(&domain->iovad, iova);
3673 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003674 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003675
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003676 /* it's a non-present to present mapping. Only flush if caching mode */
3677 if (cap_caching_mode(iommu->cap))
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003678 iommu_flush_iotlb_psi(iommu, domain, start_vpfn, size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003679 else
Weidong Han8c11e792008-12-08 15:29:22 +08003680 iommu_flush_write_buffer(iommu);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003681
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003682 return nelems;
3683}
3684
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003685static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
3686{
3687 return !dma_addr;
3688}
3689
FUJITA Tomonori160c1d82009-01-05 23:59:02 +09003690struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003691 .alloc = intel_alloc_coherent,
3692 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003693 .map_sg = intel_map_sg,
3694 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003695 .map_page = intel_map_page,
3696 .unmap_page = intel_unmap_page,
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003697 .mapping_error = intel_mapping_error,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003698};
3699
3700static inline int iommu_domain_cache_init(void)
3701{
3702 int ret = 0;
3703
3704 iommu_domain_cache = kmem_cache_create("iommu_domain",
3705 sizeof(struct dmar_domain),
3706 0,
3707 SLAB_HWCACHE_ALIGN,
3708
3709 NULL);
3710 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003711 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003712 ret = -ENOMEM;
3713 }
3714
3715 return ret;
3716}
3717
3718static inline int iommu_devinfo_cache_init(void)
3719{
3720 int ret = 0;
3721
3722 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3723 sizeof(struct device_domain_info),
3724 0,
3725 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003726 NULL);
3727 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003728 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729 ret = -ENOMEM;
3730 }
3731
3732 return ret;
3733}
3734
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003735static int __init iommu_init_mempool(void)
3736{
3737 int ret;
3738 ret = iommu_iova_cache_init();
3739 if (ret)
3740 return ret;
3741
3742 ret = iommu_domain_cache_init();
3743 if (ret)
3744 goto domain_error;
3745
3746 ret = iommu_devinfo_cache_init();
3747 if (!ret)
3748 return ret;
3749
3750 kmem_cache_destroy(iommu_domain_cache);
3751domain_error:
Robin Murphy85b45452015-01-12 17:51:14 +00003752 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003753
3754 return -ENOMEM;
3755}
3756
3757static void __init iommu_exit_mempool(void)
3758{
3759 kmem_cache_destroy(iommu_devinfo_cache);
3760 kmem_cache_destroy(iommu_domain_cache);
Robin Murphy85b45452015-01-12 17:51:14 +00003761 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003762}
3763
Dan Williams556ab452010-07-23 15:47:56 -07003764static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3765{
3766 struct dmar_drhd_unit *drhd;
3767 u32 vtbar;
3768 int rc;
3769
3770 /* We know that this device on this chipset has its own IOMMU.
3771 * If we find it under a different IOMMU, then the BIOS is lying
3772 * to us. Hope that the IOMMU for this device is actually
3773 * disabled, and it needs no translation...
3774 */
3775 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3776 if (rc) {
3777 /* "can't" happen */
3778 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3779 return;
3780 }
3781 vtbar &= 0xffff0000;
3782
3783 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3784 drhd = dmar_find_matched_drhd_unit(pdev);
3785 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3786 TAINT_FIRMWARE_WORKAROUND,
3787 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3788 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3789}
3790DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3791
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003792static void __init init_no_remapping_devices(void)
3793{
3794 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003795 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003796 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003797
3798 for_each_drhd_unit(drhd) {
3799 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003800 for_each_active_dev_scope(drhd->devices,
3801 drhd->devices_cnt, i, dev)
3802 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003803 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003804 if (i == drhd->devices_cnt)
3805 drhd->ignored = 1;
3806 }
3807 }
3808
Jiang Liu7c919772014-01-06 14:18:18 +08003809 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003810 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003811 continue;
3812
Jiang Liub683b232014-02-19 14:07:32 +08003813 for_each_active_dev_scope(drhd->devices,
3814 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003815 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003816 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003817 if (i < drhd->devices_cnt)
3818 continue;
3819
David Woodhousec0771df2011-10-14 20:59:46 +01003820 /* This IOMMU has *only* gfx devices. Either bypass it or
3821 set the gfx_mapped flag, as appropriate */
3822 if (dmar_map_gfx) {
3823 intel_iommu_gfx_mapped = 1;
3824 } else {
3825 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003826 for_each_active_dev_scope(drhd->devices,
3827 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003828 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003829 }
3830 }
3831}
3832
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003833#ifdef CONFIG_SUSPEND
3834static int init_iommu_hw(void)
3835{
3836 struct dmar_drhd_unit *drhd;
3837 struct intel_iommu *iommu = NULL;
3838
3839 for_each_active_iommu(iommu, drhd)
3840 if (iommu->qi)
3841 dmar_reenable_qi(iommu);
3842
Joseph Cihulab7792602011-05-03 00:08:37 -07003843 for_each_iommu(iommu, drhd) {
3844 if (drhd->ignored) {
3845 /*
3846 * we always have to disable PMRs or DMA may fail on
3847 * this device
3848 */
3849 if (force_on)
3850 iommu_disable_protect_mem_regions(iommu);
3851 continue;
3852 }
3853
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003854 iommu_flush_write_buffer(iommu);
3855
3856 iommu_set_root_entry(iommu);
3857
3858 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003859 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003860 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3861 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003862 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003863 }
3864
3865 return 0;
3866}
3867
3868static void iommu_flush_all(void)
3869{
3870 struct dmar_drhd_unit *drhd;
3871 struct intel_iommu *iommu;
3872
3873 for_each_active_iommu(iommu, drhd) {
3874 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003875 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003876 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003877 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003878 }
3879}
3880
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003881static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003882{
3883 struct dmar_drhd_unit *drhd;
3884 struct intel_iommu *iommu = NULL;
3885 unsigned long flag;
3886
3887 for_each_active_iommu(iommu, drhd) {
3888 iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
3889 GFP_ATOMIC);
3890 if (!iommu->iommu_state)
3891 goto nomem;
3892 }
3893
3894 iommu_flush_all();
3895
3896 for_each_active_iommu(iommu, drhd) {
3897 iommu_disable_translation(iommu);
3898
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003899 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003900
3901 iommu->iommu_state[SR_DMAR_FECTL_REG] =
3902 readl(iommu->reg + DMAR_FECTL_REG);
3903 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
3904 readl(iommu->reg + DMAR_FEDATA_REG);
3905 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
3906 readl(iommu->reg + DMAR_FEADDR_REG);
3907 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
3908 readl(iommu->reg + DMAR_FEUADDR_REG);
3909
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003910 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003911 }
3912 return 0;
3913
3914nomem:
3915 for_each_active_iommu(iommu, drhd)
3916 kfree(iommu->iommu_state);
3917
3918 return -ENOMEM;
3919}
3920
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003921static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003922{
3923 struct dmar_drhd_unit *drhd;
3924 struct intel_iommu *iommu = NULL;
3925 unsigned long flag;
3926
3927 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07003928 if (force_on)
3929 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
3930 else
3931 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003932 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003933 }
3934
3935 for_each_active_iommu(iommu, drhd) {
3936
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003937 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003938
3939 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
3940 iommu->reg + DMAR_FECTL_REG);
3941 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
3942 iommu->reg + DMAR_FEDATA_REG);
3943 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
3944 iommu->reg + DMAR_FEADDR_REG);
3945 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
3946 iommu->reg + DMAR_FEUADDR_REG);
3947
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003948 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003949 }
3950
3951 for_each_active_iommu(iommu, drhd)
3952 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003953}
3954
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003955static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003956 .resume = iommu_resume,
3957 .suspend = iommu_suspend,
3958};
3959
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003960static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003961{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003962 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003963}
3964
3965#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02003966static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003967#endif /* CONFIG_PM */
3968
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003969
Jiang Liuc2a0b532014-11-09 22:47:56 +08003970int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003971{
3972 struct acpi_dmar_reserved_memory *rmrr;
3973 struct dmar_rmrr_unit *rmrru;
3974
3975 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
3976 if (!rmrru)
3977 return -ENOMEM;
3978
3979 rmrru->hdr = header;
3980 rmrr = (struct acpi_dmar_reserved_memory *)header;
3981 rmrru->base_address = rmrr->base_address;
3982 rmrru->end_address = rmrr->end_address;
Jiang Liu2e455282014-02-19 14:07:36 +08003983 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
3984 ((void *)rmrr) + rmrr->header.length,
3985 &rmrru->devices_cnt);
3986 if (rmrru->devices_cnt && rmrru->devices == NULL) {
3987 kfree(rmrru);
3988 return -ENOMEM;
3989 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003990
Jiang Liu2e455282014-02-19 14:07:36 +08003991 list_add(&rmrru->list, &dmar_rmrr_units);
3992
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003993 return 0;
3994}
3995
Jiang Liu6b197242014-11-09 22:47:58 +08003996static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
3997{
3998 struct dmar_atsr_unit *atsru;
3999 struct acpi_dmar_atsr *tmp;
4000
4001 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4002 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4003 if (atsr->segment != tmp->segment)
4004 continue;
4005 if (atsr->header.length != tmp->header.length)
4006 continue;
4007 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4008 return atsru;
4009 }
4010
4011 return NULL;
4012}
4013
4014int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004015{
4016 struct acpi_dmar_atsr *atsr;
4017 struct dmar_atsr_unit *atsru;
4018
Jiang Liu6b197242014-11-09 22:47:58 +08004019 if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
4020 return 0;
4021
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004022 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004023 atsru = dmar_find_atsr(atsr);
4024 if (atsru)
4025 return 0;
4026
4027 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004028 if (!atsru)
4029 return -ENOMEM;
4030
Jiang Liu6b197242014-11-09 22:47:58 +08004031 /*
4032 * If memory is allocated from slab by ACPI _DSM method, we need to
4033 * copy the memory content because the memory buffer will be freed
4034 * on return.
4035 */
4036 atsru->hdr = (void *)(atsru + 1);
4037 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004038 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004039 if (!atsru->include_all) {
4040 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4041 (void *)atsr + atsr->header.length,
4042 &atsru->devices_cnt);
4043 if (atsru->devices_cnt && atsru->devices == NULL) {
4044 kfree(atsru);
4045 return -ENOMEM;
4046 }
4047 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004048
Jiang Liu0e242612014-02-19 14:07:34 +08004049 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004050
4051 return 0;
4052}
4053
Jiang Liu9bdc5312014-01-06 14:18:27 +08004054static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4055{
4056 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4057 kfree(atsru);
4058}
4059
Jiang Liu6b197242014-11-09 22:47:58 +08004060int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4061{
4062 struct acpi_dmar_atsr *atsr;
4063 struct dmar_atsr_unit *atsru;
4064
4065 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4066 atsru = dmar_find_atsr(atsr);
4067 if (atsru) {
4068 list_del_rcu(&atsru->list);
4069 synchronize_rcu();
4070 intel_iommu_free_atsr(atsru);
4071 }
4072
4073 return 0;
4074}
4075
4076int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4077{
4078 int i;
4079 struct device *dev;
4080 struct acpi_dmar_atsr *atsr;
4081 struct dmar_atsr_unit *atsru;
4082
4083 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4084 atsru = dmar_find_atsr(atsr);
4085 if (!atsru)
4086 return 0;
4087
4088 if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
4089 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4090 i, dev)
4091 return -EBUSY;
4092
4093 return 0;
4094}
4095
Jiang Liuffebeb42014-11-09 22:48:02 +08004096static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4097{
4098 int sp, ret = 0;
4099 struct intel_iommu *iommu = dmaru->iommu;
4100
4101 if (g_iommus[iommu->seq_id])
4102 return 0;
4103
4104 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004105 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004106 iommu->name);
4107 return -ENXIO;
4108 }
4109 if (!ecap_sc_support(iommu->ecap) &&
4110 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004111 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004112 iommu->name);
4113 return -ENXIO;
4114 }
4115 sp = domain_update_iommu_superpage(iommu) - 1;
4116 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004117 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004118 iommu->name);
4119 return -ENXIO;
4120 }
4121
4122 /*
4123 * Disable translation if already enabled prior to OS handover.
4124 */
4125 if (iommu->gcmd & DMA_GCMD_TE)
4126 iommu_disable_translation(iommu);
4127
4128 g_iommus[iommu->seq_id] = iommu;
4129 ret = iommu_init_domains(iommu);
4130 if (ret == 0)
4131 ret = iommu_alloc_root_entry(iommu);
4132 if (ret)
4133 goto out;
4134
4135 if (dmaru->ignored) {
4136 /*
4137 * we always have to disable PMRs or DMA may fail on this device
4138 */
4139 if (force_on)
4140 iommu_disable_protect_mem_regions(iommu);
4141 return 0;
4142 }
4143
4144 intel_iommu_init_qi(iommu);
4145 iommu_flush_write_buffer(iommu);
4146 ret = dmar_set_interrupt(iommu);
4147 if (ret)
4148 goto disable_iommu;
4149
4150 iommu_set_root_entry(iommu);
4151 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4152 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4153 iommu_enable_translation(iommu);
4154
Jiang Liuffebeb42014-11-09 22:48:02 +08004155 iommu_disable_protect_mem_regions(iommu);
4156 return 0;
4157
4158disable_iommu:
4159 disable_dmar_iommu(iommu);
4160out:
4161 free_dmar_iommu(iommu);
4162 return ret;
4163}
4164
Jiang Liu6b197242014-11-09 22:47:58 +08004165int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4166{
Jiang Liuffebeb42014-11-09 22:48:02 +08004167 int ret = 0;
4168 struct intel_iommu *iommu = dmaru->iommu;
4169
4170 if (!intel_iommu_enabled)
4171 return 0;
4172 if (iommu == NULL)
4173 return -EINVAL;
4174
4175 if (insert) {
4176 ret = intel_iommu_add(dmaru);
4177 } else {
4178 disable_dmar_iommu(iommu);
4179 free_dmar_iommu(iommu);
4180 }
4181
4182 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004183}
4184
Jiang Liu9bdc5312014-01-06 14:18:27 +08004185static void intel_iommu_free_dmars(void)
4186{
4187 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4188 struct dmar_atsr_unit *atsru, *atsr_n;
4189
4190 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4191 list_del(&rmrru->list);
4192 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
4193 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004194 }
4195
Jiang Liu9bdc5312014-01-06 14:18:27 +08004196 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4197 list_del(&atsru->list);
4198 intel_iommu_free_atsr(atsru);
4199 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004200}
4201
4202int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4203{
Jiang Liub683b232014-02-19 14:07:32 +08004204 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004205 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004206 struct pci_dev *bridge = NULL;
4207 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004208 struct acpi_dmar_atsr *atsr;
4209 struct dmar_atsr_unit *atsru;
4210
4211 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004212 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004213 bridge = bus->self;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004214 if (!bridge || !pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004215 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004216 return 0;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004217 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004218 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004219 }
Jiang Liub5f82dd2014-02-19 14:07:31 +08004220 if (!bridge)
4221 return 0;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004222
Jiang Liu0e242612014-02-19 14:07:34 +08004223 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004224 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4225 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4226 if (atsr->segment != pci_domain_nr(dev->bus))
4227 continue;
4228
Jiang Liub683b232014-02-19 14:07:32 +08004229 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004230 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004231 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004232
4233 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004234 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004235 }
Jiang Liub683b232014-02-19 14:07:32 +08004236 ret = 0;
4237out:
Jiang Liu0e242612014-02-19 14:07:34 +08004238 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004239
Jiang Liub683b232014-02-19 14:07:32 +08004240 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004241}
4242
Jiang Liu59ce0512014-02-19 14:07:35 +08004243int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4244{
4245 int ret = 0;
4246 struct dmar_rmrr_unit *rmrru;
4247 struct dmar_atsr_unit *atsru;
4248 struct acpi_dmar_atsr *atsr;
4249 struct acpi_dmar_reserved_memory *rmrr;
4250
4251 if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
4252 return 0;
4253
4254 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4255 rmrr = container_of(rmrru->hdr,
4256 struct acpi_dmar_reserved_memory, header);
4257 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4258 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4259 ((void *)rmrr) + rmrr->header.length,
4260 rmrr->segment, rmrru->devices,
4261 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08004262 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004263 return ret;
4264 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004265 dmar_remove_dev_scope(info, rmrr->segment,
4266 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004267 }
4268 }
4269
4270 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4271 if (atsru->include_all)
4272 continue;
4273
4274 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4275 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4276 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4277 (void *)atsr + atsr->header.length,
4278 atsr->segment, atsru->devices,
4279 atsru->devices_cnt);
4280 if (ret > 0)
4281 break;
4282 else if(ret < 0)
4283 return ret;
4284 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
4285 if (dmar_remove_dev_scope(info, atsr->segment,
4286 atsru->devices, atsru->devices_cnt))
4287 break;
4288 }
4289 }
4290
4291 return 0;
4292}
4293
Fenghua Yu99dcade2009-11-11 07:23:06 -08004294/*
4295 * Here we only respond to action of unbound device from driver.
4296 *
4297 * Added device is not attached to its DMAR domain here yet. That will happen
4298 * when mapping the device to iova.
4299 */
4300static int device_notifier(struct notifier_block *nb,
4301 unsigned long action, void *data)
4302{
4303 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004304 struct dmar_domain *domain;
4305
David Woodhouse3d891942014-03-06 15:59:26 +00004306 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004307 return 0;
4308
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004309 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004310 return 0;
4311
David Woodhouse1525a292014-03-06 16:19:30 +00004312 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004313 if (!domain)
4314 return 0;
4315
Joerg Roedele6de0f82015-07-22 16:30:36 +02004316 dmar_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004317 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004318 domain_exit(domain);
Alex Williamsona97590e2011-03-04 14:52:16 -07004319
Fenghua Yu99dcade2009-11-11 07:23:06 -08004320 return 0;
4321}
4322
4323static struct notifier_block device_nb = {
4324 .notifier_call = device_notifier,
4325};
4326
Jiang Liu75f05562014-02-19 14:07:37 +08004327static int intel_iommu_memory_notifier(struct notifier_block *nb,
4328 unsigned long val, void *v)
4329{
4330 struct memory_notify *mhp = v;
4331 unsigned long long start, end;
4332 unsigned long start_vpfn, last_vpfn;
4333
4334 switch (val) {
4335 case MEM_GOING_ONLINE:
4336 start = mhp->start_pfn << PAGE_SHIFT;
4337 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4338 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004339 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004340 start, end);
4341 return NOTIFY_BAD;
4342 }
4343 break;
4344
4345 case MEM_OFFLINE:
4346 case MEM_CANCEL_ONLINE:
4347 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4348 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4349 while (start_vpfn <= last_vpfn) {
4350 struct iova *iova;
4351 struct dmar_drhd_unit *drhd;
4352 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004353 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004354
4355 iova = find_iova(&si_domain->iovad, start_vpfn);
4356 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004357 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004358 start_vpfn);
4359 break;
4360 }
4361
4362 iova = split_and_remove_iova(&si_domain->iovad, iova,
4363 start_vpfn, last_vpfn);
4364 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004365 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004366 start_vpfn, last_vpfn);
4367 return NOTIFY_BAD;
4368 }
4369
David Woodhouseea8ea462014-03-05 17:09:32 +00004370 freelist = domain_unmap(si_domain, iova->pfn_lo,
4371 iova->pfn_hi);
4372
Jiang Liu75f05562014-02-19 14:07:37 +08004373 rcu_read_lock();
4374 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004375 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004376 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004377 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004378 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004379 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004380
4381 start_vpfn = iova->pfn_hi + 1;
4382 free_iova_mem(iova);
4383 }
4384 break;
4385 }
4386
4387 return NOTIFY_OK;
4388}
4389
4390static struct notifier_block intel_iommu_memory_nb = {
4391 .notifier_call = intel_iommu_memory_notifier,
4392 .priority = 0
4393};
4394
Alex Williamsona5459cf2014-06-12 16:12:31 -06004395
4396static ssize_t intel_iommu_show_version(struct device *dev,
4397 struct device_attribute *attr,
4398 char *buf)
4399{
4400 struct intel_iommu *iommu = dev_get_drvdata(dev);
4401 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4402 return sprintf(buf, "%d:%d\n",
4403 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4404}
4405static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4406
4407static ssize_t intel_iommu_show_address(struct device *dev,
4408 struct device_attribute *attr,
4409 char *buf)
4410{
4411 struct intel_iommu *iommu = dev_get_drvdata(dev);
4412 return sprintf(buf, "%llx\n", iommu->reg_phys);
4413}
4414static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4415
4416static ssize_t intel_iommu_show_cap(struct device *dev,
4417 struct device_attribute *attr,
4418 char *buf)
4419{
4420 struct intel_iommu *iommu = dev_get_drvdata(dev);
4421 return sprintf(buf, "%llx\n", iommu->cap);
4422}
4423static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4424
4425static ssize_t intel_iommu_show_ecap(struct device *dev,
4426 struct device_attribute *attr,
4427 char *buf)
4428{
4429 struct intel_iommu *iommu = dev_get_drvdata(dev);
4430 return sprintf(buf, "%llx\n", iommu->ecap);
4431}
4432static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4433
Alex Williamson2238c082015-07-14 15:24:53 -06004434static ssize_t intel_iommu_show_ndoms(struct device *dev,
4435 struct device_attribute *attr,
4436 char *buf)
4437{
4438 struct intel_iommu *iommu = dev_get_drvdata(dev);
4439 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4440}
4441static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4442
4443static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4444 struct device_attribute *attr,
4445 char *buf)
4446{
4447 struct intel_iommu *iommu = dev_get_drvdata(dev);
4448 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4449 cap_ndoms(iommu->cap)));
4450}
4451static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4452
Alex Williamsona5459cf2014-06-12 16:12:31 -06004453static struct attribute *intel_iommu_attrs[] = {
4454 &dev_attr_version.attr,
4455 &dev_attr_address.attr,
4456 &dev_attr_cap.attr,
4457 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004458 &dev_attr_domains_supported.attr,
4459 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004460 NULL,
4461};
4462
4463static struct attribute_group intel_iommu_group = {
4464 .name = "intel-iommu",
4465 .attrs = intel_iommu_attrs,
4466};
4467
4468const struct attribute_group *intel_iommu_groups[] = {
4469 &intel_iommu_group,
4470 NULL,
4471};
4472
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004473int __init intel_iommu_init(void)
4474{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004475 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004476 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004477 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004478
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004479 /* VT-d is required for a TXT/tboot launch, so enforce that */
4480 force_on = tboot_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004481
Jiang Liu3a5670e2014-02-19 14:07:33 +08004482 if (iommu_init_mempool()) {
4483 if (force_on)
4484 panic("tboot: Failed to initialize iommu memory\n");
4485 return -ENOMEM;
4486 }
4487
4488 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004489 if (dmar_table_init()) {
4490 if (force_on)
4491 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004492 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004493 }
4494
Suresh Siddhac2c72862011-08-23 17:05:19 -07004495 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004496 if (force_on)
4497 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004498 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004499 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004500
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004501 if (no_iommu || dmar_disabled)
Jiang Liu9bdc5312014-01-06 14:18:27 +08004502 goto out_free_dmar;
Suresh Siddha2ae21012008-07-10 11:16:43 -07004503
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004504 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004505 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004506
4507 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004508 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004509
Joseph Cihula51a63e62011-03-21 11:04:24 -07004510 if (dmar_init_reserved_ranges()) {
4511 if (force_on)
4512 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004513 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004514 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004515
4516 init_no_remapping_devices();
4517
Joseph Cihulab7792602011-05-03 00:08:37 -07004518 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004519 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004520 if (force_on)
4521 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004522 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004523 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004524 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004525 up_write(&dmar_global_lock);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004526 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004527
mark gross5e0d2a62008-03-04 15:22:08 -08004528 init_timer(&unmap_timer);
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004529#ifdef CONFIG_SWIOTLB
4530 swiotlb = 0;
4531#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004532 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004533
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004534 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004535
Alex Williamsona5459cf2014-06-12 16:12:31 -06004536 for_each_active_iommu(iommu, drhd)
4537 iommu->iommu_dev = iommu_device_create(NULL, iommu,
4538 intel_iommu_groups,
Kees Cook2439d4a2015-07-24 16:27:57 -07004539 "%s", iommu->name);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004540
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004541 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004542 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004543 if (si_domain && !hw_pass_through)
4544 register_memory_notifier(&intel_iommu_memory_nb);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004545
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004546 intel_iommu_enabled = 1;
4547
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004548 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004549
4550out_free_reserved_range:
4551 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004552out_free_dmar:
4553 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004554 up_write(&dmar_global_lock);
4555 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004556 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004557}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004558
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004559static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004560{
4561 struct intel_iommu *iommu = opaque;
4562
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004563 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004564 return 0;
4565}
4566
4567/*
4568 * NB - intel-iommu lacks any sort of reference counting for the users of
4569 * dependent devices. If multiple endpoints have intersecting dependent
4570 * devices, unbinding the driver from any one of them will possibly leave
4571 * the others unable to operate.
4572 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004573static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004574{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004575 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004576 return;
4577
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004578 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004579}
4580
Joerg Roedel127c7612015-07-23 17:44:46 +02004581static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004582{
Weidong Hanc7151a82008-12-08 22:51:37 +08004583 struct intel_iommu *iommu;
4584 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004585
Joerg Roedel55d94042015-07-22 16:50:40 +02004586 assert_spin_locked(&device_domain_lock);
4587
Joerg Roedelb608ac32015-07-21 18:19:08 +02004588 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004589 return;
4590
Joerg Roedel127c7612015-07-23 17:44:46 +02004591 iommu = info->iommu;
4592
4593 if (info->dev) {
4594 iommu_disable_dev_iotlb(info);
4595 domain_context_clear(iommu, info->dev);
4596 }
4597
Joerg Roedelb608ac32015-07-21 18:19:08 +02004598 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004599
Joerg Roedeld160aca2015-07-22 11:52:53 +02004600 spin_lock_irqsave(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004601 domain_detach_iommu(info->domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004602 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004603
4604 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004605}
4606
Joerg Roedel55d94042015-07-22 16:50:40 +02004607static void dmar_remove_one_dev_info(struct dmar_domain *domain,
4608 struct device *dev)
4609{
Joerg Roedel127c7612015-07-23 17:44:46 +02004610 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02004611 unsigned long flags;
4612
Weidong Hanc7151a82008-12-08 22:51:37 +08004613 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004614 info = dev->archdata.iommu;
4615 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004616 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004617}
4618
4619static int md_domain_init(struct dmar_domain *domain, int guest_width)
4620{
4621 int adjust_width;
4622
Robin Murphy0fb5fe82015-01-12 17:51:16 +00004623 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
4624 DMA_32BIT_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004625 domain_reserve_special_ranges(domain);
4626
4627 /* calculate AGAW */
4628 domain->gaw = guest_width;
4629 adjust_width = guestwidth_to_adjustwidth(guest_width);
4630 domain->agaw = width_to_agaw(adjust_width);
4631
Weidong Han5e98c4b2008-12-08 23:03:27 +08004632 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004633 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004634 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004635 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004636
4637 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004638 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004639 if (!domain->pgd)
4640 return -ENOMEM;
4641 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4642 return 0;
4643}
4644
Joerg Roedel00a77de2015-03-26 13:43:08 +01004645static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03004646{
Joerg Roedel5d450802008-12-03 14:52:32 +01004647 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01004648 struct iommu_domain *domain;
4649
4650 if (type != IOMMU_DOMAIN_UNMANAGED)
4651 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004652
Jiang Liuab8dfe22014-07-11 14:19:27 +08004653 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01004654 if (!dmar_domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004655 pr_err("Can't allocate dmar_domain\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01004656 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004657 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004658 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004659 pr_err("Domain initialization failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08004660 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01004661 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004662 }
Allen Kay8140a952011-10-14 12:32:17 -07004663 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004664
Joerg Roedel00a77de2015-03-26 13:43:08 +01004665 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01004666 domain->geometry.aperture_start = 0;
4667 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4668 domain->geometry.force_aperture = true;
4669
Joerg Roedel00a77de2015-03-26 13:43:08 +01004670 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03004671}
Kay, Allen M38717942008-09-09 18:37:29 +03004672
Joerg Roedel00a77de2015-03-26 13:43:08 +01004673static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004674{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004675 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03004676}
Kay, Allen M38717942008-09-09 18:37:29 +03004677
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004678static int intel_iommu_attach_device(struct iommu_domain *domain,
4679 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004680{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004681 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004682 struct intel_iommu *iommu;
4683 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07004684 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03004685
Alex Williamsonc875d2c2014-07-03 09:57:02 -06004686 if (device_is_rmrr_locked(dev)) {
4687 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
4688 return -EPERM;
4689 }
4690
David Woodhouse7207d8f2014-03-09 16:31:06 -07004691 /* normally dev is not mapped */
4692 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004693 struct dmar_domain *old_domain;
4694
David Woodhouse1525a292014-03-06 16:19:30 +00004695 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004696 if (old_domain) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02004697 rcu_read_lock();
Joerg Roedelde7e8882015-07-22 11:58:07 +02004698 dmar_remove_one_dev_info(old_domain, dev);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004699 rcu_read_unlock();
Joerg Roedel62c22162014-12-09 12:56:45 +01004700
4701 if (!domain_type_is_vm_or_si(old_domain) &&
4702 list_empty(&old_domain->devices))
4703 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004704 }
4705 }
4706
David Woodhouse156baca2014-03-09 14:00:57 -07004707 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004708 if (!iommu)
4709 return -ENODEV;
4710
4711 /* check if this iommu agaw is sufficient for max mapped address */
4712 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01004713 if (addr_width > cap_mgaw(iommu->cap))
4714 addr_width = cap_mgaw(iommu->cap);
4715
4716 if (dmar_domain->max_addr > (1LL << addr_width)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004717 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004718 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01004719 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004720 return -EFAULT;
4721 }
Tom Lyona99c47a2010-05-17 08:20:45 +01004722 dmar_domain->gaw = addr_width;
4723
4724 /*
4725 * Knock out extra levels of page tables if necessary
4726 */
4727 while (iommu->agaw < dmar_domain->agaw) {
4728 struct dma_pte *pte;
4729
4730 pte = dmar_domain->pgd;
4731 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08004732 dmar_domain->pgd = (struct dma_pte *)
4733 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01004734 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01004735 }
4736 dmar_domain->agaw--;
4737 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004738
Joerg Roedel28ccce02015-07-21 14:45:31 +02004739 return domain_add_dev_info(dmar_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004740}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004741
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004742static void intel_iommu_detach_device(struct iommu_domain *domain,
4743 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004744{
Joerg Roedele6de0f82015-07-22 16:30:36 +02004745 dmar_remove_one_dev_info(to_dmar_domain(domain), dev);
Kay, Allen M38717942008-09-09 18:37:29 +03004746}
Kay, Allen M38717942008-09-09 18:37:29 +03004747
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004748static int intel_iommu_map(struct iommu_domain *domain,
4749 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004750 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03004751{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004752 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004753 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004754 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004755 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004756
Joerg Roedeldde57a22008-12-03 15:04:09 +01004757 if (iommu_prot & IOMMU_READ)
4758 prot |= DMA_PTE_READ;
4759 if (iommu_prot & IOMMU_WRITE)
4760 prot |= DMA_PTE_WRITE;
Sheng Yang9cf066972009-03-18 15:33:07 +08004761 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
4762 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004763
David Woodhouse163cc522009-06-28 00:51:17 +01004764 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004765 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004766 u64 end;
4767
4768 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01004769 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004770 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004771 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004772 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01004773 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004774 return -EFAULT;
4775 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01004776 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004777 }
David Woodhousead051222009-06-28 14:22:28 +01004778 /* Round up size to next multiple of PAGE_SIZE, if it and
4779 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01004780 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01004781 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
4782 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004783 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03004784}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004785
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004786static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00004787 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004788{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004789 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00004790 struct page *freelist = NULL;
4791 struct intel_iommu *iommu;
4792 unsigned long start_pfn, last_pfn;
4793 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02004794 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01004795
David Woodhouse5cf0a762014-03-19 16:07:49 +00004796 /* Cope with horrid API which requires us to unmap more than the
4797 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02004798 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00004799
4800 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
4801 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
4802
David Woodhouseea8ea462014-03-05 17:09:32 +00004803 start_pfn = iova >> VTD_PAGE_SHIFT;
4804 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
4805
4806 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
4807
4808 npages = last_pfn - start_pfn + 1;
4809
Joerg Roedel29a27712015-07-21 17:17:12 +02004810 for_each_domain_iommu(iommu_id, dmar_domain) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004811 iommu = g_iommus[iommu_id];
David Woodhouseea8ea462014-03-05 17:09:32 +00004812
Joerg Roedel42e8c182015-07-21 15:50:02 +02004813 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
4814 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00004815 }
4816
4817 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004818
David Woodhouse163cc522009-06-28 00:51:17 +01004819 if (dmar_domain->max_addr == iova + size)
4820 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004821
David Woodhouse5cf0a762014-03-19 16:07:49 +00004822 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004823}
Kay, Allen M38717942008-09-09 18:37:29 +03004824
Joerg Roedeld14d6572008-12-03 15:06:57 +01004825static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547ac2013-03-29 01:23:58 +05304826 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03004827{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004828 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004829 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00004830 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004831 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004832
David Woodhouse5cf0a762014-03-19 16:07:49 +00004833 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03004834 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004835 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03004836
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004837 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03004838}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004839
Joerg Roedel5d587b82014-09-05 10:50:45 +02004840static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004841{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004842 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004843 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04004844 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004845 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004846
Joerg Roedel5d587b82014-09-05 10:50:45 +02004847 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004848}
4849
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004850static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004851{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004852 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004853 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07004854 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04004855
Alex Williamsona5459cf2014-06-12 16:12:31 -06004856 iommu = device_to_iommu(dev, &bus, &devfn);
4857 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004858 return -ENODEV;
4859
Alex Williamsona5459cf2014-06-12 16:12:31 -06004860 iommu_device_link(iommu->iommu_dev, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004861
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004862 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06004863
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004864 if (IS_ERR(group))
4865 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004866
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004867 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004868 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004869}
4870
4871static void intel_iommu_remove_device(struct device *dev)
4872{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004873 struct intel_iommu *iommu;
4874 u8 bus, devfn;
4875
4876 iommu = device_to_iommu(dev, &bus, &devfn);
4877 if (!iommu)
4878 return;
4879
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004880 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004881
4882 iommu_device_unlink(iommu->iommu_dev, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004883}
4884
Thierry Redingb22f6432014-06-27 09:03:12 +02004885static const struct iommu_ops intel_iommu_ops = {
Joerg Roedel5d587b82014-09-05 10:50:45 +02004886 .capable = intel_iommu_capable,
Joerg Roedel00a77de2015-03-26 13:43:08 +01004887 .domain_alloc = intel_iommu_domain_alloc,
4888 .domain_free = intel_iommu_domain_free,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004889 .attach_dev = intel_iommu_attach_device,
4890 .detach_dev = intel_iommu_detach_device,
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004891 .map = intel_iommu_map,
4892 .unmap = intel_iommu_unmap,
Olav Haugan315786e2014-10-25 09:55:16 -07004893 .map_sg = default_iommu_map_sg,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004894 .iova_to_phys = intel_iommu_iova_to_phys,
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004895 .add_device = intel_iommu_add_device,
4896 .remove_device = intel_iommu_remove_device,
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +02004897 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004898};
David Woodhouse9af88142009-02-13 23:18:03 +00004899
Daniel Vetter94526182013-01-20 23:50:13 +01004900static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
4901{
4902 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004903 pr_info("Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01004904 dmar_map_gfx = 0;
4905}
4906
4907DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
4908DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
4909DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
4910DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
4911DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
4912DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
4913DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
4914
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004915static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00004916{
4917 /*
4918 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01004919 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00004920 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004921 pr_info("Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00004922 rwbf_quirk = 1;
4923}
4924
4925DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01004926DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
4927DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
4928DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
4929DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
4930DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
4931DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07004932
Adam Jacksoneecfd572010-08-25 21:17:34 +01004933#define GGC 0x52
4934#define GGC_MEMORY_SIZE_MASK (0xf << 8)
4935#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
4936#define GGC_MEMORY_SIZE_1M (0x1 << 8)
4937#define GGC_MEMORY_SIZE_2M (0x3 << 8)
4938#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
4939#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
4940#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
4941#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
4942
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004943static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01004944{
4945 unsigned short ggc;
4946
Adam Jacksoneecfd572010-08-25 21:17:34 +01004947 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01004948 return;
4949
Adam Jacksoneecfd572010-08-25 21:17:34 +01004950 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004951 pr_info("BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01004952 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004953 } else if (dmar_map_gfx) {
4954 /* we have to ensure the gfx device is idle before we flush */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004955 pr_info("Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004956 intel_iommu_strict = 1;
4957 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01004958}
4959DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4960DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
4961DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
4962DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
4963
David Woodhousee0fc7e02009-09-30 09:12:17 -07004964/* On Tylersburg chipsets, some BIOSes have been known to enable the
4965 ISOCH DMAR unit for the Azalia sound device, but not give it any
4966 TLB entries, which causes it to deadlock. Check for that. We do
4967 this in a function called from init_dmars(), instead of in a PCI
4968 quirk, because we don't want to print the obnoxious "BIOS broken"
4969 message if VT-d is actually disabled.
4970*/
4971static void __init check_tylersburg_isoch(void)
4972{
4973 struct pci_dev *pdev;
4974 uint32_t vtisochctrl;
4975
4976 /* If there's no Azalia in the system anyway, forget it. */
4977 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
4978 if (!pdev)
4979 return;
4980 pci_dev_put(pdev);
4981
4982 /* System Management Registers. Might be hidden, in which case
4983 we can't do the sanity check. But that's OK, because the
4984 known-broken BIOSes _don't_ actually hide it, so far. */
4985 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
4986 if (!pdev)
4987 return;
4988
4989 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
4990 pci_dev_put(pdev);
4991 return;
4992 }
4993
4994 pci_dev_put(pdev);
4995
4996 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
4997 if (vtisochctrl & 1)
4998 return;
4999
5000 /* Drop all bits other than the number of TLB entries */
5001 vtisochctrl &= 0x1c;
5002
5003 /* If we have the recommended number of TLB entries (16), fine. */
5004 if (vtisochctrl == 0x10)
5005 return;
5006
5007 /* Zero TLB entries? You get to ride the short bus to school. */
5008 if (!vtisochctrl) {
5009 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5010 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5011 dmi_get_system_info(DMI_BIOS_VENDOR),
5012 dmi_get_system_info(DMI_BIOS_VERSION),
5013 dmi_get_system_info(DMI_PRODUCT_VERSION));
5014 iommu_identity_mapping |= IDENTMAP_AZALIA;
5015 return;
5016 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005017
5018 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005019 vtisochctrl);
5020}