blob: d25cc6219a32a4bc4ecaf3e51b9edd9913387551 [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>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070018 */
19
20#include <linux/init.h>
21#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080022#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040023#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070024#include <linux/slab.h>
25#include <linux/irq.h>
26#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070027#include <linux/spinlock.h>
28#include <linux/pci.h>
29#include <linux/dmar.h>
30#include <linux/dma-mapping.h>
31#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080032#include <linux/memory.h>
mark gross5e0d2a62008-03-04 15:22:08 -080033#include <linux/timer.h>
Kay, Allen M38717942008-09-09 18:37:29 +030034#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010035#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030036#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010037#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070038#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100039#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020040#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080041#include <linux/memblock.h>
Akinobu Mita36746432014-06-04 16:06:51 -070042#include <linux/dma-contiguous.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070043#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070044#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090045#include <asm/iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070046
Joerg Roedel078e1ee2012-09-26 12:44:43 +020047#include "irq_remapping.h"
48
Fenghua Yu5b6985c2008-10-16 18:02:32 -070049#define ROOT_SIZE VTD_PAGE_SIZE
50#define CONTEXT_SIZE VTD_PAGE_SIZE
51
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070052#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
53#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070054#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070055
56#define IOAPIC_RANGE_START (0xfee00000)
57#define IOAPIC_RANGE_END (0xfeefffff)
58#define IOVA_START_ADDR (0x1000)
59
60#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
61
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070062#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080063#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070064
David Woodhouse2ebe3152009-09-19 07:34:04 -070065#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
66#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
67
68/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
69 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
70#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
71 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
72#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070073
Robin Murphy1b722502015-01-12 17:51:15 +000074/* IO virtual address start page frame number */
75#define IOVA_START_PFN (1)
76
Mark McLoughlinf27be032008-11-20 15:49:43 +000077#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
Yang Hongyang284901a2009-04-06 19:01:15 -070078#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
Yang Hongyang6a355282009-04-06 19:01:13 -070079#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
mark gross5e0d2a62008-03-04 15:22:08 -080080
Andrew Mortondf08cdc2010-09-22 13:05:11 -070081/* page table handling */
82#define LEVEL_STRIDE (9)
83#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
84
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020085/*
86 * This bitmap is used to advertise the page sizes our hardware support
87 * to the IOMMU core, which will then use this information to split
88 * physically contiguous memory regions it is mapping into page sizes
89 * that we support.
90 *
91 * Traditionally the IOMMU core just handed us the mappings directly,
92 * after making sure the size is an order of a 4KiB page and that the
93 * mapping has natural alignment.
94 *
95 * To retain this behavior, we currently advertise that we support
96 * all page sizes that are an order of 4KiB.
97 *
98 * If at some point we'd like to utilize the IOMMU core's new behavior,
99 * we could change this to advertise the real page sizes we support.
100 */
101#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
102
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700103static inline int agaw_to_level(int agaw)
104{
105 return agaw + 2;
106}
107
108static inline int agaw_to_width(int agaw)
109{
Jiang Liu5c645b32014-01-06 14:18:12 +0800110 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700111}
112
113static inline int width_to_agaw(int width)
114{
Jiang Liu5c645b32014-01-06 14:18:12 +0800115 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700116}
117
118static inline unsigned int level_to_offset_bits(int level)
119{
120 return (level - 1) * LEVEL_STRIDE;
121}
122
123static inline int pfn_level_offset(unsigned long pfn, int level)
124{
125 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
126}
127
128static inline unsigned long level_mask(int level)
129{
130 return -1UL << level_to_offset_bits(level);
131}
132
133static inline unsigned long level_size(int level)
134{
135 return 1UL << level_to_offset_bits(level);
136}
137
138static inline unsigned long align_to_level(unsigned long pfn, int level)
139{
140 return (pfn + level_size(level) - 1) & level_mask(level);
141}
David Woodhousefd18de52009-05-10 23:57:41 +0100142
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100143static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
144{
Jiang Liu5c645b32014-01-06 14:18:12 +0800145 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100146}
147
David Woodhousedd4e8312009-06-27 16:21:20 +0100148/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
149 are never going to work. */
150static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
151{
152 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
153}
154
155static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
156{
157 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
158}
159static inline unsigned long page_to_dma_pfn(struct page *pg)
160{
161 return mm_to_dma_pfn(page_to_pfn(pg));
162}
163static inline unsigned long virt_to_dma_pfn(void *p)
164{
165 return page_to_dma_pfn(virt_to_page(p));
166}
167
Weidong Hand9630fe2008-12-08 11:06:32 +0800168/* global iommu list, set NULL for ignored DMAR units */
169static struct intel_iommu **g_iommus;
170
David Woodhousee0fc7e02009-09-30 09:12:17 -0700171static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000172static int rwbf_quirk;
173
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000174/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700175 * set to 1 to panic kernel if can't successfully enable VT-d
176 * (used when kernel is launched w/ TXT)
177 */
178static int force_on = 0;
179
180/*
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000181 * 0: Present
182 * 1-11: Reserved
183 * 12-63: Context Ptr (12 - (haw-1))
184 * 64-127: Reserved
185 */
186struct root_entry {
187 u64 val;
188 u64 rsvd1;
189};
190#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
191static inline bool root_present(struct root_entry *root)
192{
193 return (root->val & 1);
194}
195static inline void set_root_present(struct root_entry *root)
196{
197 root->val |= 1;
198}
199static inline void set_root_value(struct root_entry *root, unsigned long value)
200{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800201 root->val &= ~VTD_PAGE_MASK;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000202 root->val |= value & VTD_PAGE_MASK;
203}
204
205static inline struct context_entry *
206get_context_addr_from_root(struct root_entry *root)
207{
208 return (struct context_entry *)
209 (root_present(root)?phys_to_virt(
210 root->val & VTD_PAGE_MASK) :
211 NULL);
212}
213
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000214/*
215 * low 64 bits:
216 * 0: present
217 * 1: fault processing disable
218 * 2-3: translation type
219 * 12-63: address space root
220 * high 64 bits:
221 * 0-2: address width
222 * 3-6: aval
223 * 8-23: domain id
224 */
225struct context_entry {
226 u64 lo;
227 u64 hi;
228};
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000229
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000230static inline bool context_present(struct context_entry *context)
231{
232 return (context->lo & 1);
233}
234static inline void context_set_present(struct context_entry *context)
235{
236 context->lo |= 1;
237}
238
239static inline void context_set_fault_enable(struct context_entry *context)
240{
241 context->lo &= (((u64)-1) << 2) | 1;
242}
243
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000244static inline void context_set_translation_type(struct context_entry *context,
245 unsigned long value)
246{
247 context->lo &= (((u64)-1) << 4) | 3;
248 context->lo |= (value & 3) << 2;
249}
250
251static inline void context_set_address_root(struct context_entry *context,
252 unsigned long value)
253{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800254 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000255 context->lo |= value & VTD_PAGE_MASK;
256}
257
258static inline void context_set_address_width(struct context_entry *context,
259 unsigned long value)
260{
261 context->hi |= value & 7;
262}
263
264static inline void context_set_domain_id(struct context_entry *context,
265 unsigned long value)
266{
267 context->hi |= (value & ((1 << 16) - 1)) << 8;
268}
269
270static inline void context_clear_entry(struct context_entry *context)
271{
272 context->lo = 0;
273 context->hi = 0;
274}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000275
Mark McLoughlin622ba122008-11-20 15:49:46 +0000276/*
277 * 0: readable
278 * 1: writable
279 * 2-6: reserved
280 * 7: super page
Sheng Yang9cf066972009-03-18 15:33:07 +0800281 * 8-10: available
282 * 11: snoop behavior
Mark McLoughlin622ba122008-11-20 15:49:46 +0000283 * 12-63: Host physcial address
284 */
285struct dma_pte {
286 u64 val;
287};
Mark McLoughlin622ba122008-11-20 15:49:46 +0000288
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000289static inline void dma_clear_pte(struct dma_pte *pte)
290{
291 pte->val = 0;
292}
293
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000294static inline u64 dma_pte_addr(struct dma_pte *pte)
295{
David Woodhousec85994e2009-07-01 19:21:24 +0100296#ifdef CONFIG_64BIT
297 return pte->val & VTD_PAGE_MASK;
298#else
299 /* Must have a full atomic 64-bit read */
David Woodhouse1a8bd482010-08-10 01:38:53 +0100300 return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
David Woodhousec85994e2009-07-01 19:21:24 +0100301#endif
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000302}
303
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000304static inline bool dma_pte_present(struct dma_pte *pte)
305{
306 return (pte->val & 3) != 0;
307}
Mark McLoughlin622ba122008-11-20 15:49:46 +0000308
Allen Kay4399c8b2011-10-14 12:32:46 -0700309static inline bool dma_pte_superpage(struct dma_pte *pte)
310{
Joerg Roedelc3c75eb2014-07-04 11:19:10 +0200311 return (pte->val & DMA_PTE_LARGE_PAGE);
Allen Kay4399c8b2011-10-14 12:32:46 -0700312}
313
David Woodhouse75e6bf92009-07-02 11:21:16 +0100314static inline int first_pte_in_page(struct dma_pte *pte)
315{
316 return !((unsigned long)pte & ~VTD_PAGE_MASK);
317}
318
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700319/*
320 * This domain is a statically identity mapping domain.
321 * 1. This domain creats a static 1:1 mapping to all usable memory.
322 * 2. It maps to each iommu if successful.
323 * 3. Each iommu mapps to this domain if successful.
324 */
David Woodhouse19943b02009-08-04 16:19:20 +0100325static struct dmar_domain *si_domain;
326static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700327
Weidong Han1ce28fe2008-12-08 16:35:39 +0800328/* domain represents a virtual machine, more than one devices
329 * across iommus may be owned in one domain, e.g. kvm guest.
330 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800331#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800332
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700333/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800334#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700335
Mark McLoughlin99126f72008-11-20 15:49:47 +0000336struct dmar_domain {
337 int id; /* domain id */
Suresh Siddha4c923d42009-10-02 11:01:24 -0700338 int nid; /* node id */
Jiang Liu78d8e702014-11-09 22:47:57 +0800339 DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
Mike Travis1b198bb2012-03-05 15:05:16 -0800340 /* bitmap of iommus this domain uses*/
Mark McLoughlin99126f72008-11-20 15:49:47 +0000341
342 struct list_head devices; /* all devices' list */
343 struct iova_domain iovad; /* iova's that belong to this domain */
344
345 struct dma_pte *pgd; /* virtual address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000346 int gaw; /* max guest address width */
347
348 /* adjusted guest address width, 0 is level 2 30-bit */
349 int agaw;
350
Weidong Han3b5410e2008-12-08 09:17:15 +0800351 int flags; /* flags to find out type of domain */
Weidong Han8e6040972008-12-08 15:49:06 +0800352
353 int iommu_coherency;/* indicate coherency of iommu access */
Sheng Yang58c610b2009-03-18 15:33:05 +0800354 int iommu_snooping; /* indicate snooping control feature*/
Weidong Hanc7151a82008-12-08 22:51:37 +0800355 int iommu_count; /* reference count of iommu */
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100356 int iommu_superpage;/* Level of superpages supported:
357 0 == 4KiB (no superpages), 1 == 2MiB,
358 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
Weidong Hanc7151a82008-12-08 22:51:37 +0800359 spinlock_t iommu_lock; /* protect iommu set in domain */
Weidong Hanfe40f1e2008-12-08 23:10:23 +0800360 u64 max_addr; /* maximum mapped address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000361};
362
Mark McLoughlina647dac2008-11-20 15:49:48 +0000363/* PCI domain-device relationship */
364struct device_domain_info {
365 struct list_head link; /* link to domain siblings */
366 struct list_head global; /* link to global list */
David Woodhouse276dbf992009-04-04 01:45:37 +0100367 u8 bus; /* PCI bus number */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000368 u8 devfn; /* PCI devfn number */
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000369 struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
Yu Zhao93a23a72009-05-18 13:51:37 +0800370 struct intel_iommu *iommu; /* IOMMU used by this device */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000371 struct dmar_domain *domain; /* pointer to domain */
372};
373
Jiang Liub94e4112014-02-19 14:07:25 +0800374struct dmar_rmrr_unit {
375 struct list_head list; /* list of rmrr units */
376 struct acpi_dmar_header *hdr; /* ACPI header */
377 u64 base_address; /* reserved base address*/
378 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000379 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800380 int devices_cnt; /* target device count */
381};
382
383struct dmar_atsr_unit {
384 struct list_head list; /* list of ATSR units */
385 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000386 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800387 int devices_cnt; /* target device count */
388 u8 include_all:1; /* include all ports */
389};
390
391static LIST_HEAD(dmar_atsr_units);
392static LIST_HEAD(dmar_rmrr_units);
393
394#define for_each_rmrr_units(rmrr) \
395 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
396
mark gross5e0d2a62008-03-04 15:22:08 -0800397static void flush_unmaps_timeout(unsigned long data);
398
Jiang Liub707cb02014-01-06 14:18:26 +0800399static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
mark gross5e0d2a62008-03-04 15:22:08 -0800400
mark gross80b20dd2008-04-18 13:53:58 -0700401#define HIGH_WATER_MARK 250
402struct deferred_flush_tables {
403 int next;
404 struct iova *iova[HIGH_WATER_MARK];
405 struct dmar_domain *domain[HIGH_WATER_MARK];
David Woodhouseea8ea462014-03-05 17:09:32 +0000406 struct page *freelist[HIGH_WATER_MARK];
mark gross80b20dd2008-04-18 13:53:58 -0700407};
408
409static struct deferred_flush_tables *deferred_flush;
410
mark gross5e0d2a62008-03-04 15:22:08 -0800411/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800412static int g_num_of_iommus;
413
414static DEFINE_SPINLOCK(async_umap_flush_lock);
415static LIST_HEAD(unmaps_to_do);
416
417static int timer_on;
418static long list_size;
mark gross5e0d2a62008-03-04 15:22:08 -0800419
Jiang Liu92d03cc2014-02-19 14:07:28 +0800420static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700421static void domain_remove_dev_info(struct dmar_domain *domain);
Jiang Liub94e4112014-02-19 14:07:25 +0800422static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -0700423 struct device *dev);
Jiang Liu92d03cc2014-02-19 14:07:28 +0800424static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000425 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800426static int domain_detach_iommu(struct dmar_domain *domain,
427 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700428
Suresh Siddhad3f13812011-08-23 17:05:25 -0700429#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800430int dmar_disabled = 0;
431#else
432int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700433#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800434
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200435int intel_iommu_enabled = 0;
436EXPORT_SYMBOL_GPL(intel_iommu_enabled);
437
David Woodhouse2d9e6672010-06-15 10:57:57 +0100438static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700439static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800440static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100441static int intel_iommu_superpage = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700442
David Woodhousec0771df2011-10-14 20:59:46 +0100443int intel_iommu_gfx_mapped;
444EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
445
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700446#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
447static DEFINE_SPINLOCK(device_domain_lock);
448static LIST_HEAD(device_domain_list);
449
Thierry Redingb22f6432014-06-27 09:03:12 +0200450static const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100451
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700452static int __init intel_iommu_setup(char *str)
453{
454 if (!str)
455 return -EINVAL;
456 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800457 if (!strncmp(str, "on", 2)) {
458 dmar_disabled = 0;
459 printk(KERN_INFO "Intel-IOMMU: enabled\n");
460 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700461 dmar_disabled = 1;
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800462 printk(KERN_INFO "Intel-IOMMU: disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700463 } else if (!strncmp(str, "igfx_off", 8)) {
464 dmar_map_gfx = 0;
465 printk(KERN_INFO
466 "Intel-IOMMU: disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700467 } else if (!strncmp(str, "forcedac", 8)) {
mark gross5e0d2a62008-03-04 15:22:08 -0800468 printk(KERN_INFO
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700469 "Intel-IOMMU: Forcing DAC for PCI devices\n");
470 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800471 } else if (!strncmp(str, "strict", 6)) {
472 printk(KERN_INFO
473 "Intel-IOMMU: disable batched IOTLB flush\n");
474 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100475 } else if (!strncmp(str, "sp_off", 6)) {
476 printk(KERN_INFO
477 "Intel-IOMMU: disable supported super page\n");
478 intel_iommu_superpage = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700479 }
480
481 str += strcspn(str, ",");
482 while (*str == ',')
483 str++;
484 }
485 return 0;
486}
487__setup("intel_iommu=", intel_iommu_setup);
488
489static struct kmem_cache *iommu_domain_cache;
490static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700491
Suresh Siddha4c923d42009-10-02 11:01:24 -0700492static inline void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700493{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700494 struct page *page;
495 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700496
Suresh Siddha4c923d42009-10-02 11:01:24 -0700497 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
498 if (page)
499 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700500 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700501}
502
503static inline void free_pgtable_page(void *vaddr)
504{
505 free_page((unsigned long)vaddr);
506}
507
508static inline void *alloc_domain_mem(void)
509{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900510 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700511}
512
Kay, Allen M38717942008-09-09 18:37:29 +0300513static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700514{
515 kmem_cache_free(iommu_domain_cache, vaddr);
516}
517
518static inline void * alloc_devinfo_mem(void)
519{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900520 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700521}
522
523static inline void free_devinfo_mem(void *vaddr)
524{
525 kmem_cache_free(iommu_devinfo_cache, vaddr);
526}
527
Jiang Liuab8dfe22014-07-11 14:19:27 +0800528static inline int domain_type_is_vm(struct dmar_domain *domain)
529{
530 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
531}
532
533static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
534{
535 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
536 DOMAIN_FLAG_STATIC_IDENTITY);
537}
Weidong Han1b573682008-12-08 15:34:06 +0800538
Jiang Liu162d1b12014-07-11 14:19:35 +0800539static inline int domain_pfn_supported(struct dmar_domain *domain,
540 unsigned long pfn)
541{
542 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
543
544 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
545}
546
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700547static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800548{
549 unsigned long sagaw;
550 int agaw = -1;
551
552 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700553 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800554 agaw >= 0; agaw--) {
555 if (test_bit(agaw, &sagaw))
556 break;
557 }
558
559 return agaw;
560}
561
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700562/*
563 * Calculate max SAGAW for each iommu.
564 */
565int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
566{
567 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
568}
569
570/*
571 * calculate agaw for each iommu.
572 * "SAGAW" may be different across iommus, use a default agaw, and
573 * get a supported less agaw for iommus that don't support the default agaw.
574 */
575int iommu_calculate_agaw(struct intel_iommu *iommu)
576{
577 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
578}
579
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700580/* This functionin only returns single iommu in a domain */
Weidong Han8c11e792008-12-08 15:29:22 +0800581static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
582{
583 int iommu_id;
584
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700585 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800586 BUG_ON(domain_type_is_vm_or_si(domain));
Mike Travis1b198bb2012-03-05 15:05:16 -0800587 iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
Weidong Han8c11e792008-12-08 15:29:22 +0800588 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
589 return NULL;
590
591 return g_iommus[iommu_id];
592}
593
Weidong Han8e6040972008-12-08 15:49:06 +0800594static void domain_update_iommu_coherency(struct dmar_domain *domain)
595{
David Woodhoused0501962014-03-11 17:10:29 -0700596 struct dmar_drhd_unit *drhd;
597 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100598 bool found = false;
599 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800600
David Woodhoused0501962014-03-11 17:10:29 -0700601 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800602
Mike Travis1b198bb2012-03-05 15:05:16 -0800603 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100604 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800605 if (!ecap_coherent(g_iommus[i]->ecap)) {
606 domain->iommu_coherency = 0;
607 break;
608 }
Weidong Han8e6040972008-12-08 15:49:06 +0800609 }
David Woodhoused0501962014-03-11 17:10:29 -0700610 if (found)
611 return;
612
613 /* No hardware attached; use lowest common denominator */
614 rcu_read_lock();
615 for_each_active_iommu(iommu, drhd) {
616 if (!ecap_coherent(iommu->ecap)) {
617 domain->iommu_coherency = 0;
618 break;
619 }
620 }
621 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800622}
623
Jiang Liu161f6932014-07-11 14:19:37 +0800624static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100625{
Allen Kay8140a952011-10-14 12:32:17 -0700626 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800627 struct intel_iommu *iommu;
628 int ret = 1;
629
630 rcu_read_lock();
631 for_each_active_iommu(iommu, drhd) {
632 if (iommu != skip) {
633 if (!ecap_sc_support(iommu->ecap)) {
634 ret = 0;
635 break;
636 }
637 }
638 }
639 rcu_read_unlock();
640
641 return ret;
642}
643
644static int domain_update_iommu_superpage(struct intel_iommu *skip)
645{
646 struct dmar_drhd_unit *drhd;
647 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700648 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100649
650 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800651 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100652 }
653
Allen Kay8140a952011-10-14 12:32:17 -0700654 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800655 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700656 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800657 if (iommu != skip) {
658 mask &= cap_super_page_val(iommu->cap);
659 if (!mask)
660 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100661 }
662 }
Jiang Liu0e242612014-02-19 14:07:34 +0800663 rcu_read_unlock();
664
Jiang Liu161f6932014-07-11 14:19:37 +0800665 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100666}
667
Sheng Yang58c610b2009-03-18 15:33:05 +0800668/* Some capabilities may be different across iommus */
669static void domain_update_iommu_cap(struct dmar_domain *domain)
670{
671 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800672 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
673 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800674}
675
David Woodhouse156baca2014-03-09 14:00:57 -0700676static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800677{
678 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800679 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700680 struct device *tmp;
681 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800682 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800683 int i;
684
David Woodhouse156baca2014-03-09 14:00:57 -0700685 if (dev_is_pci(dev)) {
686 pdev = to_pci_dev(dev);
687 segment = pci_domain_nr(pdev->bus);
688 } else if (ACPI_COMPANION(dev))
689 dev = &ACPI_COMPANION(dev)->dev;
690
Jiang Liu0e242612014-02-19 14:07:34 +0800691 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800692 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700693 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100694 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800695
Jiang Liub683b232014-02-19 14:07:32 +0800696 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700697 drhd->devices_cnt, i, tmp) {
698 if (tmp == dev) {
699 *bus = drhd->devices[i].bus;
700 *devfn = drhd->devices[i].devfn;
701 goto out;
702 }
703
704 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000705 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700706
707 ptmp = to_pci_dev(tmp);
708 if (ptmp->subordinate &&
709 ptmp->subordinate->number <= pdev->bus->number &&
710 ptmp->subordinate->busn_res.end >= pdev->bus->number)
711 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100712 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800713
David Woodhouse156baca2014-03-09 14:00:57 -0700714 if (pdev && drhd->include_all) {
715 got_pdev:
716 *bus = pdev->bus->number;
717 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800718 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700719 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800720 }
Jiang Liub683b232014-02-19 14:07:32 +0800721 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700722 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800723 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800724
Jiang Liub683b232014-02-19 14:07:32 +0800725 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800726}
727
Weidong Han5331fe62008-12-08 23:00:00 +0800728static void domain_flush_cache(struct dmar_domain *domain,
729 void *addr, int size)
730{
731 if (!domain->iommu_coherency)
732 clflush_cache_range(addr, size);
733}
734
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700735/* Gets context entry for a given bus and devfn */
736static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
737 u8 bus, u8 devfn)
738{
739 struct root_entry *root;
740 struct context_entry *context;
741 unsigned long phy_addr;
742 unsigned long flags;
743
744 spin_lock_irqsave(&iommu->lock, flags);
745 root = &iommu->root_entry[bus];
746 context = get_context_addr_from_root(root);
747 if (!context) {
Suresh Siddha4c923d42009-10-02 11:01:24 -0700748 context = (struct context_entry *)
749 alloc_pgtable_page(iommu->node);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700750 if (!context) {
751 spin_unlock_irqrestore(&iommu->lock, flags);
752 return NULL;
753 }
Fenghua Yu5b6985c2008-10-16 18:02:32 -0700754 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700755 phy_addr = virt_to_phys((void *)context);
756 set_root_value(root, phy_addr);
757 set_root_present(root);
758 __iommu_flush_cache(iommu, root, sizeof(*root));
759 }
760 spin_unlock_irqrestore(&iommu->lock, flags);
761 return &context[devfn];
762}
763
764static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
765{
766 struct root_entry *root;
767 struct context_entry *context;
768 int ret;
769 unsigned long flags;
770
771 spin_lock_irqsave(&iommu->lock, flags);
772 root = &iommu->root_entry[bus];
773 context = get_context_addr_from_root(root);
774 if (!context) {
775 ret = 0;
776 goto out;
777 }
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000778 ret = context_present(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700779out:
780 spin_unlock_irqrestore(&iommu->lock, flags);
781 return ret;
782}
783
784static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
785{
786 struct root_entry *root;
787 struct context_entry *context;
788 unsigned long flags;
789
790 spin_lock_irqsave(&iommu->lock, flags);
791 root = &iommu->root_entry[bus];
792 context = get_context_addr_from_root(root);
793 if (context) {
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000794 context_clear_entry(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700795 __iommu_flush_cache(iommu, &context[devfn], \
796 sizeof(*context));
797 }
798 spin_unlock_irqrestore(&iommu->lock, flags);
799}
800
801static void free_context_table(struct intel_iommu *iommu)
802{
803 struct root_entry *root;
804 int i;
805 unsigned long flags;
806 struct context_entry *context;
807
808 spin_lock_irqsave(&iommu->lock, flags);
809 if (!iommu->root_entry) {
810 goto out;
811 }
812 for (i = 0; i < ROOT_ENTRY_NR; i++) {
813 root = &iommu->root_entry[i];
814 context = get_context_addr_from_root(root);
815 if (context)
816 free_pgtable_page(context);
817 }
818 free_pgtable_page(iommu->root_entry);
819 iommu->root_entry = NULL;
820out:
821 spin_unlock_irqrestore(&iommu->lock, flags);
822}
823
David Woodhouseb026fd22009-06-28 10:37:25 +0100824static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000825 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700826{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700827 struct dma_pte *parent, *pte = NULL;
828 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700829 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700830
831 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200832
Jiang Liu162d1b12014-07-11 14:19:35 +0800833 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200834 /* Address beyond IOMMU's addressing capabilities. */
835 return NULL;
836
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700837 parent = domain->pgd;
838
David Woodhouse5cf0a762014-03-19 16:07:49 +0000839 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700840 void *tmp_page;
841
David Woodhouseb026fd22009-06-28 10:37:25 +0100842 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700843 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000844 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100845 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000846 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700847 break;
848
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000849 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100850 uint64_t pteval;
851
Suresh Siddha4c923d42009-10-02 11:01:24 -0700852 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700853
David Woodhouse206a73c12009-07-01 19:30:28 +0100854 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700855 return NULL;
David Woodhouse206a73c12009-07-01 19:30:28 +0100856
David Woodhousec85994e2009-07-01 19:21:24 +0100857 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400858 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 +0800859 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100860 /* Someone else set it while we were thinking; use theirs. */
861 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800862 else
David Woodhousec85994e2009-07-01 19:21:24 +0100863 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700864 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000865 if (level == 1)
866 break;
867
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000868 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700869 level--;
870 }
871
David Woodhouse5cf0a762014-03-19 16:07:49 +0000872 if (!*target_level)
873 *target_level = level;
874
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700875 return pte;
876}
877
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100878
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700879/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100880static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
881 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100882 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700883{
884 struct dma_pte *parent, *pte = NULL;
885 int total = agaw_to_level(domain->agaw);
886 int offset;
887
888 parent = domain->pgd;
889 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100890 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700891 pte = &parent[offset];
892 if (level == total)
893 return pte;
894
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100895 if (!dma_pte_present(pte)) {
896 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700897 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100898 }
899
Yijing Wange16922a2014-05-20 20:37:51 +0800900 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100901 *large_page = total;
902 return pte;
903 }
904
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000905 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700906 total--;
907 }
908 return NULL;
909}
910
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700911/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000912static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf2009-06-27 22:09:11 +0100913 unsigned long start_pfn,
914 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700915{
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100916 unsigned int large_page = 1;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100917 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700918
Jiang Liu162d1b12014-07-11 14:19:35 +0800919 BUG_ON(!domain_pfn_supported(domain, start_pfn));
920 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700921 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100922
David Woodhouse04b18e62009-06-27 19:15:01 +0100923 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700924 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100925 large_page = 1;
926 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100927 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100928 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100929 continue;
930 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100931 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100932 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100933 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100934 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100935 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
936
David Woodhouse310a5ab2009-06-28 18:52:20 +0100937 domain_flush_cache(domain, first_pte,
938 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700939
940 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700941}
942
Alex Williamson3269ee02013-06-15 10:27:19 -0600943static void dma_pte_free_level(struct dmar_domain *domain, int level,
944 struct dma_pte *pte, unsigned long pfn,
945 unsigned long start_pfn, unsigned long last_pfn)
946{
947 pfn = max(start_pfn, pfn);
948 pte = &pte[pfn_level_offset(pfn, level)];
949
950 do {
951 unsigned long level_pfn;
952 struct dma_pte *level_pte;
953
954 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
955 goto next;
956
957 level_pfn = pfn & level_mask(level - 1);
958 level_pte = phys_to_virt(dma_pte_addr(pte));
959
960 if (level > 2)
961 dma_pte_free_level(domain, level - 1, level_pte,
962 level_pfn, start_pfn, last_pfn);
963
964 /* If range covers entire pagetable, free it */
965 if (!(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -0800966 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -0600967 dma_clear_pte(pte);
968 domain_flush_cache(domain, pte, sizeof(*pte));
969 free_pgtable_page(level_pte);
970 }
971next:
972 pfn += level_size(level);
973 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
974}
975
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700976/* free page table pages. last level pte should already be cleared */
977static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +0100978 unsigned long start_pfn,
979 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700980{
Jiang Liu162d1b12014-07-11 14:19:35 +0800981 BUG_ON(!domain_pfn_supported(domain, start_pfn));
982 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700983 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700984
Jiang Liud41a4ad2014-07-11 14:19:34 +0800985 dma_pte_clear_range(domain, start_pfn, last_pfn);
986
David Woodhousef3a0a522009-06-30 03:40:07 +0100987 /* We don't need lock here; nobody else touches the iova range */
Alex Williamson3269ee02013-06-15 10:27:19 -0600988 dma_pte_free_level(domain, agaw_to_level(domain->agaw),
989 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +0100990
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700991 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +0100992 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700993 free_pgtable_page(domain->pgd);
994 domain->pgd = NULL;
995 }
996}
997
David Woodhouseea8ea462014-03-05 17:09:32 +0000998/* When a page at a given level is being unlinked from its parent, we don't
999 need to *modify* it at all. All we need to do is make a list of all the
1000 pages which can be freed just as soon as we've flushed the IOTLB and we
1001 know the hardware page-walk will no longer touch them.
1002 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1003 be freed. */
1004static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1005 int level, struct dma_pte *pte,
1006 struct page *freelist)
1007{
1008 struct page *pg;
1009
1010 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1011 pg->freelist = freelist;
1012 freelist = pg;
1013
1014 if (level == 1)
1015 return freelist;
1016
Jiang Liuadeb2592014-04-09 10:20:39 +08001017 pte = page_address(pg);
1018 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001019 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1020 freelist = dma_pte_list_pagetables(domain, level - 1,
1021 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001022 pte++;
1023 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001024
1025 return freelist;
1026}
1027
1028static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1029 struct dma_pte *pte, unsigned long pfn,
1030 unsigned long start_pfn,
1031 unsigned long last_pfn,
1032 struct page *freelist)
1033{
1034 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1035
1036 pfn = max(start_pfn, pfn);
1037 pte = &pte[pfn_level_offset(pfn, level)];
1038
1039 do {
1040 unsigned long level_pfn;
1041
1042 if (!dma_pte_present(pte))
1043 goto next;
1044
1045 level_pfn = pfn & level_mask(level);
1046
1047 /* If range covers entire pagetable, free it */
1048 if (start_pfn <= level_pfn &&
1049 last_pfn >= level_pfn + level_size(level) - 1) {
1050 /* These suborbinate page tables are going away entirely. Don't
1051 bother to clear them; we're just going to *free* them. */
1052 if (level > 1 && !dma_pte_superpage(pte))
1053 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1054
1055 dma_clear_pte(pte);
1056 if (!first_pte)
1057 first_pte = pte;
1058 last_pte = pte;
1059 } else if (level > 1) {
1060 /* Recurse down into a level that isn't *entirely* obsolete */
1061 freelist = dma_pte_clear_level(domain, level - 1,
1062 phys_to_virt(dma_pte_addr(pte)),
1063 level_pfn, start_pfn, last_pfn,
1064 freelist);
1065 }
1066next:
1067 pfn += level_size(level);
1068 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1069
1070 if (first_pte)
1071 domain_flush_cache(domain, first_pte,
1072 (void *)++last_pte - (void *)first_pte);
1073
1074 return freelist;
1075}
1076
1077/* We can't just free the pages because the IOMMU may still be walking
1078 the page tables, and may have cached the intermediate levels. The
1079 pages can only be freed after the IOTLB flush has been done. */
1080struct page *domain_unmap(struct dmar_domain *domain,
1081 unsigned long start_pfn,
1082 unsigned long last_pfn)
1083{
David Woodhouseea8ea462014-03-05 17:09:32 +00001084 struct page *freelist = NULL;
1085
Jiang Liu162d1b12014-07-11 14:19:35 +08001086 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1087 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001088 BUG_ON(start_pfn > last_pfn);
1089
1090 /* we don't need lock here; nobody else touches the iova range */
1091 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1092 domain->pgd, 0, start_pfn, last_pfn, NULL);
1093
1094 /* free pgd */
1095 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1096 struct page *pgd_page = virt_to_page(domain->pgd);
1097 pgd_page->freelist = freelist;
1098 freelist = pgd_page;
1099
1100 domain->pgd = NULL;
1101 }
1102
1103 return freelist;
1104}
1105
1106void dma_free_pagelist(struct page *freelist)
1107{
1108 struct page *pg;
1109
1110 while ((pg = freelist)) {
1111 freelist = pg->freelist;
1112 free_pgtable_page(page_address(pg));
1113 }
1114}
1115
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001116/* iommu handling */
1117static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1118{
1119 struct root_entry *root;
1120 unsigned long flags;
1121
Suresh Siddha4c923d42009-10-02 11:01:24 -07001122 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001123 if (!root) {
1124 pr_err("IOMMU: allocating root entry for %s failed\n",
1125 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001126 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001127 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001128
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001129 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001130
1131 spin_lock_irqsave(&iommu->lock, flags);
1132 iommu->root_entry = root;
1133 spin_unlock_irqrestore(&iommu->lock, flags);
1134
1135 return 0;
1136}
1137
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001138static void iommu_set_root_entry(struct intel_iommu *iommu)
1139{
1140 void *addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001141 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001142 unsigned long flag;
1143
1144 addr = iommu->root_entry;
1145
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001146 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001147 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
1148
David Woodhousec416daa2009-05-10 20:30:58 +01001149 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001150
1151 /* Make sure hardware complete it */
1152 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001153 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001154
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001155 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001156}
1157
1158static void iommu_flush_write_buffer(struct intel_iommu *iommu)
1159{
1160 u32 val;
1161 unsigned long flag;
1162
David Woodhouse9af88142009-02-13 23:18:03 +00001163 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001164 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001165
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001166 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001167 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001168
1169 /* Make sure hardware complete it */
1170 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001171 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001172
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001173 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001174}
1175
1176/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001177static void __iommu_flush_context(struct intel_iommu *iommu,
1178 u16 did, u16 source_id, u8 function_mask,
1179 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001180{
1181 u64 val = 0;
1182 unsigned long flag;
1183
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001184 switch (type) {
1185 case DMA_CCMD_GLOBAL_INVL:
1186 val = DMA_CCMD_GLOBAL_INVL;
1187 break;
1188 case DMA_CCMD_DOMAIN_INVL:
1189 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1190 break;
1191 case DMA_CCMD_DEVICE_INVL:
1192 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1193 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1194 break;
1195 default:
1196 BUG();
1197 }
1198 val |= DMA_CCMD_ICC;
1199
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001200 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001201 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1202
1203 /* Make sure hardware complete it */
1204 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1205 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1206
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001207 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001208}
1209
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001210/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001211static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1212 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001213{
1214 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1215 u64 val = 0, val_iva = 0;
1216 unsigned long flag;
1217
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001218 switch (type) {
1219 case DMA_TLB_GLOBAL_FLUSH:
1220 /* global flush doesn't need set IVA_REG */
1221 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1222 break;
1223 case DMA_TLB_DSI_FLUSH:
1224 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1225 break;
1226 case DMA_TLB_PSI_FLUSH:
1227 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001228 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001229 val_iva = size_order | addr;
1230 break;
1231 default:
1232 BUG();
1233 }
1234 /* Note: set drain read/write */
1235#if 0
1236 /*
1237 * This is probably to be super secure.. Looks like we can
1238 * ignore it without any impact.
1239 */
1240 if (cap_read_drain(iommu->cap))
1241 val |= DMA_TLB_READ_DRAIN;
1242#endif
1243 if (cap_write_drain(iommu->cap))
1244 val |= DMA_TLB_WRITE_DRAIN;
1245
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001246 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001247 /* Note: Only uses first TLB reg currently */
1248 if (val_iva)
1249 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1250 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1251
1252 /* Make sure hardware complete it */
1253 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1254 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1255
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001256 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001257
1258 /* check IOTLB invalidation granularity */
1259 if (DMA_TLB_IAIG(val) == 0)
1260 printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
1261 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
1262 pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001263 (unsigned long long)DMA_TLB_IIRG(type),
1264 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001265}
1266
David Woodhouse64ae8922014-03-09 12:52:30 -07001267static struct device_domain_info *
1268iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1269 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001270{
Quentin Lambert2f119c72015-02-06 10:59:53 +01001271 bool found = false;
Yu Zhao93a23a72009-05-18 13:51:37 +08001272 unsigned long flags;
1273 struct device_domain_info *info;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001274 struct pci_dev *pdev;
Yu Zhao93a23a72009-05-18 13:51:37 +08001275
1276 if (!ecap_dev_iotlb_support(iommu->ecap))
1277 return NULL;
1278
1279 if (!iommu->qi)
1280 return NULL;
1281
1282 spin_lock_irqsave(&device_domain_lock, flags);
1283 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001284 if (info->iommu == iommu && info->bus == bus &&
1285 info->devfn == devfn) {
Quentin Lambert2f119c72015-02-06 10:59:53 +01001286 found = true;
Yu Zhao93a23a72009-05-18 13:51:37 +08001287 break;
1288 }
1289 spin_unlock_irqrestore(&device_domain_lock, flags);
1290
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001291 if (!found || !info->dev || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001292 return NULL;
1293
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001294 pdev = to_pci_dev(info->dev);
1295
1296 if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
Yu Zhao93a23a72009-05-18 13:51:37 +08001297 return NULL;
1298
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001299 if (!dmar_find_matched_atsr_unit(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001300 return NULL;
1301
Yu Zhao93a23a72009-05-18 13:51:37 +08001302 return info;
1303}
1304
1305static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1306{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001307 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001308 return;
1309
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001310 pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
Yu Zhao93a23a72009-05-18 13:51:37 +08001311}
1312
1313static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1314{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001315 if (!info->dev || !dev_is_pci(info->dev) ||
1316 !pci_ats_enabled(to_pci_dev(info->dev)))
Yu Zhao93a23a72009-05-18 13:51:37 +08001317 return;
1318
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001319 pci_disable_ats(to_pci_dev(info->dev));
Yu Zhao93a23a72009-05-18 13:51:37 +08001320}
1321
1322static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1323 u64 addr, unsigned mask)
1324{
1325 u16 sid, qdep;
1326 unsigned long flags;
1327 struct device_domain_info *info;
1328
1329 spin_lock_irqsave(&device_domain_lock, flags);
1330 list_for_each_entry(info, &domain->devices, link) {
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001331 struct pci_dev *pdev;
1332 if (!info->dev || !dev_is_pci(info->dev))
1333 continue;
1334
1335 pdev = to_pci_dev(info->dev);
1336 if (!pci_ats_enabled(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001337 continue;
1338
1339 sid = info->bus << 8 | info->devfn;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001340 qdep = pci_ats_queue_depth(pdev);
Yu Zhao93a23a72009-05-18 13:51:37 +08001341 qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
1342 }
1343 spin_unlock_irqrestore(&device_domain_lock, flags);
1344}
1345
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001346static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
David Woodhouseea8ea462014-03-05 17:09:32 +00001347 unsigned long pfn, unsigned int pages, int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001348{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001349 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001350 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001351
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001352 BUG_ON(pages == 0);
1353
David Woodhouseea8ea462014-03-05 17:09:32 +00001354 if (ih)
1355 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001356 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001357 * Fallback to domain selective flush if no PSI support or the size is
1358 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001359 * PSI requires page size to be 2 ^ x, and the base address is naturally
1360 * aligned to the size
1361 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001362 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1363 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001364 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001365 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001366 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001367 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001368
1369 /*
Nadav Amit82653632010-04-01 13:24:40 +03001370 * In caching mode, changes of pages from non-present to present require
1371 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001372 */
Nadav Amit82653632010-04-01 13:24:40 +03001373 if (!cap_caching_mode(iommu->cap) || !map)
Yu Zhao93a23a72009-05-18 13:51:37 +08001374 iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001375}
1376
mark grossf8bab732008-02-08 04:18:38 -08001377static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1378{
1379 u32 pmen;
1380 unsigned long flags;
1381
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001382 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001383 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1384 pmen &= ~DMA_PMEN_EPM;
1385 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1386
1387 /* wait for the protected region status bit to clear */
1388 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1389 readl, !(pmen & DMA_PMEN_PRS), pmen);
1390
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001391 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001392}
1393
Jiang Liu2a41cce2014-07-11 14:19:33 +08001394static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001395{
1396 u32 sts;
1397 unsigned long flags;
1398
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001399 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001400 iommu->gcmd |= DMA_GCMD_TE;
1401 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001402
1403 /* Make sure hardware complete it */
1404 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001405 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001406
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001407 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001408}
1409
Jiang Liu2a41cce2014-07-11 14:19:33 +08001410static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001411{
1412 u32 sts;
1413 unsigned long flag;
1414
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001415 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001416 iommu->gcmd &= ~DMA_GCMD_TE;
1417 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1418
1419 /* Make sure hardware complete it */
1420 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001421 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001422
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001423 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001424}
1425
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001426
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001427static int iommu_init_domains(struct intel_iommu *iommu)
1428{
1429 unsigned long ndomains;
1430 unsigned long nlongs;
1431
1432 ndomains = cap_ndoms(iommu->cap);
Jiang Liu852bdb02014-01-06 14:18:11 +08001433 pr_debug("IOMMU%d: Number of Domains supported <%ld>\n",
1434 iommu->seq_id, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001435 nlongs = BITS_TO_LONGS(ndomains);
1436
Donald Dutile94a91b52009-08-20 16:51:34 -04001437 spin_lock_init(&iommu->lock);
1438
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001439 /* TBD: there might be 64K domains,
1440 * consider other allocation for future chip
1441 */
1442 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1443 if (!iommu->domain_ids) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001444 pr_err("IOMMU%d: allocating domain id array failed\n",
1445 iommu->seq_id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001446 return -ENOMEM;
1447 }
1448 iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
1449 GFP_KERNEL);
1450 if (!iommu->domains) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001451 pr_err("IOMMU%d: allocating domain array failed\n",
1452 iommu->seq_id);
1453 kfree(iommu->domain_ids);
1454 iommu->domain_ids = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001455 return -ENOMEM;
1456 }
1457
1458 /*
1459 * if Caching mode is set, then invalid translations are tagged
1460 * with domainid 0. Hence we need to pre-allocate it.
1461 */
1462 if (cap_caching_mode(iommu->cap))
1463 set_bit(0, iommu->domain_ids);
1464 return 0;
1465}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001466
Jiang Liuffebeb42014-11-09 22:48:02 +08001467static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001468{
1469 struct dmar_domain *domain;
Jiang Liu2a46ddf2014-07-11 14:19:30 +08001470 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001471
Donald Dutile94a91b52009-08-20 16:51:34 -04001472 if ((iommu->domains) && (iommu->domain_ids)) {
Akinobu Mitaa45946a2010-03-11 14:04:08 -08001473 for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
Jiang Liua4eaa862014-02-19 14:07:30 +08001474 /*
1475 * Domain id 0 is reserved for invalid translation
1476 * if hardware supports caching mode.
1477 */
1478 if (cap_caching_mode(iommu->cap) && i == 0)
1479 continue;
1480
Donald Dutile94a91b52009-08-20 16:51:34 -04001481 domain = iommu->domains[i];
1482 clear_bit(i, iommu->domain_ids);
Jiang Liu129ad282014-07-11 14:19:31 +08001483 if (domain_detach_iommu(domain, iommu) == 0 &&
1484 !domain_type_is_vm(domain))
Jiang Liu92d03cc2014-02-19 14:07:28 +08001485 domain_exit(domain);
Weidong Han5e98c4b2008-12-08 23:03:27 +08001486 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001487 }
1488
1489 if (iommu->gcmd & DMA_GCMD_TE)
1490 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001491}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001492
Jiang Liuffebeb42014-11-09 22:48:02 +08001493static void free_dmar_iommu(struct intel_iommu *iommu)
1494{
1495 if ((iommu->domains) && (iommu->domain_ids)) {
1496 kfree(iommu->domains);
1497 kfree(iommu->domain_ids);
1498 iommu->domains = NULL;
1499 iommu->domain_ids = NULL;
1500 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001501
Weidong Hand9630fe2008-12-08 11:06:32 +08001502 g_iommus[iommu->seq_id] = NULL;
1503
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001504 /* free context mapping */
1505 free_context_table(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001506}
1507
Jiang Liuab8dfe22014-07-11 14:19:27 +08001508static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001509{
Jiang Liu92d03cc2014-02-19 14:07:28 +08001510 /* domain id for virtual machine, it won't be set in context */
1511 static atomic_t vm_domid = ATOMIC_INIT(0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001512 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001513
1514 domain = alloc_domain_mem();
1515 if (!domain)
1516 return NULL;
1517
Jiang Liuab8dfe22014-07-11 14:19:27 +08001518 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001519 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001520 domain->flags = flags;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001521 spin_lock_init(&domain->iommu_lock);
1522 INIT_LIST_HEAD(&domain->devices);
Jiang Liuab8dfe22014-07-11 14:19:27 +08001523 if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
Jiang Liu92d03cc2014-02-19 14:07:28 +08001524 domain->id = atomic_inc_return(&vm_domid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001525
1526 return domain;
1527}
1528
Jiang Liufb170fb2014-07-11 14:19:28 +08001529static int __iommu_attach_domain(struct dmar_domain *domain,
1530 struct intel_iommu *iommu)
1531{
1532 int num;
1533 unsigned long ndomains;
1534
1535 ndomains = cap_ndoms(iommu->cap);
1536 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1537 if (num < ndomains) {
1538 set_bit(num, iommu->domain_ids);
1539 iommu->domains[num] = domain;
1540 } else {
1541 num = -ENOSPC;
1542 }
1543
1544 return num;
1545}
1546
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001547static int iommu_attach_domain(struct dmar_domain *domain,
1548 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001549{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001550 int num;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001551 unsigned long flags;
1552
Weidong Han8c11e792008-12-08 15:29:22 +08001553 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001554 num = __iommu_attach_domain(domain, iommu);
Jiang Liu44bde612014-07-11 14:19:29 +08001555 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001556 if (num < 0)
1557 pr_err("IOMMU: no free domain ids\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001558
Jiang Liufb170fb2014-07-11 14:19:28 +08001559 return num;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001560}
1561
Jiang Liu44bde612014-07-11 14:19:29 +08001562static int iommu_attach_vm_domain(struct dmar_domain *domain,
1563 struct intel_iommu *iommu)
1564{
1565 int num;
1566 unsigned long ndomains;
1567
1568 ndomains = cap_ndoms(iommu->cap);
1569 for_each_set_bit(num, iommu->domain_ids, ndomains)
1570 if (iommu->domains[num] == domain)
1571 return num;
1572
1573 return __iommu_attach_domain(domain, iommu);
1574}
1575
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001576static void iommu_detach_domain(struct dmar_domain *domain,
1577 struct intel_iommu *iommu)
1578{
1579 unsigned long flags;
1580 int num, ndomains;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001581
1582 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001583 if (domain_type_is_vm_or_si(domain)) {
1584 ndomains = cap_ndoms(iommu->cap);
1585 for_each_set_bit(num, iommu->domain_ids, ndomains) {
1586 if (iommu->domains[num] == domain) {
1587 clear_bit(num, iommu->domain_ids);
1588 iommu->domains[num] = NULL;
1589 break;
1590 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001591 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001592 } else {
1593 clear_bit(domain->id, iommu->domain_ids);
1594 iommu->domains[domain->id] = NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001595 }
Weidong Han8c11e792008-12-08 15:29:22 +08001596 spin_unlock_irqrestore(&iommu->lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001597}
1598
Jiang Liufb170fb2014-07-11 14:19:28 +08001599static void domain_attach_iommu(struct dmar_domain *domain,
1600 struct intel_iommu *iommu)
1601{
1602 unsigned long flags;
1603
1604 spin_lock_irqsave(&domain->iommu_lock, flags);
1605 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
1606 domain->iommu_count++;
1607 if (domain->iommu_count == 1)
1608 domain->nid = iommu->node;
1609 domain_update_iommu_cap(domain);
1610 }
1611 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1612}
1613
1614static int domain_detach_iommu(struct dmar_domain *domain,
1615 struct intel_iommu *iommu)
1616{
1617 unsigned long flags;
1618 int count = INT_MAX;
1619
1620 spin_lock_irqsave(&domain->iommu_lock, flags);
1621 if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
1622 count = --domain->iommu_count;
1623 domain_update_iommu_cap(domain);
1624 }
1625 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1626
1627 return count;
1628}
1629
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001630static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001631static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001632
Joseph Cihula51a63e62011-03-21 11:04:24 -07001633static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001634{
1635 struct pci_dev *pdev = NULL;
1636 struct iova *iova;
1637 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001638
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001639 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN,
1640 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001641
Mark Gross8a443df2008-03-04 14:59:31 -08001642 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1643 &reserved_rbtree_key);
1644
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001645 /* IOAPIC ranges shouldn't be accessed by DMA */
1646 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1647 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001648 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001649 printk(KERN_ERR "Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001650 return -ENODEV;
1651 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001652
1653 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1654 for_each_pci_dev(pdev) {
1655 struct resource *r;
1656
1657 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1658 r = &pdev->resource[i];
1659 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1660 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001661 iova = reserve_iova(&reserved_iova_list,
1662 IOVA_PFN(r->start),
1663 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001664 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001665 printk(KERN_ERR "Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001666 return -ENODEV;
1667 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001668 }
1669 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001670 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001671}
1672
1673static void domain_reserve_special_ranges(struct dmar_domain *domain)
1674{
1675 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1676}
1677
1678static inline int guestwidth_to_adjustwidth(int gaw)
1679{
1680 int agaw;
1681 int r = (gaw - 12) % 9;
1682
1683 if (r == 0)
1684 agaw = gaw;
1685 else
1686 agaw = gaw + 9 - r;
1687 if (agaw > 64)
1688 agaw = 64;
1689 return agaw;
1690}
1691
1692static int domain_init(struct dmar_domain *domain, int guest_width)
1693{
1694 struct intel_iommu *iommu;
1695 int adjust_width, agaw;
1696 unsigned long sagaw;
1697
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001698 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
1699 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001700 domain_reserve_special_ranges(domain);
1701
1702 /* calculate AGAW */
Weidong Han8c11e792008-12-08 15:29:22 +08001703 iommu = domain_get_iommu(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001704 if (guest_width > cap_mgaw(iommu->cap))
1705 guest_width = cap_mgaw(iommu->cap);
1706 domain->gaw = guest_width;
1707 adjust_width = guestwidth_to_adjustwidth(guest_width);
1708 agaw = width_to_agaw(adjust_width);
1709 sagaw = cap_sagaw(iommu->cap);
1710 if (!test_bit(agaw, &sagaw)) {
1711 /* hardware doesn't support it, choose a bigger one */
1712 pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
1713 agaw = find_next_bit(&sagaw, 5, agaw);
1714 if (agaw >= 5)
1715 return -ENODEV;
1716 }
1717 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001718
Weidong Han8e6040972008-12-08 15:49:06 +08001719 if (ecap_coherent(iommu->ecap))
1720 domain->iommu_coherency = 1;
1721 else
1722 domain->iommu_coherency = 0;
1723
Sheng Yang58c610b2009-03-18 15:33:05 +08001724 if (ecap_sc_support(iommu->ecap))
1725 domain->iommu_snooping = 1;
1726 else
1727 domain->iommu_snooping = 0;
1728
David Woodhouse214e39a2014-03-19 10:38:49 +00001729 if (intel_iommu_superpage)
1730 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1731 else
1732 domain->iommu_superpage = 0;
1733
Suresh Siddha4c923d42009-10-02 11:01:24 -07001734 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001735
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001736 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001737 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001738 if (!domain->pgd)
1739 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001740 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001741 return 0;
1742}
1743
1744static void domain_exit(struct dmar_domain *domain)
1745{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001746 struct dmar_drhd_unit *drhd;
1747 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00001748 struct page *freelist = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001749
1750 /* Domain 0 is reserved, so dont process it */
1751 if (!domain)
1752 return;
1753
Alex Williamson7b668352011-05-24 12:02:41 +01001754 /* Flush any lazy unmaps that may reference this domain */
1755 if (!intel_iommu_strict)
1756 flush_unmaps_timeout(0);
1757
Jiang Liu92d03cc2014-02-19 14:07:28 +08001758 /* remove associated devices */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001759 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001760
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001761 /* destroy iovas */
1762 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001763
David Woodhouseea8ea462014-03-05 17:09:32 +00001764 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001765
Jiang Liu92d03cc2014-02-19 14:07:28 +08001766 /* clear attached or cached domains */
Jiang Liu0e242612014-02-19 14:07:34 +08001767 rcu_read_lock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001768 for_each_active_iommu(iommu, drhd)
Jiang Liufb170fb2014-07-11 14:19:28 +08001769 iommu_detach_domain(domain, iommu);
Jiang Liu0e242612014-02-19 14:07:34 +08001770 rcu_read_unlock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001771
David Woodhouseea8ea462014-03-05 17:09:32 +00001772 dma_free_pagelist(freelist);
1773
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001774 free_domain_mem(domain);
1775}
1776
David Woodhouse64ae8922014-03-09 12:52:30 -07001777static int domain_context_mapping_one(struct dmar_domain *domain,
1778 struct intel_iommu *iommu,
1779 u8 bus, u8 devfn, int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001780{
1781 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001782 unsigned long flags;
Weidong Hanea6606b2008-12-08 23:08:15 +08001783 struct dma_pte *pgd;
Weidong Hanea6606b2008-12-08 23:08:15 +08001784 int id;
1785 int agaw;
Yu Zhao93a23a72009-05-18 13:51:37 +08001786 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001787
1788 pr_debug("Set context mapping for %02x:%02x.%d\n",
1789 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001790
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001791 BUG_ON(!domain->pgd);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001792 BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
1793 translation != CONTEXT_TT_MULTI_LEVEL);
Weidong Han5331fe62008-12-08 23:00:00 +08001794
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001795 context = device_to_context_entry(iommu, bus, devfn);
1796 if (!context)
1797 return -ENOMEM;
1798 spin_lock_irqsave(&iommu->lock, flags);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001799 if (context_present(context)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001800 spin_unlock_irqrestore(&iommu->lock, flags);
1801 return 0;
1802 }
1803
Weidong Hanea6606b2008-12-08 23:08:15 +08001804 id = domain->id;
1805 pgd = domain->pgd;
1806
Jiang Liuab8dfe22014-07-11 14:19:27 +08001807 if (domain_type_is_vm_or_si(domain)) {
Jiang Liu44bde612014-07-11 14:19:29 +08001808 if (domain_type_is_vm(domain)) {
1809 id = iommu_attach_vm_domain(domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08001810 if (id < 0) {
Weidong Hanea6606b2008-12-08 23:08:15 +08001811 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001812 pr_err("IOMMU: no free domain ids\n");
Weidong Hanea6606b2008-12-08 23:08:15 +08001813 return -EFAULT;
1814 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001815 }
1816
1817 /* Skip top levels of page tables for
1818 * iommu which has less agaw than default.
Chris Wright1672af12009-12-02 12:06:34 -08001819 * Unnecessary for PT mode.
Weidong Hanea6606b2008-12-08 23:08:15 +08001820 */
Chris Wright1672af12009-12-02 12:06:34 -08001821 if (translation != CONTEXT_TT_PASS_THROUGH) {
1822 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
1823 pgd = phys_to_virt(dma_pte_addr(pgd));
1824 if (!dma_pte_present(pgd)) {
1825 spin_unlock_irqrestore(&iommu->lock, flags);
1826 return -ENOMEM;
1827 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001828 }
1829 }
1830 }
1831
1832 context_set_domain_id(context, id);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001833
Yu Zhao93a23a72009-05-18 13:51:37 +08001834 if (translation != CONTEXT_TT_PASS_THROUGH) {
David Woodhouse64ae8922014-03-09 12:52:30 -07001835 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
Yu Zhao93a23a72009-05-18 13:51:37 +08001836 translation = info ? CONTEXT_TT_DEV_IOTLB :
1837 CONTEXT_TT_MULTI_LEVEL;
1838 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001839 /*
1840 * In pass through mode, AW must be programmed to indicate the largest
1841 * AGAW value supported by hardware. And ASR is ignored by hardware.
1842 */
Yu Zhao93a23a72009-05-18 13:51:37 +08001843 if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001844 context_set_address_width(context, iommu->msagaw);
Yu Zhao93a23a72009-05-18 13:51:37 +08001845 else {
1846 context_set_address_root(context, virt_to_phys(pgd));
1847 context_set_address_width(context, iommu->agaw);
1848 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001849
1850 context_set_translation_type(context, translation);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001851 context_set_fault_enable(context);
1852 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08001853 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001854
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001855 /*
1856 * It's a non-present to present mapping. If hardware doesn't cache
1857 * non-present entry we only need to flush the write-buffer. If the
1858 * _does_ cache non-present entries, then it does so in the special
1859 * domain #0, which we have to flush:
1860 */
1861 if (cap_caching_mode(iommu->cap)) {
1862 iommu->flush.flush_context(iommu, 0,
1863 (((u16)bus) << 8) | devfn,
1864 DMA_CCMD_MASK_NOBIT,
1865 DMA_CCMD_DEVICE_INVL);
Jiang Liu18fd7792014-07-11 14:19:26 +08001866 iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001867 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001868 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001869 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001870 iommu_enable_dev_iotlb(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001871 spin_unlock_irqrestore(&iommu->lock, flags);
Weidong Hanc7151a82008-12-08 22:51:37 +08001872
Jiang Liufb170fb2014-07-11 14:19:28 +08001873 domain_attach_iommu(domain, iommu);
1874
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001875 return 0;
1876}
1877
Alex Williamson579305f2014-07-03 09:51:43 -06001878struct domain_context_mapping_data {
1879 struct dmar_domain *domain;
1880 struct intel_iommu *iommu;
1881 int translation;
1882};
1883
1884static int domain_context_mapping_cb(struct pci_dev *pdev,
1885 u16 alias, void *opaque)
1886{
1887 struct domain_context_mapping_data *data = opaque;
1888
1889 return domain_context_mapping_one(data->domain, data->iommu,
1890 PCI_BUS_NUM(alias), alias & 0xff,
1891 data->translation);
1892}
1893
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001894static int
David Woodhousee1f167f2014-03-09 15:24:46 -07001895domain_context_mapping(struct dmar_domain *domain, struct device *dev,
1896 int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001897{
David Woodhouse64ae8922014-03-09 12:52:30 -07001898 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001899 u8 bus, devfn;
Alex Williamson579305f2014-07-03 09:51:43 -06001900 struct domain_context_mapping_data data;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001901
David Woodhousee1f167f2014-03-09 15:24:46 -07001902 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07001903 if (!iommu)
1904 return -ENODEV;
1905
Alex Williamson579305f2014-07-03 09:51:43 -06001906 if (!dev_is_pci(dev))
1907 return domain_context_mapping_one(domain, iommu, bus, devfn,
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001908 translation);
Alex Williamson579305f2014-07-03 09:51:43 -06001909
1910 data.domain = domain;
1911 data.iommu = iommu;
1912 data.translation = translation;
1913
1914 return pci_for_each_dma_alias(to_pci_dev(dev),
1915 &domain_context_mapping_cb, &data);
1916}
1917
1918static int domain_context_mapped_cb(struct pci_dev *pdev,
1919 u16 alias, void *opaque)
1920{
1921 struct intel_iommu *iommu = opaque;
1922
1923 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001924}
1925
David Woodhousee1f167f2014-03-09 15:24:46 -07001926static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001927{
Weidong Han5331fe62008-12-08 23:00:00 +08001928 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001929 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08001930
David Woodhousee1f167f2014-03-09 15:24:46 -07001931 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08001932 if (!iommu)
1933 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001934
Alex Williamson579305f2014-07-03 09:51:43 -06001935 if (!dev_is_pci(dev))
1936 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07001937
Alex Williamson579305f2014-07-03 09:51:43 -06001938 return !pci_for_each_dma_alias(to_pci_dev(dev),
1939 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001940}
1941
Fenghua Yuf5329592009-08-04 15:09:37 -07001942/* Returns a number of VTD pages, but aligned to MM page size */
1943static inline unsigned long aligned_nrpages(unsigned long host_addr,
1944 size_t size)
1945{
1946 host_addr &= ~PAGE_MASK;
1947 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
1948}
1949
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001950/* Return largest possible superpage level for a given mapping */
1951static inline int hardware_largepage_caps(struct dmar_domain *domain,
1952 unsigned long iov_pfn,
1953 unsigned long phy_pfn,
1954 unsigned long pages)
1955{
1956 int support, level = 1;
1957 unsigned long pfnmerge;
1958
1959 support = domain->iommu_superpage;
1960
1961 /* To use a large page, the virtual *and* physical addresses
1962 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
1963 of them will mean we have to use smaller pages. So just
1964 merge them and check both at once. */
1965 pfnmerge = iov_pfn | phy_pfn;
1966
1967 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
1968 pages >>= VTD_STRIDE_SHIFT;
1969 if (!pages)
1970 break;
1971 pfnmerge >>= VTD_STRIDE_SHIFT;
1972 level++;
1973 support--;
1974 }
1975 return level;
1976}
1977
David Woodhouse9051aa02009-06-29 12:30:54 +01001978static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
1979 struct scatterlist *sg, unsigned long phys_pfn,
1980 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01001981{
1982 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01001983 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08001984 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001985 unsigned int largepage_lvl = 0;
1986 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01001987
Jiang Liu162d1b12014-07-11 14:19:35 +08001988 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01001989
1990 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
1991 return -EINVAL;
1992
1993 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
1994
Jiang Liucc4f14a2014-11-26 09:42:10 +08001995 if (!sg) {
1996 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01001997 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
1998 }
1999
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002000 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002001 uint64_t tmp;
2002
David Woodhousee1605492009-06-29 11:17:38 +01002003 if (!sg_res) {
Fenghua Yuf5329592009-08-04 15:09:37 -07002004 sg_res = aligned_nrpages(sg->offset, sg->length);
David Woodhousee1605492009-06-29 11:17:38 +01002005 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
2006 sg->dma_length = sg->length;
2007 pteval = page_to_phys(sg_page(sg)) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002008 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002009 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002010
David Woodhousee1605492009-06-29 11:17:38 +01002011 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002012 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2013
David Woodhouse5cf0a762014-03-19 16:07:49 +00002014 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002015 if (!pte)
2016 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002017 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002018 if (largepage_lvl > 1) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002019 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002020 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2021 /*
2022 * Ensure that old small page tables are
2023 * removed to make room for superpage,
2024 * if they exist.
2025 */
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002026 dma_pte_free_pagetable(domain, iov_pfn,
Jiang Liud41a4ad2014-07-11 14:19:34 +08002027 iov_pfn + lvl_pages - 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002028 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002029 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002030 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002031
David Woodhousee1605492009-06-29 11:17:38 +01002032 }
2033 /* We don't need lock here, nobody else
2034 * touches the iova range
2035 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002036 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002037 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002038 static int dumps = 5;
David Woodhousec85994e2009-07-01 19:21:24 +01002039 printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2040 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002041 if (dumps) {
2042 dumps--;
2043 debug_dma_dump_mappings(NULL);
2044 }
2045 WARN_ON(1);
2046 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002047
2048 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2049
2050 BUG_ON(nr_pages < lvl_pages);
2051 BUG_ON(sg_res < lvl_pages);
2052
2053 nr_pages -= lvl_pages;
2054 iov_pfn += lvl_pages;
2055 phys_pfn += lvl_pages;
2056 pteval += lvl_pages * VTD_PAGE_SIZE;
2057 sg_res -= lvl_pages;
2058
2059 /* If the next PTE would be the first in a new page, then we
2060 need to flush the cache on the entries we've just written.
2061 And then we'll need to recalculate 'pte', so clear it and
2062 let it get set again in the if (!pte) block above.
2063
2064 If we're done (!nr_pages) we need to flush the cache too.
2065
2066 Also if we've been setting superpages, we may need to
2067 recalculate 'pte' and switch back to smaller pages for the
2068 end of the mapping, if the trailing size is not enough to
2069 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002070 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002071 if (!nr_pages || first_pte_in_page(pte) ||
2072 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002073 domain_flush_cache(domain, first_pte,
2074 (void *)pte - (void *)first_pte);
2075 pte = NULL;
2076 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002077
2078 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002079 sg = sg_next(sg);
2080 }
2081 return 0;
2082}
2083
David Woodhouse9051aa02009-06-29 12:30:54 +01002084static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2085 struct scatterlist *sg, unsigned long nr_pages,
2086 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002087{
David Woodhouse9051aa02009-06-29 12:30:54 +01002088 return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
2089}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002090
David Woodhouse9051aa02009-06-29 12:30:54 +01002091static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2092 unsigned long phys_pfn, unsigned long nr_pages,
2093 int prot)
2094{
2095 return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002096}
2097
Weidong Hanc7151a82008-12-08 22:51:37 +08002098static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002099{
Weidong Hanc7151a82008-12-08 22:51:37 +08002100 if (!iommu)
2101 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002102
2103 clear_context_table(iommu, bus, devfn);
2104 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002105 DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002106 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002107}
2108
David Woodhouse109b9b02012-05-25 17:43:02 +01002109static inline void unlink_domain_info(struct device_domain_info *info)
2110{
2111 assert_spin_locked(&device_domain_lock);
2112 list_del(&info->link);
2113 list_del(&info->global);
2114 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002115 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002116}
2117
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002118static void domain_remove_dev_info(struct dmar_domain *domain)
2119{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002120 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002121 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002122
2123 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wang3a74ca02014-05-20 20:37:47 +08002124 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhouse109b9b02012-05-25 17:43:02 +01002125 unlink_domain_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002126 spin_unlock_irqrestore(&device_domain_lock, flags);
2127
Yu Zhao93a23a72009-05-18 13:51:37 +08002128 iommu_disable_dev_iotlb(info);
David Woodhouse7c7faa12014-03-09 13:33:06 -07002129 iommu_detach_dev(info->iommu, info->bus, info->devfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002130
Jiang Liuab8dfe22014-07-11 14:19:27 +08002131 if (domain_type_is_vm(domain)) {
David Woodhouse7c7faa12014-03-09 13:33:06 -07002132 iommu_detach_dependent_devices(info->iommu, info->dev);
Jiang Liufb170fb2014-07-11 14:19:28 +08002133 domain_detach_iommu(domain, info->iommu);
Jiang Liu92d03cc2014-02-19 14:07:28 +08002134 }
2135
2136 free_devinfo_mem(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002137 spin_lock_irqsave(&device_domain_lock, flags);
2138 }
2139 spin_unlock_irqrestore(&device_domain_lock, flags);
2140}
2141
2142/*
2143 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002144 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002145 */
David Woodhouse1525a292014-03-06 16:19:30 +00002146static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002147{
2148 struct device_domain_info *info;
2149
2150 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002151 info = dev->archdata.iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002152 if (info)
2153 return info->domain;
2154 return NULL;
2155}
2156
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002157static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002158dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2159{
2160 struct device_domain_info *info;
2161
2162 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002163 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002164 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002165 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002166
2167 return NULL;
2168}
2169
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002170static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
David Woodhouse41e80dca2014-03-09 13:55:54 -07002171 int bus, int devfn,
David Woodhouseb718cd32014-03-09 13:11:33 -07002172 struct device *dev,
2173 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002174{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002175 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002176 struct device_domain_info *info;
2177 unsigned long flags;
2178
2179 info = alloc_devinfo_mem();
2180 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002181 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002182
Jiang Liu745f2582014-02-19 14:07:26 +08002183 info->bus = bus;
2184 info->devfn = devfn;
2185 info->dev = dev;
2186 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002187 info->iommu = iommu;
Jiang Liu745f2582014-02-19 14:07:26 +08002188
2189 spin_lock_irqsave(&device_domain_lock, flags);
2190 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002191 found = find_domain(dev);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002192 else {
2193 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002194 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002195 if (info2)
2196 found = info2->domain;
2197 }
Jiang Liu745f2582014-02-19 14:07:26 +08002198 if (found) {
2199 spin_unlock_irqrestore(&device_domain_lock, flags);
2200 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002201 /* Caller must free the original domain */
2202 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002203 }
2204
David Woodhouseb718cd32014-03-09 13:11:33 -07002205 list_add(&info->link, &domain->devices);
2206 list_add(&info->global, &device_domain_list);
2207 if (dev)
2208 dev->archdata.iommu = info;
2209 spin_unlock_irqrestore(&device_domain_lock, flags);
2210
2211 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002212}
2213
Alex Williamson579305f2014-07-03 09:51:43 -06002214static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2215{
2216 *(u16 *)opaque = alias;
2217 return 0;
2218}
2219
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002220/* domain is initialized */
David Woodhouse146922e2014-03-09 15:44:17 -07002221static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002222{
Alex Williamson579305f2014-07-03 09:51:43 -06002223 struct dmar_domain *domain, *tmp;
2224 struct intel_iommu *iommu;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002225 struct device_domain_info *info;
Alex Williamson579305f2014-07-03 09:51:43 -06002226 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002227 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002228 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002229
David Woodhouse146922e2014-03-09 15:44:17 -07002230 domain = find_domain(dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002231 if (domain)
2232 return domain;
2233
David Woodhouse146922e2014-03-09 15:44:17 -07002234 iommu = device_to_iommu(dev, &bus, &devfn);
2235 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002236 return NULL;
2237
2238 if (dev_is_pci(dev)) {
2239 struct pci_dev *pdev = to_pci_dev(dev);
2240
2241 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2242
2243 spin_lock_irqsave(&device_domain_lock, flags);
2244 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2245 PCI_BUS_NUM(dma_alias),
2246 dma_alias & 0xff);
2247 if (info) {
2248 iommu = info->iommu;
2249 domain = info->domain;
2250 }
2251 spin_unlock_irqrestore(&device_domain_lock, flags);
2252
2253 /* DMA alias already has a domain, uses it */
2254 if (info)
2255 goto found_domain;
2256 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002257
David Woodhouse146922e2014-03-09 15:44:17 -07002258 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002259 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002260 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002261 return NULL;
Jiang Liu44bde612014-07-11 14:19:29 +08002262 domain->id = iommu_attach_domain(domain, iommu);
2263 if (domain->id < 0) {
Alex Williamson2fe9723d2011-03-04 14:52:30 -07002264 free_domain_mem(domain);
Alex Williamson579305f2014-07-03 09:51:43 -06002265 return NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002266 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002267 domain_attach_iommu(domain, iommu);
Alex Williamson579305f2014-07-03 09:51:43 -06002268 if (domain_init(domain, gaw)) {
2269 domain_exit(domain);
2270 return NULL;
2271 }
2272
2273 /* register PCI DMA alias device */
2274 if (dev_is_pci(dev)) {
2275 tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2276 dma_alias & 0xff, NULL, domain);
2277
2278 if (!tmp || tmp != domain) {
2279 domain_exit(domain);
2280 domain = tmp;
2281 }
2282
David Woodhouseb718cd32014-03-09 13:11:33 -07002283 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002284 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002285 }
2286
2287found_domain:
Alex Williamson579305f2014-07-03 09:51:43 -06002288 tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
2289
2290 if (!tmp || tmp != domain) {
2291 domain_exit(domain);
2292 domain = tmp;
2293 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002294
2295 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002296}
2297
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002298static int iommu_identity_mapping;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002299#define IDENTMAP_ALL 1
2300#define IDENTMAP_GFX 2
2301#define IDENTMAP_AZALIA 4
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002302
David Woodhouseb2132032009-06-26 18:50:28 +01002303static int iommu_domain_identity_map(struct dmar_domain *domain,
2304 unsigned long long start,
2305 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002306{
David Woodhousec5395d52009-06-28 16:35:56 +01002307 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2308 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002309
David Woodhousec5395d52009-06-28 16:35:56 +01002310 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2311 dma_to_mm_pfn(last_vpfn))) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002312 printk(KERN_ERR "IOMMU: reserve iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002313 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002314 }
2315
David Woodhousec5395d52009-06-28 16:35:56 +01002316 pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
2317 start, end, domain->id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002318 /*
2319 * RMRR range might have overlap with physical memory range,
2320 * clear it first
2321 */
David Woodhousec5395d52009-06-28 16:35:56 +01002322 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002323
David Woodhousec5395d52009-06-28 16:35:56 +01002324 return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
2325 last_vpfn - first_vpfn + 1,
David Woodhouse61df7442009-06-28 11:55:58 +01002326 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002327}
2328
David Woodhouse0b9d9752014-03-09 15:48:15 -07002329static int iommu_prepare_identity_map(struct device *dev,
David Woodhouseb2132032009-06-26 18:50:28 +01002330 unsigned long long start,
2331 unsigned long long end)
2332{
2333 struct dmar_domain *domain;
2334 int ret;
2335
David Woodhouse0b9d9752014-03-09 15:48:15 -07002336 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
David Woodhouseb2132032009-06-26 18:50:28 +01002337 if (!domain)
2338 return -ENOMEM;
2339
David Woodhouse19943b02009-08-04 16:19:20 +01002340 /* For _hardware_ passthrough, don't bother. But for software
2341 passthrough, we do it anyway -- it may indicate a memory
2342 range which is reserved in E820, so which didn't get set
2343 up to start with in si_domain */
2344 if (domain == si_domain && hw_pass_through) {
2345 printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002346 dev_name(dev), start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002347 return 0;
2348 }
2349
2350 printk(KERN_INFO
2351 "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002352 dev_name(dev), start, end);
David Woodhouse2ff729f2009-08-26 14:25:41 +01002353
David Woodhouse5595b522009-12-02 09:21:55 +00002354 if (end < start) {
2355 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2356 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2357 dmi_get_system_info(DMI_BIOS_VENDOR),
2358 dmi_get_system_info(DMI_BIOS_VERSION),
2359 dmi_get_system_info(DMI_PRODUCT_VERSION));
2360 ret = -EIO;
2361 goto error;
2362 }
2363
David Woodhouse2ff729f2009-08-26 14:25:41 +01002364 if (end >> agaw_to_width(domain->agaw)) {
2365 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2366 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2367 agaw_to_width(domain->agaw),
2368 dmi_get_system_info(DMI_BIOS_VENDOR),
2369 dmi_get_system_info(DMI_BIOS_VERSION),
2370 dmi_get_system_info(DMI_PRODUCT_VERSION));
2371 ret = -EIO;
2372 goto error;
2373 }
David Woodhouse19943b02009-08-04 16:19:20 +01002374
David Woodhouseb2132032009-06-26 18:50:28 +01002375 ret = iommu_domain_identity_map(domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002376 if (ret)
2377 goto error;
2378
2379 /* context entry init */
David Woodhouse0b9d9752014-03-09 15:48:15 -07002380 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
David Woodhouseb2132032009-06-26 18:50:28 +01002381 if (ret)
2382 goto error;
2383
2384 return 0;
2385
2386 error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002387 domain_exit(domain);
2388 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002389}
2390
2391static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002392 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002393{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002394 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002395 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002396 return iommu_prepare_identity_map(dev, rmrr->base_address,
2397 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002398}
2399
Suresh Siddhad3f13812011-08-23 17:05:25 -07002400#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002401static inline void iommu_prepare_isa(void)
2402{
2403 struct pci_dev *pdev;
2404 int ret;
2405
2406 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2407 if (!pdev)
2408 return;
2409
David Woodhousec7ab48d2009-06-26 19:10:36 +01002410 printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002411 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002412
2413 if (ret)
David Woodhousec7ab48d2009-06-26 19:10:36 +01002414 printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
2415 "floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002416
Yijing Wang9b27e822014-05-20 20:37:52 +08002417 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002418}
2419#else
2420static inline void iommu_prepare_isa(void)
2421{
2422 return;
2423}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002424#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002425
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002426static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002427
Matt Kraai071e1372009-08-23 22:30:22 -07002428static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002429{
2430 struct dmar_drhd_unit *drhd;
2431 struct intel_iommu *iommu;
David Woodhousec7ab48d2009-06-26 19:10:36 +01002432 int nid, ret = 0;
Jiang Liu44bde612014-07-11 14:19:29 +08002433 bool first = true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002434
Jiang Liuab8dfe22014-07-11 14:19:27 +08002435 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002436 if (!si_domain)
2437 return -EFAULT;
2438
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002439 for_each_active_iommu(iommu, drhd) {
2440 ret = iommu_attach_domain(si_domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08002441 if (ret < 0) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002442 domain_exit(si_domain);
2443 return -EFAULT;
Jiang Liu44bde612014-07-11 14:19:29 +08002444 } else if (first) {
2445 si_domain->id = ret;
2446 first = false;
2447 } else if (si_domain->id != ret) {
2448 domain_exit(si_domain);
2449 return -EFAULT;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002450 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002451 domain_attach_iommu(si_domain, iommu);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002452 }
2453
2454 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2455 domain_exit(si_domain);
2456 return -EFAULT;
2457 }
2458
Jiang Liu9544c002014-01-06 14:18:13 +08002459 pr_debug("IOMMU: identity mapping domain is domain %d\n",
2460 si_domain->id);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002461
David Woodhouse19943b02009-08-04 16:19:20 +01002462 if (hw)
2463 return 0;
2464
David Woodhousec7ab48d2009-06-26 19:10:36 +01002465 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002466 unsigned long start_pfn, end_pfn;
2467 int i;
2468
2469 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2470 ret = iommu_domain_identity_map(si_domain,
2471 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2472 if (ret)
2473 return ret;
2474 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002475 }
2476
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002477 return 0;
2478}
2479
David Woodhouse9b226622014-03-09 14:03:28 -07002480static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002481{
2482 struct device_domain_info *info;
2483
2484 if (likely(!iommu_identity_mapping))
2485 return 0;
2486
David Woodhouse9b226622014-03-09 14:03:28 -07002487 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002488 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2489 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002490
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002491 return 0;
2492}
2493
2494static int domain_add_dev_info(struct dmar_domain *domain,
David Woodhouse5913c9b2014-03-09 16:27:31 -07002495 struct device *dev, int translation)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002496{
David Woodhouse0ac72662014-03-09 13:19:22 -07002497 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002498 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002499 u8 bus, devfn;
David Woodhouse5fe60f42009-08-09 10:53:41 +01002500 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002501
David Woodhouse5913c9b2014-03-09 16:27:31 -07002502 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002503 if (!iommu)
2504 return -ENODEV;
2505
David Woodhouse5913c9b2014-03-09 16:27:31 -07002506 ndomain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002507 if (ndomain != domain)
2508 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002509
David Woodhouse5913c9b2014-03-09 16:27:31 -07002510 ret = domain_context_mapping(domain, dev, translation);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002511 if (ret) {
David Woodhouse5913c9b2014-03-09 16:27:31 -07002512 domain_remove_one_dev_info(domain, dev);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002513 return ret;
2514 }
2515
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002516 return 0;
2517}
2518
David Woodhouse0b9d9752014-03-09 15:48:15 -07002519static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002520{
2521 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002522 struct device *tmp;
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002523 int i;
2524
Jiang Liu0e242612014-02-19 14:07:34 +08002525 rcu_read_lock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002526 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002527 /*
2528 * Return TRUE if this RMRR contains the device that
2529 * is passed in.
2530 */
2531 for_each_active_dev_scope(rmrr->devices,
2532 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002533 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002534 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002535 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002536 }
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002537 }
Jiang Liu0e242612014-02-19 14:07:34 +08002538 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002539 return false;
2540}
2541
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002542/*
2543 * There are a couple cases where we need to restrict the functionality of
2544 * devices associated with RMRRs. The first is when evaluating a device for
2545 * identity mapping because problems exist when devices are moved in and out
2546 * of domains and their respective RMRR information is lost. This means that
2547 * a device with associated RMRRs will never be in a "passthrough" domain.
2548 * The second is use of the device through the IOMMU API. This interface
2549 * expects to have full control of the IOVA space for the device. We cannot
2550 * satisfy both the requirement that RMRR access is maintained and have an
2551 * unencumbered IOVA space. We also have no ability to quiesce the device's
2552 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2553 * We therefore prevent devices associated with an RMRR from participating in
2554 * the IOMMU API, which eliminates them from device assignment.
2555 *
2556 * In both cases we assume that PCI USB devices with RMRRs have them largely
2557 * for historical reasons and that the RMRR space is not actively used post
2558 * boot. This exclusion may change if vendors begin to abuse it.
2559 */
2560static bool device_is_rmrr_locked(struct device *dev)
2561{
2562 if (!device_has_rmrr(dev))
2563 return false;
2564
2565 if (dev_is_pci(dev)) {
2566 struct pci_dev *pdev = to_pci_dev(dev);
2567
2568 if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
2569 return false;
2570 }
2571
2572 return true;
2573}
2574
David Woodhouse3bdb2592014-03-09 16:03:08 -07002575static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002576{
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002577
David Woodhouse3bdb2592014-03-09 16:03:08 -07002578 if (dev_is_pci(dev)) {
2579 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002580
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002581 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002582 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002583
David Woodhouse3bdb2592014-03-09 16:03:08 -07002584 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2585 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002586
David Woodhouse3bdb2592014-03-09 16:03:08 -07002587 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2588 return 1;
2589
2590 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2591 return 0;
2592
2593 /*
2594 * We want to start off with all devices in the 1:1 domain, and
2595 * take them out later if we find they can't access all of memory.
2596 *
2597 * However, we can't do this for PCI devices behind bridges,
2598 * because all PCI devices behind the same bridge will end up
2599 * with the same source-id on their transactions.
2600 *
2601 * Practically speaking, we can't change things around for these
2602 * devices at run-time, because we can't be sure there'll be no
2603 * DMA transactions in flight for any of their siblings.
2604 *
2605 * So PCI devices (unless they're on the root bus) as well as
2606 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2607 * the 1:1 domain, just in _case_ one of their siblings turns out
2608 * not to be able to map all of memory.
2609 */
2610 if (!pci_is_pcie(pdev)) {
2611 if (!pci_is_root_bus(pdev->bus))
2612 return 0;
2613 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2614 return 0;
2615 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2616 return 0;
2617 } else {
2618 if (device_has_rmrr(dev))
2619 return 0;
2620 }
David Woodhouse6941af22009-07-04 18:24:27 +01002621
David Woodhouse3dfc8132009-07-04 19:11:08 +01002622 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002623 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002624 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002625 * take them out of the 1:1 domain later.
2626 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002627 if (!startup) {
2628 /*
2629 * If the device's dma_mask is less than the system's memory
2630 * size then this is not a candidate for identity mapping.
2631 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002632 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002633
David Woodhouse3bdb2592014-03-09 16:03:08 -07002634 if (dev->coherent_dma_mask &&
2635 dev->coherent_dma_mask < dma_mask)
2636 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002637
David Woodhouse3bdb2592014-03-09 16:03:08 -07002638 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05002639 }
David Woodhouse6941af22009-07-04 18:24:27 +01002640
2641 return 1;
2642}
2643
David Woodhousecf04eee2014-03-21 16:49:04 +00002644static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
2645{
2646 int ret;
2647
2648 if (!iommu_should_identity_map(dev, 1))
2649 return 0;
2650
2651 ret = domain_add_dev_info(si_domain, dev,
2652 hw ? CONTEXT_TT_PASS_THROUGH :
2653 CONTEXT_TT_MULTI_LEVEL);
2654 if (!ret)
2655 pr_info("IOMMU: %s identity mapping for device %s\n",
2656 hw ? "hardware" : "software", dev_name(dev));
2657 else if (ret == -ENODEV)
2658 /* device not associated with an iommu */
2659 ret = 0;
2660
2661 return ret;
2662}
2663
2664
Matt Kraai071e1372009-08-23 22:30:22 -07002665static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002666{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002667 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00002668 struct dmar_drhd_unit *drhd;
2669 struct intel_iommu *iommu;
2670 struct device *dev;
2671 int i;
2672 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002673
David Woodhouse19943b02009-08-04 16:19:20 +01002674 ret = si_domain_init(hw);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002675 if (ret)
2676 return -EFAULT;
2677
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002678 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00002679 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
2680 if (ret)
2681 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002682 }
2683
David Woodhousecf04eee2014-03-21 16:49:04 +00002684 for_each_active_iommu(iommu, drhd)
2685 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
2686 struct acpi_device_physical_node *pn;
2687 struct acpi_device *adev;
2688
2689 if (dev->bus != &acpi_bus_type)
2690 continue;
2691
2692 adev= to_acpi_device(dev);
2693 mutex_lock(&adev->physical_node_lock);
2694 list_for_each_entry(pn, &adev->physical_node_list, node) {
2695 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
2696 if (ret)
2697 break;
2698 }
2699 mutex_unlock(&adev->physical_node_lock);
2700 if (ret)
2701 return ret;
2702 }
2703
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002704 return 0;
2705}
2706
Jiang Liuffebeb42014-11-09 22:48:02 +08002707static void intel_iommu_init_qi(struct intel_iommu *iommu)
2708{
2709 /*
2710 * Start from the sane iommu hardware state.
2711 * If the queued invalidation is already initialized by us
2712 * (for example, while enabling interrupt-remapping) then
2713 * we got the things already rolling from a sane state.
2714 */
2715 if (!iommu->qi) {
2716 /*
2717 * Clear any previous faults.
2718 */
2719 dmar_fault(-1, iommu);
2720 /*
2721 * Disable queued invalidation if supported and already enabled
2722 * before OS handover.
2723 */
2724 dmar_disable_qi(iommu);
2725 }
2726
2727 if (dmar_enable_qi(iommu)) {
2728 /*
2729 * Queued Invalidate not enabled, use Register Based Invalidate
2730 */
2731 iommu->flush.flush_context = __iommu_flush_context;
2732 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
2733 pr_info("IOMMU: %s using Register based invalidation\n",
2734 iommu->name);
2735 } else {
2736 iommu->flush.flush_context = qi_flush_context;
2737 iommu->flush.flush_iotlb = qi_flush_iotlb;
2738 pr_info("IOMMU: %s using Queued invalidation\n", iommu->name);
2739 }
2740}
2741
Joseph Cihulab7792602011-05-03 00:08:37 -07002742static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002743{
2744 struct dmar_drhd_unit *drhd;
2745 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002746 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002747 struct intel_iommu *iommu;
Suresh Siddha9d783ba2009-03-16 17:04:55 -07002748 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002749
2750 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002751 * for each drhd
2752 * allocate root
2753 * initialize and program root entry to not present
2754 * endfor
2755 */
2756 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08002757 /*
2758 * lock not needed as this is only incremented in the single
2759 * threaded kernel __init code path all other access are read
2760 * only
2761 */
Jiang Liu78d8e702014-11-09 22:47:57 +08002762 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08002763 g_num_of_iommus++;
2764 continue;
2765 }
2766 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
Jiang Liu78d8e702014-11-09 22:47:57 +08002767 DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08002768 }
2769
Jiang Liuffebeb42014-11-09 22:48:02 +08002770 /* Preallocate enough resources for IOMMU hot-addition */
2771 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
2772 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
2773
Weidong Hand9630fe2008-12-08 11:06:32 +08002774 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
2775 GFP_KERNEL);
2776 if (!g_iommus) {
2777 printk(KERN_ERR "Allocating global iommu array failed\n");
2778 ret = -ENOMEM;
2779 goto error;
2780 }
2781
mark gross80b20dd2008-04-18 13:53:58 -07002782 deferred_flush = kzalloc(g_num_of_iommus *
2783 sizeof(struct deferred_flush_tables), GFP_KERNEL);
2784 if (!deferred_flush) {
mark gross5e0d2a62008-03-04 15:22:08 -08002785 ret = -ENOMEM;
Jiang Liu989d51f2014-02-19 14:07:21 +08002786 goto free_g_iommus;
mark gross5e0d2a62008-03-04 15:22:08 -08002787 }
2788
Jiang Liu7c919772014-01-06 14:18:18 +08002789 for_each_active_iommu(iommu, drhd) {
Weidong Hand9630fe2008-12-08 11:06:32 +08002790 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002791
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002792 ret = iommu_init_domains(iommu);
2793 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002794 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002795
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002796 /*
2797 * TBD:
2798 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002799 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002800 */
2801 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002802 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002803 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002804 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01002805 hw_pass_through = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002806 }
2807
Jiang Liuffebeb42014-11-09 22:48:02 +08002808 for_each_active_iommu(iommu, drhd)
2809 intel_iommu_init_qi(iommu);
Youquan Songa77b67d2008-10-16 16:31:56 -07002810
David Woodhouse19943b02009-08-04 16:19:20 +01002811 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07002812 iommu_identity_mapping |= IDENTMAP_ALL;
2813
Suresh Siddhad3f13812011-08-23 17:05:25 -07002814#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07002815 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01002816#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07002817
2818 check_tylersburg_isoch();
2819
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002820 /*
2821 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002822 * identity mappings for rmrr, gfx, and isa and may fall back to static
2823 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002824 */
David Woodhouse19943b02009-08-04 16:19:20 +01002825 if (iommu_identity_mapping) {
2826 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
2827 if (ret) {
2828 printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08002829 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002830 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002831 }
David Woodhouse19943b02009-08-04 16:19:20 +01002832 /*
2833 * For each rmrr
2834 * for each dev attached to rmrr
2835 * do
2836 * locate drhd for dev, alloc domain for dev
2837 * allocate free domain
2838 * allocate page table entries for rmrr
2839 * if context not allocated for bus
2840 * allocate and init context
2841 * set present in root table for this bus
2842 * init context with domain, translation etc
2843 * endfor
2844 * endfor
2845 */
2846 printk(KERN_INFO "IOMMU: Setting RMRR:\n");
2847 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002848 /* some BIOS lists non-exist devices in DMAR table. */
2849 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00002850 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07002851 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01002852 if (ret)
2853 printk(KERN_ERR
2854 "IOMMU: mapping reserved region failed\n");
2855 }
2856 }
2857
2858 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002859
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002860 /*
2861 * for each drhd
2862 * enable fault log
2863 * global invalidate context cache
2864 * global invalidate iotlb
2865 * enable translation
2866 */
Jiang Liu7c919772014-01-06 14:18:18 +08002867 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07002868 if (drhd->ignored) {
2869 /*
2870 * we always have to disable PMRs or DMA may fail on
2871 * this device
2872 */
2873 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08002874 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002875 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07002876 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002877
2878 iommu_flush_write_buffer(iommu);
2879
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002880 ret = dmar_set_interrupt(iommu);
2881 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002882 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002883
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002884 iommu_set_root_entry(iommu);
2885
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002886 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002887 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Jiang Liu2a41cce2014-07-11 14:19:33 +08002888 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07002889 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002890 }
2891
2892 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08002893
2894free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08002895 for_each_active_iommu(iommu, drhd) {
2896 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08002897 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002898 }
Jiang Liu9bdc5312014-01-06 14:18:27 +08002899 kfree(deferred_flush);
Jiang Liu989d51f2014-02-19 14:07:21 +08002900free_g_iommus:
Weidong Hand9630fe2008-12-08 11:06:32 +08002901 kfree(g_iommus);
Jiang Liu989d51f2014-02-19 14:07:21 +08002902error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002903 return ret;
2904}
2905
David Woodhouse5a5e02a2009-07-04 09:35:44 +01002906/* This takes a number of _MM_ pages, not VTD pages */
David Woodhouse875764d2009-06-28 21:20:51 +01002907static struct iova *intel_alloc_iova(struct device *dev,
2908 struct dmar_domain *domain,
2909 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002910{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002911 struct iova *iova = NULL;
2912
David Woodhouse875764d2009-06-28 21:20:51 +01002913 /* Restrict dma_mask to the width that the iommu can handle */
2914 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
2915
2916 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002917 /*
2918 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07002919 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08002920 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002921 */
David Woodhouse875764d2009-06-28 21:20:51 +01002922 iova = alloc_iova(&domain->iovad, nrpages,
2923 IOVA_PFN(DMA_BIT_MASK(32)), 1);
2924 if (iova)
2925 return iova;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002926 }
David Woodhouse875764d2009-06-28 21:20:51 +01002927 iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
2928 if (unlikely(!iova)) {
2929 printk(KERN_ERR "Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07002930 nrpages, dev_name(dev));
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002931 return NULL;
2932 }
2933
2934 return iova;
2935}
2936
David Woodhoused4b709f2014-03-09 16:07:40 -07002937static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002938{
2939 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002940 int ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002941
David Woodhoused4b709f2014-03-09 16:07:40 -07002942 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002943 if (!domain) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002944 printk(KERN_ERR "Allocating domain for %s failed",
2945 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002946 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002947 }
2948
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002949 /* make sure context mapping is ok */
David Woodhoused4b709f2014-03-09 16:07:40 -07002950 if (unlikely(!domain_context_mapped(dev))) {
2951 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002952 if (ret) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002953 printk(KERN_ERR "Domain context map for %s failed",
2954 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002955 return NULL;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002956 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002957 }
2958
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002959 return domain;
2960}
2961
David Woodhoused4b709f2014-03-09 16:07:40 -07002962static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
David Woodhouse147202a2009-07-07 19:43:20 +01002963{
2964 struct device_domain_info *info;
2965
2966 /* No lock here, assumes no domain exit in normal case */
David Woodhoused4b709f2014-03-09 16:07:40 -07002967 info = dev->archdata.iommu;
David Woodhouse147202a2009-07-07 19:43:20 +01002968 if (likely(info))
2969 return info->domain;
2970
2971 return __get_valid_domain_for_dev(dev);
2972}
2973
David Woodhouse3d891942014-03-06 15:59:26 +00002974static int iommu_dummy(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002975{
David Woodhouse3d891942014-03-06 15:59:26 +00002976 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002977}
2978
David Woodhouseecb509e2014-03-09 16:29:55 -07002979/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01002980static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002981{
2982 int found;
2983
David Woodhouse3d891942014-03-06 15:59:26 +00002984 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002985 return 1;
2986
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002987 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002988 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002989
David Woodhouse9b226622014-03-09 14:03:28 -07002990 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002991 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07002992 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002993 return 1;
2994 else {
2995 /*
2996 * 32 bit DMA is removed from si_domain and fall back
2997 * to non-identity mapping.
2998 */
David Woodhousebf9c9ed2014-03-09 16:19:13 -07002999 domain_remove_one_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003000 printk(KERN_INFO "32bit %s uses non-identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07003001 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003002 return 0;
3003 }
3004 } else {
3005 /*
3006 * In case of a detached 64 bit DMA device from vm, the device
3007 * is put into si_domain for identity mapping.
3008 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003009 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003010 int ret;
David Woodhouse5913c9b2014-03-09 16:27:31 -07003011 ret = domain_add_dev_info(si_domain, dev,
David Woodhouse5fe60f42009-08-09 10:53:41 +01003012 hw_pass_through ?
3013 CONTEXT_TT_PASS_THROUGH :
3014 CONTEXT_TT_MULTI_LEVEL);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003015 if (!ret) {
3016 printk(KERN_INFO "64bit %s uses identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07003017 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003018 return 1;
3019 }
3020 }
3021 }
3022
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003023 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003024}
3025
David Woodhouse5040a912014-03-09 16:14:00 -07003026static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003027 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003028{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003029 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003030 phys_addr_t start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003031 struct iova *iova;
3032 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003033 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003034 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003035 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003036
3037 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003038
David Woodhouse5040a912014-03-09 16:14:00 -07003039 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003040 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003041
David Woodhouse5040a912014-03-09 16:14:00 -07003042 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003043 if (!domain)
3044 return 0;
3045
Weidong Han8c11e792008-12-08 15:29:22 +08003046 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003047 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003048
David Woodhouse5040a912014-03-09 16:14:00 -07003049 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003050 if (!iova)
3051 goto error;
3052
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003053 /*
3054 * Check if DMAR supports zero-length reads on write only
3055 * mappings..
3056 */
3057 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003058 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003059 prot |= DMA_PTE_READ;
3060 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3061 prot |= DMA_PTE_WRITE;
3062 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003063 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003064 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003065 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003066 * is not a big problem
3067 */
David Woodhouse0ab36de2009-06-28 14:01:43 +01003068 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003069 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003070 if (ret)
3071 goto error;
3072
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003073 /* it's a non-present to present mapping. Only flush if caching mode */
3074 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003075 iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003076 else
Weidong Han8c11e792008-12-08 15:29:22 +08003077 iommu_flush_write_buffer(iommu);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003078
David Woodhouse03d6a242009-06-28 15:33:46 +01003079 start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
3080 start_paddr += paddr & ~PAGE_MASK;
3081 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003082
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003083error:
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003084 if (iova)
3085 __free_iova(&domain->iovad, iova);
David Woodhouse4cf2e752009-02-11 17:23:43 +00003086 printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003087 dev_name(dev), size, (unsigned long long)paddr, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003088 return 0;
3089}
3090
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003091static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3092 unsigned long offset, size_t size,
3093 enum dma_data_direction dir,
3094 struct dma_attrs *attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003095{
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003096 return __intel_map_single(dev, page_to_phys(page) + offset, size,
David Woodhouse46333e32014-03-10 20:01:21 -07003097 dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003098}
3099
mark gross5e0d2a62008-03-04 15:22:08 -08003100static void flush_unmaps(void)
3101{
mark gross80b20dd2008-04-18 13:53:58 -07003102 int i, j;
mark gross5e0d2a62008-03-04 15:22:08 -08003103
mark gross5e0d2a62008-03-04 15:22:08 -08003104 timer_on = 0;
3105
3106 /* just flush them all */
3107 for (i = 0; i < g_num_of_iommus; i++) {
Weidong Hana2bb8452008-12-08 11:24:12 +08003108 struct intel_iommu *iommu = g_iommus[i];
3109 if (!iommu)
3110 continue;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003111
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003112 if (!deferred_flush[i].next)
3113 continue;
3114
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003115 /* In caching mode, global flushes turn emulation expensive */
3116 if (!cap_caching_mode(iommu->cap))
3117 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
Yu Zhao93a23a72009-05-18 13:51:37 +08003118 DMA_TLB_GLOBAL_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003119 for (j = 0; j < deferred_flush[i].next; j++) {
Yu Zhao93a23a72009-05-18 13:51:37 +08003120 unsigned long mask;
3121 struct iova *iova = deferred_flush[i].iova[j];
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003122 struct dmar_domain *domain = deferred_flush[i].domain[j];
Yu Zhao93a23a72009-05-18 13:51:37 +08003123
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003124 /* On real hardware multiple invalidations are expensive */
3125 if (cap_caching_mode(iommu->cap))
3126 iommu_flush_iotlb_psi(iommu, domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08003127 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00003128 !deferred_flush[i].freelist[j], 0);
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003129 else {
Jiang Liua156ef92014-07-11 14:19:36 +08003130 mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003131 iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
3132 (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
3133 }
Yu Zhao93a23a72009-05-18 13:51:37 +08003134 __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003135 if (deferred_flush[i].freelist[j])
3136 dma_free_pagelist(deferred_flush[i].freelist[j]);
mark gross80b20dd2008-04-18 13:53:58 -07003137 }
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003138 deferred_flush[i].next = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003139 }
3140
mark gross5e0d2a62008-03-04 15:22:08 -08003141 list_size = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003142}
3143
3144static void flush_unmaps_timeout(unsigned long data)
3145{
mark gross80b20dd2008-04-18 13:53:58 -07003146 unsigned long flags;
3147
3148 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003149 flush_unmaps();
mark gross80b20dd2008-04-18 13:53:58 -07003150 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003151}
3152
David Woodhouseea8ea462014-03-05 17:09:32 +00003153static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist)
mark gross5e0d2a62008-03-04 15:22:08 -08003154{
3155 unsigned long flags;
mark gross80b20dd2008-04-18 13:53:58 -07003156 int next, iommu_id;
Weidong Han8c11e792008-12-08 15:29:22 +08003157 struct intel_iommu *iommu;
mark gross5e0d2a62008-03-04 15:22:08 -08003158
3159 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross80b20dd2008-04-18 13:53:58 -07003160 if (list_size == HIGH_WATER_MARK)
3161 flush_unmaps();
3162
Weidong Han8c11e792008-12-08 15:29:22 +08003163 iommu = domain_get_iommu(dom);
3164 iommu_id = iommu->seq_id;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003165
mark gross80b20dd2008-04-18 13:53:58 -07003166 next = deferred_flush[iommu_id].next;
3167 deferred_flush[iommu_id].domain[next] = dom;
3168 deferred_flush[iommu_id].iova[next] = iova;
David Woodhouseea8ea462014-03-05 17:09:32 +00003169 deferred_flush[iommu_id].freelist[next] = freelist;
mark gross80b20dd2008-04-18 13:53:58 -07003170 deferred_flush[iommu_id].next++;
mark gross5e0d2a62008-03-04 15:22:08 -08003171
3172 if (!timer_on) {
3173 mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
3174 timer_on = 1;
3175 }
3176 list_size++;
3177 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
3178}
3179
Jiang Liud41a4ad2014-07-11 14:19:34 +08003180static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003181{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003182 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003183 unsigned long start_pfn, last_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003184 struct iova *iova;
Weidong Han8c11e792008-12-08 15:29:22 +08003185 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003186 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003187
David Woodhouse73676832009-07-04 14:08:36 +01003188 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003189 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003190
David Woodhouse1525a292014-03-06 16:19:30 +00003191 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003192 BUG_ON(!domain);
3193
Weidong Han8c11e792008-12-08 15:29:22 +08003194 iommu = domain_get_iommu(domain);
3195
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003196 iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
David Woodhouse85b98272009-07-01 19:27:53 +01003197 if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
3198 (unsigned long long)dev_addr))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003199 return;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003200
David Woodhoused794dc92009-06-28 00:27:49 +01003201 start_pfn = mm_to_dma_pfn(iova->pfn_lo);
3202 last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003203
David Woodhoused794dc92009-06-28 00:27:49 +01003204 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003205 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003206
David Woodhouseea8ea462014-03-05 17:09:32 +00003207 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003208
mark gross5e0d2a62008-03-04 15:22:08 -08003209 if (intel_iommu_strict) {
David Woodhouse03d6a242009-06-28 15:33:46 +01003210 iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
David Woodhouseea8ea462014-03-05 17:09:32 +00003211 last_pfn - start_pfn + 1, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003212 /* free iova */
3213 __free_iova(&domain->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003214 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003215 } else {
David Woodhouseea8ea462014-03-05 17:09:32 +00003216 add_unmap(domain, iova, freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003217 /*
3218 * queue up the release of the unmap to save the 1/6th of the
3219 * cpu used up by the iotlb flush operation...
3220 */
mark gross5e0d2a62008-03-04 15:22:08 -08003221 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003222}
3223
Jiang Liud41a4ad2014-07-11 14:19:34 +08003224static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3225 size_t size, enum dma_data_direction dir,
3226 struct dma_attrs *attrs)
3227{
3228 intel_unmap(dev, dev_addr);
3229}
3230
David Woodhouse5040a912014-03-09 16:14:00 -07003231static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003232 dma_addr_t *dma_handle, gfp_t flags,
3233 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003234{
Akinobu Mita36746432014-06-04 16:06:51 -07003235 struct page *page = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003236 int order;
3237
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003238 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003239 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003240
David Woodhouse5040a912014-03-09 16:14:00 -07003241 if (!iommu_no_mapping(dev))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003242 flags &= ~(GFP_DMA | GFP_DMA32);
David Woodhouse5040a912014-03-09 16:14:00 -07003243 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3244 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003245 flags |= GFP_DMA;
3246 else
3247 flags |= GFP_DMA32;
3248 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003249
Akinobu Mita36746432014-06-04 16:06:51 -07003250 if (flags & __GFP_WAIT) {
3251 unsigned int count = size >> PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003252
Akinobu Mita36746432014-06-04 16:06:51 -07003253 page = dma_alloc_from_contiguous(dev, count, order);
3254 if (page && iommu_no_mapping(dev) &&
3255 page_to_phys(page) + size > dev->coherent_dma_mask) {
3256 dma_release_from_contiguous(dev, page, count);
3257 page = NULL;
3258 }
3259 }
3260
3261 if (!page)
3262 page = alloc_pages(flags, order);
3263 if (!page)
3264 return NULL;
3265 memset(page_address(page), 0, size);
3266
3267 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003268 DMA_BIDIRECTIONAL,
David Woodhouse5040a912014-03-09 16:14:00 -07003269 dev->coherent_dma_mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003270 if (*dma_handle)
Akinobu Mita36746432014-06-04 16:06:51 -07003271 return page_address(page);
3272 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3273 __free_pages(page, order);
3274
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003275 return NULL;
3276}
3277
David Woodhouse5040a912014-03-09 16:14:00 -07003278static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003279 dma_addr_t dma_handle, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003280{
3281 int order;
Akinobu Mita36746432014-06-04 16:06:51 -07003282 struct page *page = virt_to_page(vaddr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003283
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003284 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003285 order = get_order(size);
3286
Jiang Liud41a4ad2014-07-11 14:19:34 +08003287 intel_unmap(dev, dma_handle);
Akinobu Mita36746432014-06-04 16:06:51 -07003288 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3289 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003290}
3291
David Woodhouse5040a912014-03-09 16:14:00 -07003292static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003293 int nelems, enum dma_data_direction dir,
3294 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003295{
Jiang Liud41a4ad2014-07-11 14:19:34 +08003296 intel_unmap(dev, sglist[0].dma_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003297}
3298
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003299static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003300 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003301{
3302 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003303 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003304
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003305 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003306 BUG_ON(!sg_page(sg));
David Woodhouse4cf2e752009-02-11 17:23:43 +00003307 sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003308 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003309 }
3310 return nelems;
3311}
3312
David Woodhouse5040a912014-03-09 16:14:00 -07003313static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003314 enum dma_data_direction dir, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003315{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003316 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003317 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003318 size_t size = 0;
3319 int prot = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003320 struct iova *iova = NULL;
3321 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003322 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003323 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003324 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003325
3326 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003327 if (iommu_no_mapping(dev))
3328 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003329
David Woodhouse5040a912014-03-09 16:14:00 -07003330 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003331 if (!domain)
3332 return 0;
3333
Weidong Han8c11e792008-12-08 15:29:22 +08003334 iommu = domain_get_iommu(domain);
3335
David Woodhouseb536d242009-06-28 14:49:31 +01003336 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003337 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003338
David Woodhouse5040a912014-03-09 16:14:00 -07003339 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
3340 *dev->dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003341 if (!iova) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003342 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003343 return 0;
3344 }
3345
3346 /*
3347 * Check if DMAR supports zero-length reads on write only
3348 * mappings..
3349 */
3350 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003351 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003352 prot |= DMA_PTE_READ;
3353 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3354 prot |= DMA_PTE_WRITE;
3355
David Woodhouseb536d242009-06-28 14:49:31 +01003356 start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
David Woodhousee1605492009-06-29 11:17:38 +01003357
Fenghua Yuf5329592009-08-04 15:09:37 -07003358 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003359 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003360 dma_pte_free_pagetable(domain, start_vpfn,
3361 start_vpfn + size - 1);
David Woodhousee1605492009-06-29 11:17:38 +01003362 __free_iova(&domain->iovad, iova);
3363 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003364 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003365
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003366 /* it's a non-present to present mapping. Only flush if caching mode */
3367 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003368 iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003369 else
Weidong Han8c11e792008-12-08 15:29:22 +08003370 iommu_flush_write_buffer(iommu);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003371
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003372 return nelems;
3373}
3374
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003375static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
3376{
3377 return !dma_addr;
3378}
3379
FUJITA Tomonori160c1d82009-01-05 23:59:02 +09003380struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003381 .alloc = intel_alloc_coherent,
3382 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003383 .map_sg = intel_map_sg,
3384 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003385 .map_page = intel_map_page,
3386 .unmap_page = intel_unmap_page,
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003387 .mapping_error = intel_mapping_error,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003388};
3389
3390static inline int iommu_domain_cache_init(void)
3391{
3392 int ret = 0;
3393
3394 iommu_domain_cache = kmem_cache_create("iommu_domain",
3395 sizeof(struct dmar_domain),
3396 0,
3397 SLAB_HWCACHE_ALIGN,
3398
3399 NULL);
3400 if (!iommu_domain_cache) {
3401 printk(KERN_ERR "Couldn't create iommu_domain cache\n");
3402 ret = -ENOMEM;
3403 }
3404
3405 return ret;
3406}
3407
3408static inline int iommu_devinfo_cache_init(void)
3409{
3410 int ret = 0;
3411
3412 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3413 sizeof(struct device_domain_info),
3414 0,
3415 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003416 NULL);
3417 if (!iommu_devinfo_cache) {
3418 printk(KERN_ERR "Couldn't create devinfo cache\n");
3419 ret = -ENOMEM;
3420 }
3421
3422 return ret;
3423}
3424
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003425static int __init iommu_init_mempool(void)
3426{
3427 int ret;
3428 ret = iommu_iova_cache_init();
3429 if (ret)
3430 return ret;
3431
3432 ret = iommu_domain_cache_init();
3433 if (ret)
3434 goto domain_error;
3435
3436 ret = iommu_devinfo_cache_init();
3437 if (!ret)
3438 return ret;
3439
3440 kmem_cache_destroy(iommu_domain_cache);
3441domain_error:
Robin Murphy85b45452015-01-12 17:51:14 +00003442 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003443
3444 return -ENOMEM;
3445}
3446
3447static void __init iommu_exit_mempool(void)
3448{
3449 kmem_cache_destroy(iommu_devinfo_cache);
3450 kmem_cache_destroy(iommu_domain_cache);
Robin Murphy85b45452015-01-12 17:51:14 +00003451 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003452}
3453
Dan Williams556ab452010-07-23 15:47:56 -07003454static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3455{
3456 struct dmar_drhd_unit *drhd;
3457 u32 vtbar;
3458 int rc;
3459
3460 /* We know that this device on this chipset has its own IOMMU.
3461 * If we find it under a different IOMMU, then the BIOS is lying
3462 * to us. Hope that the IOMMU for this device is actually
3463 * disabled, and it needs no translation...
3464 */
3465 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3466 if (rc) {
3467 /* "can't" happen */
3468 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3469 return;
3470 }
3471 vtbar &= 0xffff0000;
3472
3473 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3474 drhd = dmar_find_matched_drhd_unit(pdev);
3475 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3476 TAINT_FIRMWARE_WORKAROUND,
3477 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3478 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3479}
3480DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3481
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003482static void __init init_no_remapping_devices(void)
3483{
3484 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003485 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003486 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003487
3488 for_each_drhd_unit(drhd) {
3489 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003490 for_each_active_dev_scope(drhd->devices,
3491 drhd->devices_cnt, i, dev)
3492 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003493 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003494 if (i == drhd->devices_cnt)
3495 drhd->ignored = 1;
3496 }
3497 }
3498
Jiang Liu7c919772014-01-06 14:18:18 +08003499 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003500 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003501 continue;
3502
Jiang Liub683b232014-02-19 14:07:32 +08003503 for_each_active_dev_scope(drhd->devices,
3504 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003505 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003506 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003507 if (i < drhd->devices_cnt)
3508 continue;
3509
David Woodhousec0771df2011-10-14 20:59:46 +01003510 /* This IOMMU has *only* gfx devices. Either bypass it or
3511 set the gfx_mapped flag, as appropriate */
3512 if (dmar_map_gfx) {
3513 intel_iommu_gfx_mapped = 1;
3514 } else {
3515 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003516 for_each_active_dev_scope(drhd->devices,
3517 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003518 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003519 }
3520 }
3521}
3522
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003523#ifdef CONFIG_SUSPEND
3524static int init_iommu_hw(void)
3525{
3526 struct dmar_drhd_unit *drhd;
3527 struct intel_iommu *iommu = NULL;
3528
3529 for_each_active_iommu(iommu, drhd)
3530 if (iommu->qi)
3531 dmar_reenable_qi(iommu);
3532
Joseph Cihulab7792602011-05-03 00:08:37 -07003533 for_each_iommu(iommu, drhd) {
3534 if (drhd->ignored) {
3535 /*
3536 * we always have to disable PMRs or DMA may fail on
3537 * this device
3538 */
3539 if (force_on)
3540 iommu_disable_protect_mem_regions(iommu);
3541 continue;
3542 }
3543
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003544 iommu_flush_write_buffer(iommu);
3545
3546 iommu_set_root_entry(iommu);
3547
3548 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003549 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003550 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3551 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003552 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003553 }
3554
3555 return 0;
3556}
3557
3558static void iommu_flush_all(void)
3559{
3560 struct dmar_drhd_unit *drhd;
3561 struct intel_iommu *iommu;
3562
3563 for_each_active_iommu(iommu, drhd) {
3564 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003565 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003566 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003567 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003568 }
3569}
3570
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003571static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003572{
3573 struct dmar_drhd_unit *drhd;
3574 struct intel_iommu *iommu = NULL;
3575 unsigned long flag;
3576
3577 for_each_active_iommu(iommu, drhd) {
3578 iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
3579 GFP_ATOMIC);
3580 if (!iommu->iommu_state)
3581 goto nomem;
3582 }
3583
3584 iommu_flush_all();
3585
3586 for_each_active_iommu(iommu, drhd) {
3587 iommu_disable_translation(iommu);
3588
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003589 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003590
3591 iommu->iommu_state[SR_DMAR_FECTL_REG] =
3592 readl(iommu->reg + DMAR_FECTL_REG);
3593 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
3594 readl(iommu->reg + DMAR_FEDATA_REG);
3595 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
3596 readl(iommu->reg + DMAR_FEADDR_REG);
3597 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
3598 readl(iommu->reg + DMAR_FEUADDR_REG);
3599
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003600 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003601 }
3602 return 0;
3603
3604nomem:
3605 for_each_active_iommu(iommu, drhd)
3606 kfree(iommu->iommu_state);
3607
3608 return -ENOMEM;
3609}
3610
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003611static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003612{
3613 struct dmar_drhd_unit *drhd;
3614 struct intel_iommu *iommu = NULL;
3615 unsigned long flag;
3616
3617 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07003618 if (force_on)
3619 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
3620 else
3621 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003622 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003623 }
3624
3625 for_each_active_iommu(iommu, drhd) {
3626
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003627 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003628
3629 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
3630 iommu->reg + DMAR_FECTL_REG);
3631 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
3632 iommu->reg + DMAR_FEDATA_REG);
3633 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
3634 iommu->reg + DMAR_FEADDR_REG);
3635 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
3636 iommu->reg + DMAR_FEUADDR_REG);
3637
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003638 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003639 }
3640
3641 for_each_active_iommu(iommu, drhd)
3642 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003643}
3644
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003645static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003646 .resume = iommu_resume,
3647 .suspend = iommu_suspend,
3648};
3649
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003650static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003651{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003652 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003653}
3654
3655#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02003656static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003657#endif /* CONFIG_PM */
3658
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003659
Jiang Liuc2a0b532014-11-09 22:47:56 +08003660int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003661{
3662 struct acpi_dmar_reserved_memory *rmrr;
3663 struct dmar_rmrr_unit *rmrru;
3664
3665 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
3666 if (!rmrru)
3667 return -ENOMEM;
3668
3669 rmrru->hdr = header;
3670 rmrr = (struct acpi_dmar_reserved_memory *)header;
3671 rmrru->base_address = rmrr->base_address;
3672 rmrru->end_address = rmrr->end_address;
Jiang Liu2e455282014-02-19 14:07:36 +08003673 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
3674 ((void *)rmrr) + rmrr->header.length,
3675 &rmrru->devices_cnt);
3676 if (rmrru->devices_cnt && rmrru->devices == NULL) {
3677 kfree(rmrru);
3678 return -ENOMEM;
3679 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003680
Jiang Liu2e455282014-02-19 14:07:36 +08003681 list_add(&rmrru->list, &dmar_rmrr_units);
3682
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003683 return 0;
3684}
3685
Jiang Liu6b197242014-11-09 22:47:58 +08003686static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
3687{
3688 struct dmar_atsr_unit *atsru;
3689 struct acpi_dmar_atsr *tmp;
3690
3691 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3692 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
3693 if (atsr->segment != tmp->segment)
3694 continue;
3695 if (atsr->header.length != tmp->header.length)
3696 continue;
3697 if (memcmp(atsr, tmp, atsr->header.length) == 0)
3698 return atsru;
3699 }
3700
3701 return NULL;
3702}
3703
3704int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003705{
3706 struct acpi_dmar_atsr *atsr;
3707 struct dmar_atsr_unit *atsru;
3708
Jiang Liu6b197242014-11-09 22:47:58 +08003709 if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
3710 return 0;
3711
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003712 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08003713 atsru = dmar_find_atsr(atsr);
3714 if (atsru)
3715 return 0;
3716
3717 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003718 if (!atsru)
3719 return -ENOMEM;
3720
Jiang Liu6b197242014-11-09 22:47:58 +08003721 /*
3722 * If memory is allocated from slab by ACPI _DSM method, we need to
3723 * copy the memory content because the memory buffer will be freed
3724 * on return.
3725 */
3726 atsru->hdr = (void *)(atsru + 1);
3727 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003728 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08003729 if (!atsru->include_all) {
3730 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
3731 (void *)atsr + atsr->header.length,
3732 &atsru->devices_cnt);
3733 if (atsru->devices_cnt && atsru->devices == NULL) {
3734 kfree(atsru);
3735 return -ENOMEM;
3736 }
3737 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003738
Jiang Liu0e242612014-02-19 14:07:34 +08003739 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003740
3741 return 0;
3742}
3743
Jiang Liu9bdc5312014-01-06 14:18:27 +08003744static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3745{
3746 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
3747 kfree(atsru);
3748}
3749
Jiang Liu6b197242014-11-09 22:47:58 +08003750int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3751{
3752 struct acpi_dmar_atsr *atsr;
3753 struct dmar_atsr_unit *atsru;
3754
3755 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3756 atsru = dmar_find_atsr(atsr);
3757 if (atsru) {
3758 list_del_rcu(&atsru->list);
3759 synchronize_rcu();
3760 intel_iommu_free_atsr(atsru);
3761 }
3762
3763 return 0;
3764}
3765
3766int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3767{
3768 int i;
3769 struct device *dev;
3770 struct acpi_dmar_atsr *atsr;
3771 struct dmar_atsr_unit *atsru;
3772
3773 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3774 atsru = dmar_find_atsr(atsr);
3775 if (!atsru)
3776 return 0;
3777
3778 if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
3779 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
3780 i, dev)
3781 return -EBUSY;
3782
3783 return 0;
3784}
3785
Jiang Liuffebeb42014-11-09 22:48:02 +08003786static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
3787{
3788 int sp, ret = 0;
3789 struct intel_iommu *iommu = dmaru->iommu;
3790
3791 if (g_iommus[iommu->seq_id])
3792 return 0;
3793
3794 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
3795 pr_warn("IOMMU: %s doesn't support hardware pass through.\n",
3796 iommu->name);
3797 return -ENXIO;
3798 }
3799 if (!ecap_sc_support(iommu->ecap) &&
3800 domain_update_iommu_snooping(iommu)) {
3801 pr_warn("IOMMU: %s doesn't support snooping.\n",
3802 iommu->name);
3803 return -ENXIO;
3804 }
3805 sp = domain_update_iommu_superpage(iommu) - 1;
3806 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
3807 pr_warn("IOMMU: %s doesn't support large page.\n",
3808 iommu->name);
3809 return -ENXIO;
3810 }
3811
3812 /*
3813 * Disable translation if already enabled prior to OS handover.
3814 */
3815 if (iommu->gcmd & DMA_GCMD_TE)
3816 iommu_disable_translation(iommu);
3817
3818 g_iommus[iommu->seq_id] = iommu;
3819 ret = iommu_init_domains(iommu);
3820 if (ret == 0)
3821 ret = iommu_alloc_root_entry(iommu);
3822 if (ret)
3823 goto out;
3824
3825 if (dmaru->ignored) {
3826 /*
3827 * we always have to disable PMRs or DMA may fail on this device
3828 */
3829 if (force_on)
3830 iommu_disable_protect_mem_regions(iommu);
3831 return 0;
3832 }
3833
3834 intel_iommu_init_qi(iommu);
3835 iommu_flush_write_buffer(iommu);
3836 ret = dmar_set_interrupt(iommu);
3837 if (ret)
3838 goto disable_iommu;
3839
3840 iommu_set_root_entry(iommu);
3841 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3842 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3843 iommu_enable_translation(iommu);
3844
3845 if (si_domain) {
3846 ret = iommu_attach_domain(si_domain, iommu);
3847 if (ret < 0 || si_domain->id != ret)
3848 goto disable_iommu;
3849 domain_attach_iommu(si_domain, iommu);
3850 }
3851
3852 iommu_disable_protect_mem_regions(iommu);
3853 return 0;
3854
3855disable_iommu:
3856 disable_dmar_iommu(iommu);
3857out:
3858 free_dmar_iommu(iommu);
3859 return ret;
3860}
3861
Jiang Liu6b197242014-11-09 22:47:58 +08003862int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
3863{
Jiang Liuffebeb42014-11-09 22:48:02 +08003864 int ret = 0;
3865 struct intel_iommu *iommu = dmaru->iommu;
3866
3867 if (!intel_iommu_enabled)
3868 return 0;
3869 if (iommu == NULL)
3870 return -EINVAL;
3871
3872 if (insert) {
3873 ret = intel_iommu_add(dmaru);
3874 } else {
3875 disable_dmar_iommu(iommu);
3876 free_dmar_iommu(iommu);
3877 }
3878
3879 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08003880}
3881
Jiang Liu9bdc5312014-01-06 14:18:27 +08003882static void intel_iommu_free_dmars(void)
3883{
3884 struct dmar_rmrr_unit *rmrru, *rmrr_n;
3885 struct dmar_atsr_unit *atsru, *atsr_n;
3886
3887 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
3888 list_del(&rmrru->list);
3889 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
3890 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003891 }
3892
Jiang Liu9bdc5312014-01-06 14:18:27 +08003893 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
3894 list_del(&atsru->list);
3895 intel_iommu_free_atsr(atsru);
3896 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003897}
3898
3899int dmar_find_matched_atsr_unit(struct pci_dev *dev)
3900{
Jiang Liub683b232014-02-19 14:07:32 +08003901 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003902 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00003903 struct pci_dev *bridge = NULL;
3904 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003905 struct acpi_dmar_atsr *atsr;
3906 struct dmar_atsr_unit *atsru;
3907
3908 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003909 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08003910 bridge = bus->self;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003911 if (!bridge || !pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08003912 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003913 return 0;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003914 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003915 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003916 }
Jiang Liub5f82dd2014-02-19 14:07:31 +08003917 if (!bridge)
3918 return 0;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003919
Jiang Liu0e242612014-02-19 14:07:34 +08003920 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08003921 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3922 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3923 if (atsr->segment != pci_domain_nr(dev->bus))
3924 continue;
3925
Jiang Liub683b232014-02-19 14:07:32 +08003926 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00003927 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08003928 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003929
3930 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08003931 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003932 }
Jiang Liub683b232014-02-19 14:07:32 +08003933 ret = 0;
3934out:
Jiang Liu0e242612014-02-19 14:07:34 +08003935 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003936
Jiang Liub683b232014-02-19 14:07:32 +08003937 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003938}
3939
Jiang Liu59ce0512014-02-19 14:07:35 +08003940int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3941{
3942 int ret = 0;
3943 struct dmar_rmrr_unit *rmrru;
3944 struct dmar_atsr_unit *atsru;
3945 struct acpi_dmar_atsr *atsr;
3946 struct acpi_dmar_reserved_memory *rmrr;
3947
3948 if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
3949 return 0;
3950
3951 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
3952 rmrr = container_of(rmrru->hdr,
3953 struct acpi_dmar_reserved_memory, header);
3954 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3955 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
3956 ((void *)rmrr) + rmrr->header.length,
3957 rmrr->segment, rmrru->devices,
3958 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08003959 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08003960 return ret;
3961 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08003962 dmar_remove_dev_scope(info, rmrr->segment,
3963 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08003964 }
3965 }
3966
3967 list_for_each_entry(atsru, &dmar_atsr_units, list) {
3968 if (atsru->include_all)
3969 continue;
3970
3971 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3972 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3973 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
3974 (void *)atsr + atsr->header.length,
3975 atsr->segment, atsru->devices,
3976 atsru->devices_cnt);
3977 if (ret > 0)
3978 break;
3979 else if(ret < 0)
3980 return ret;
3981 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
3982 if (dmar_remove_dev_scope(info, atsr->segment,
3983 atsru->devices, atsru->devices_cnt))
3984 break;
3985 }
3986 }
3987
3988 return 0;
3989}
3990
Fenghua Yu99dcade2009-11-11 07:23:06 -08003991/*
3992 * Here we only respond to action of unbound device from driver.
3993 *
3994 * Added device is not attached to its DMAR domain here yet. That will happen
3995 * when mapping the device to iova.
3996 */
3997static int device_notifier(struct notifier_block *nb,
3998 unsigned long action, void *data)
3999{
4000 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004001 struct dmar_domain *domain;
4002
David Woodhouse3d891942014-03-06 15:59:26 +00004003 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004004 return 0;
4005
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004006 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004007 return 0;
4008
David Woodhouse1525a292014-03-06 16:19:30 +00004009 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004010 if (!domain)
4011 return 0;
4012
Jiang Liu3a5670e2014-02-19 14:07:33 +08004013 down_read(&dmar_global_lock);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004014 domain_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004015 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004016 domain_exit(domain);
Jiang Liu3a5670e2014-02-19 14:07:33 +08004017 up_read(&dmar_global_lock);
Alex Williamsona97590e2011-03-04 14:52:16 -07004018
Fenghua Yu99dcade2009-11-11 07:23:06 -08004019 return 0;
4020}
4021
4022static struct notifier_block device_nb = {
4023 .notifier_call = device_notifier,
4024};
4025
Jiang Liu75f05562014-02-19 14:07:37 +08004026static int intel_iommu_memory_notifier(struct notifier_block *nb,
4027 unsigned long val, void *v)
4028{
4029 struct memory_notify *mhp = v;
4030 unsigned long long start, end;
4031 unsigned long start_vpfn, last_vpfn;
4032
4033 switch (val) {
4034 case MEM_GOING_ONLINE:
4035 start = mhp->start_pfn << PAGE_SHIFT;
4036 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4037 if (iommu_domain_identity_map(si_domain, start, end)) {
4038 pr_warn("dmar: failed to build identity map for [%llx-%llx]\n",
4039 start, end);
4040 return NOTIFY_BAD;
4041 }
4042 break;
4043
4044 case MEM_OFFLINE:
4045 case MEM_CANCEL_ONLINE:
4046 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4047 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4048 while (start_vpfn <= last_vpfn) {
4049 struct iova *iova;
4050 struct dmar_drhd_unit *drhd;
4051 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004052 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004053
4054 iova = find_iova(&si_domain->iovad, start_vpfn);
4055 if (iova == NULL) {
4056 pr_debug("dmar: failed get IOVA for PFN %lx\n",
4057 start_vpfn);
4058 break;
4059 }
4060
4061 iova = split_and_remove_iova(&si_domain->iovad, iova,
4062 start_vpfn, last_vpfn);
4063 if (iova == NULL) {
4064 pr_warn("dmar: failed to split IOVA PFN [%lx-%lx]\n",
4065 start_vpfn, last_vpfn);
4066 return NOTIFY_BAD;
4067 }
4068
David Woodhouseea8ea462014-03-05 17:09:32 +00004069 freelist = domain_unmap(si_domain, iova->pfn_lo,
4070 iova->pfn_hi);
4071
Jiang Liu75f05562014-02-19 14:07:37 +08004072 rcu_read_lock();
4073 for_each_active_iommu(iommu, drhd)
4074 iommu_flush_iotlb_psi(iommu, si_domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08004075 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004076 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004077 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004078 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004079
4080 start_vpfn = iova->pfn_hi + 1;
4081 free_iova_mem(iova);
4082 }
4083 break;
4084 }
4085
4086 return NOTIFY_OK;
4087}
4088
4089static struct notifier_block intel_iommu_memory_nb = {
4090 .notifier_call = intel_iommu_memory_notifier,
4091 .priority = 0
4092};
4093
Alex Williamsona5459cf2014-06-12 16:12:31 -06004094
4095static ssize_t intel_iommu_show_version(struct device *dev,
4096 struct device_attribute *attr,
4097 char *buf)
4098{
4099 struct intel_iommu *iommu = dev_get_drvdata(dev);
4100 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4101 return sprintf(buf, "%d:%d\n",
4102 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4103}
4104static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4105
4106static ssize_t intel_iommu_show_address(struct device *dev,
4107 struct device_attribute *attr,
4108 char *buf)
4109{
4110 struct intel_iommu *iommu = dev_get_drvdata(dev);
4111 return sprintf(buf, "%llx\n", iommu->reg_phys);
4112}
4113static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4114
4115static ssize_t intel_iommu_show_cap(struct device *dev,
4116 struct device_attribute *attr,
4117 char *buf)
4118{
4119 struct intel_iommu *iommu = dev_get_drvdata(dev);
4120 return sprintf(buf, "%llx\n", iommu->cap);
4121}
4122static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4123
4124static ssize_t intel_iommu_show_ecap(struct device *dev,
4125 struct device_attribute *attr,
4126 char *buf)
4127{
4128 struct intel_iommu *iommu = dev_get_drvdata(dev);
4129 return sprintf(buf, "%llx\n", iommu->ecap);
4130}
4131static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4132
4133static struct attribute *intel_iommu_attrs[] = {
4134 &dev_attr_version.attr,
4135 &dev_attr_address.attr,
4136 &dev_attr_cap.attr,
4137 &dev_attr_ecap.attr,
4138 NULL,
4139};
4140
4141static struct attribute_group intel_iommu_group = {
4142 .name = "intel-iommu",
4143 .attrs = intel_iommu_attrs,
4144};
4145
4146const struct attribute_group *intel_iommu_groups[] = {
4147 &intel_iommu_group,
4148 NULL,
4149};
4150
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004151int __init intel_iommu_init(void)
4152{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004153 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004154 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004155 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004156
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004157 /* VT-d is required for a TXT/tboot launch, so enforce that */
4158 force_on = tboot_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004159
Jiang Liu3a5670e2014-02-19 14:07:33 +08004160 if (iommu_init_mempool()) {
4161 if (force_on)
4162 panic("tboot: Failed to initialize iommu memory\n");
4163 return -ENOMEM;
4164 }
4165
4166 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004167 if (dmar_table_init()) {
4168 if (force_on)
4169 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004170 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004171 }
4172
Takao Indoh3a93c842013-04-23 17:35:03 +09004173 /*
4174 * Disable translation if already enabled prior to OS handover.
4175 */
Jiang Liu7c919772014-01-06 14:18:18 +08004176 for_each_active_iommu(iommu, drhd)
Takao Indoh3a93c842013-04-23 17:35:03 +09004177 if (iommu->gcmd & DMA_GCMD_TE)
4178 iommu_disable_translation(iommu);
Takao Indoh3a93c842013-04-23 17:35:03 +09004179
Suresh Siddhac2c72862011-08-23 17:05:19 -07004180 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004181 if (force_on)
4182 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004183 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004184 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004185
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004186 if (no_iommu || dmar_disabled)
Jiang Liu9bdc5312014-01-06 14:18:27 +08004187 goto out_free_dmar;
Suresh Siddha2ae21012008-07-10 11:16:43 -07004188
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004189 if (list_empty(&dmar_rmrr_units))
4190 printk(KERN_INFO "DMAR: No RMRR found\n");
4191
4192 if (list_empty(&dmar_atsr_units))
4193 printk(KERN_INFO "DMAR: No ATSR found\n");
4194
Joseph Cihula51a63e62011-03-21 11:04:24 -07004195 if (dmar_init_reserved_ranges()) {
4196 if (force_on)
4197 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004198 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004199 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004200
4201 init_no_remapping_devices();
4202
Joseph Cihulab7792602011-05-03 00:08:37 -07004203 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004204 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004205 if (force_on)
4206 panic("tboot: Failed to initialize DMARs\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004207 printk(KERN_ERR "IOMMU: dmar init failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004208 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004209 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004210 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004211 printk(KERN_INFO
4212 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
4213
mark gross5e0d2a62008-03-04 15:22:08 -08004214 init_timer(&unmap_timer);
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004215#ifdef CONFIG_SWIOTLB
4216 swiotlb = 0;
4217#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004218 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004219
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004220 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004221
Alex Williamsona5459cf2014-06-12 16:12:31 -06004222 for_each_active_iommu(iommu, drhd)
4223 iommu->iommu_dev = iommu_device_create(NULL, iommu,
4224 intel_iommu_groups,
4225 iommu->name);
4226
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004227 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004228 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004229 if (si_domain && !hw_pass_through)
4230 register_memory_notifier(&intel_iommu_memory_nb);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004231
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004232 intel_iommu_enabled = 1;
4233
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004234 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004235
4236out_free_reserved_range:
4237 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004238out_free_dmar:
4239 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004240 up_write(&dmar_global_lock);
4241 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004242 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004243}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004244
Alex Williamson579305f2014-07-03 09:51:43 -06004245static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
4246{
4247 struct intel_iommu *iommu = opaque;
4248
4249 iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4250 return 0;
4251}
4252
4253/*
4254 * NB - intel-iommu lacks any sort of reference counting for the users of
4255 * dependent devices. If multiple endpoints have intersecting dependent
4256 * devices, unbinding the driver from any one of them will possibly leave
4257 * the others unable to operate.
4258 */
Han, Weidong3199aa62009-02-26 17:31:12 +08004259static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004260 struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004261{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004262 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004263 return;
4264
Alex Williamson579305f2014-07-03 09:51:43 -06004265 pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004266}
4267
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004268static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004269 struct device *dev)
Weidong Hanc7151a82008-12-08 22:51:37 +08004270{
Yijing Wangbca2b912013-10-31 17:26:04 +08004271 struct device_domain_info *info, *tmp;
Weidong Hanc7151a82008-12-08 22:51:37 +08004272 struct intel_iommu *iommu;
4273 unsigned long flags;
Quentin Lambert2f119c72015-02-06 10:59:53 +01004274 bool found = false;
David Woodhouse156baca2014-03-09 14:00:57 -07004275 u8 bus, devfn;
Weidong Hanc7151a82008-12-08 22:51:37 +08004276
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004277 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanc7151a82008-12-08 22:51:37 +08004278 if (!iommu)
4279 return;
4280
4281 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wangbca2b912013-10-31 17:26:04 +08004282 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004283 if (info->iommu == iommu && info->bus == bus &&
4284 info->devfn == devfn) {
David Woodhouse109b9b02012-05-25 17:43:02 +01004285 unlink_domain_info(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004286 spin_unlock_irqrestore(&device_domain_lock, flags);
4287
Yu Zhao93a23a72009-05-18 13:51:37 +08004288 iommu_disable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004289 iommu_detach_dev(iommu, info->bus, info->devfn);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004290 iommu_detach_dependent_devices(iommu, dev);
Weidong Hanc7151a82008-12-08 22:51:37 +08004291 free_devinfo_mem(info);
4292
4293 spin_lock_irqsave(&device_domain_lock, flags);
4294
4295 if (found)
4296 break;
4297 else
4298 continue;
4299 }
4300
4301 /* if there is no other devices under the same iommu
4302 * owned by this domain, clear this iommu in iommu_bmp
4303 * update iommu count and coherency
4304 */
David Woodhouse8bbc4412014-03-09 13:52:37 -07004305 if (info->iommu == iommu)
Quentin Lambert2f119c72015-02-06 10:59:53 +01004306 found = true;
Weidong Hanc7151a82008-12-08 22:51:37 +08004307 }
4308
Roland Dreier3e7abe22011-07-20 06:22:21 -07004309 spin_unlock_irqrestore(&device_domain_lock, flags);
4310
Weidong Hanc7151a82008-12-08 22:51:37 +08004311 if (found == 0) {
Jiang Liufb170fb2014-07-11 14:19:28 +08004312 domain_detach_iommu(domain, iommu);
4313 if (!domain_type_is_vm_or_si(domain))
4314 iommu_detach_domain(domain, iommu);
Weidong Hanc7151a82008-12-08 22:51:37 +08004315 }
Weidong Hanc7151a82008-12-08 22:51:37 +08004316}
4317
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004318static int md_domain_init(struct dmar_domain *domain, int guest_width)
Weidong Han5e98c4b2008-12-08 23:03:27 +08004319{
4320 int adjust_width;
4321
Robin Murphy0fb5fe82015-01-12 17:51:16 +00004322 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
4323 DMA_32BIT_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004324 domain_reserve_special_ranges(domain);
4325
4326 /* calculate AGAW */
4327 domain->gaw = guest_width;
4328 adjust_width = guestwidth_to_adjustwidth(guest_width);
4329 domain->agaw = width_to_agaw(adjust_width);
4330
Weidong Han5e98c4b2008-12-08 23:03:27 +08004331 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004332 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004333 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004334 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004335
4336 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004337 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004338 if (!domain->pgd)
4339 return -ENOMEM;
4340 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4341 return 0;
4342}
4343
Joerg Roedel5d450802008-12-03 14:52:32 +01004344static int intel_iommu_domain_init(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004345{
Joerg Roedel5d450802008-12-03 14:52:32 +01004346 struct dmar_domain *dmar_domain;
Kay, Allen M38717942008-09-09 18:37:29 +03004347
Jiang Liuab8dfe22014-07-11 14:19:27 +08004348 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01004349 if (!dmar_domain) {
Kay, Allen M38717942008-09-09 18:37:29 +03004350 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004351 "intel_iommu_domain_init: dmar_domain == NULL\n");
4352 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004353 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004354 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Kay, Allen M38717942008-09-09 18:37:29 +03004355 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004356 "intel_iommu_domain_init() failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08004357 domain_exit(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004358 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004359 }
Allen Kay8140a952011-10-14 12:32:17 -07004360 domain_update_iommu_cap(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004361 domain->priv = dmar_domain;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004362
Joerg Roedel8a0e7152012-01-26 19:40:54 +01004363 domain->geometry.aperture_start = 0;
4364 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4365 domain->geometry.force_aperture = true;
4366
Joerg Roedel5d450802008-12-03 14:52:32 +01004367 return 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004368}
Kay, Allen M38717942008-09-09 18:37:29 +03004369
Joerg Roedel5d450802008-12-03 14:52:32 +01004370static void intel_iommu_domain_destroy(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004371{
Joerg Roedel5d450802008-12-03 14:52:32 +01004372 struct dmar_domain *dmar_domain = domain->priv;
4373
4374 domain->priv = NULL;
Jiang Liu92d03cc2014-02-19 14:07:28 +08004375 domain_exit(dmar_domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004376}
Kay, Allen M38717942008-09-09 18:37:29 +03004377
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004378static int intel_iommu_attach_device(struct iommu_domain *domain,
4379 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004380{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004381 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004382 struct intel_iommu *iommu;
4383 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07004384 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03004385
Alex Williamsonc875d2c2014-07-03 09:57:02 -06004386 if (device_is_rmrr_locked(dev)) {
4387 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
4388 return -EPERM;
4389 }
4390
David Woodhouse7207d8f2014-03-09 16:31:06 -07004391 /* normally dev is not mapped */
4392 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004393 struct dmar_domain *old_domain;
4394
David Woodhouse1525a292014-03-06 16:19:30 +00004395 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004396 if (old_domain) {
Jiang Liuab8dfe22014-07-11 14:19:27 +08004397 if (domain_type_is_vm_or_si(dmar_domain))
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004398 domain_remove_one_dev_info(old_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004399 else
4400 domain_remove_dev_info(old_domain);
Joerg Roedel62c22162014-12-09 12:56:45 +01004401
4402 if (!domain_type_is_vm_or_si(old_domain) &&
4403 list_empty(&old_domain->devices))
4404 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004405 }
4406 }
4407
David Woodhouse156baca2014-03-09 14:00:57 -07004408 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004409 if (!iommu)
4410 return -ENODEV;
4411
4412 /* check if this iommu agaw is sufficient for max mapped address */
4413 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01004414 if (addr_width > cap_mgaw(iommu->cap))
4415 addr_width = cap_mgaw(iommu->cap);
4416
4417 if (dmar_domain->max_addr > (1LL << addr_width)) {
4418 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004419 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01004420 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004421 return -EFAULT;
4422 }
Tom Lyona99c47a2010-05-17 08:20:45 +01004423 dmar_domain->gaw = addr_width;
4424
4425 /*
4426 * Knock out extra levels of page tables if necessary
4427 */
4428 while (iommu->agaw < dmar_domain->agaw) {
4429 struct dma_pte *pte;
4430
4431 pte = dmar_domain->pgd;
4432 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08004433 dmar_domain->pgd = (struct dma_pte *)
4434 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01004435 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01004436 }
4437 dmar_domain->agaw--;
4438 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004439
David Woodhouse5913c9b2014-03-09 16:27:31 -07004440 return domain_add_dev_info(dmar_domain, dev, CONTEXT_TT_MULTI_LEVEL);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004441}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004442
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004443static void intel_iommu_detach_device(struct iommu_domain *domain,
4444 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004445{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004446 struct dmar_domain *dmar_domain = domain->priv;
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004447
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004448 domain_remove_one_dev_info(dmar_domain, dev);
Kay, Allen M38717942008-09-09 18:37:29 +03004449}
Kay, Allen M38717942008-09-09 18:37:29 +03004450
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004451static int intel_iommu_map(struct iommu_domain *domain,
4452 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004453 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03004454{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004455 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004456 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004457 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004458 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004459
Joerg Roedeldde57a22008-12-03 15:04:09 +01004460 if (iommu_prot & IOMMU_READ)
4461 prot |= DMA_PTE_READ;
4462 if (iommu_prot & IOMMU_WRITE)
4463 prot |= DMA_PTE_WRITE;
Sheng Yang9cf066972009-03-18 15:33:07 +08004464 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
4465 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004466
David Woodhouse163cc522009-06-28 00:51:17 +01004467 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004468 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004469 u64 end;
4470
4471 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01004472 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004473 if (end < max_addr) {
Tom Lyon8954da12010-05-17 08:19:52 +01004474 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004475 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01004476 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004477 return -EFAULT;
4478 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01004479 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004480 }
David Woodhousead051222009-06-28 14:22:28 +01004481 /* Round up size to next multiple of PAGE_SIZE, if it and
4482 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01004483 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01004484 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
4485 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004486 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03004487}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004488
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004489static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00004490 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004491{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004492 struct dmar_domain *dmar_domain = domain->priv;
David Woodhouseea8ea462014-03-05 17:09:32 +00004493 struct page *freelist = NULL;
4494 struct intel_iommu *iommu;
4495 unsigned long start_pfn, last_pfn;
4496 unsigned int npages;
4497 int iommu_id, num, ndomains, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01004498
David Woodhouse5cf0a762014-03-19 16:07:49 +00004499 /* Cope with horrid API which requires us to unmap more than the
4500 size argument if it happens to be a large-page mapping. */
4501 if (!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level))
4502 BUG();
4503
4504 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
4505 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
4506
David Woodhouseea8ea462014-03-05 17:09:32 +00004507 start_pfn = iova >> VTD_PAGE_SHIFT;
4508 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
4509
4510 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
4511
4512 npages = last_pfn - start_pfn + 1;
4513
4514 for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) {
4515 iommu = g_iommus[iommu_id];
4516
4517 /*
4518 * find bit position of dmar_domain
4519 */
4520 ndomains = cap_ndoms(iommu->cap);
4521 for_each_set_bit(num, iommu->domain_ids, ndomains) {
4522 if (iommu->domains[num] == dmar_domain)
4523 iommu_flush_iotlb_psi(iommu, num, start_pfn,
4524 npages, !freelist, 0);
4525 }
4526
4527 }
4528
4529 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004530
David Woodhouse163cc522009-06-28 00:51:17 +01004531 if (dmar_domain->max_addr == iova + size)
4532 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004533
David Woodhouse5cf0a762014-03-19 16:07:49 +00004534 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004535}
Kay, Allen M38717942008-09-09 18:37:29 +03004536
Joerg Roedeld14d6572008-12-03 15:06:57 +01004537static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547ac2013-03-29 01:23:58 +05304538 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03004539{
Joerg Roedeld14d6572008-12-03 15:06:57 +01004540 struct dmar_domain *dmar_domain = domain->priv;
Kay, Allen M38717942008-09-09 18:37:29 +03004541 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00004542 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004543 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004544
David Woodhouse5cf0a762014-03-19 16:07:49 +00004545 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03004546 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004547 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03004548
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004549 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03004550}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004551
Joerg Roedel5d587b82014-09-05 10:50:45 +02004552static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004553{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004554 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004555 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04004556 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004557 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004558
Joerg Roedel5d587b82014-09-05 10:50:45 +02004559 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004560}
4561
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004562static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004563{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004564 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004565 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07004566 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04004567
Alex Williamsona5459cf2014-06-12 16:12:31 -06004568 iommu = device_to_iommu(dev, &bus, &devfn);
4569 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004570 return -ENODEV;
4571
Alex Williamsona5459cf2014-06-12 16:12:31 -06004572 iommu_device_link(iommu->iommu_dev, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004573
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004574 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06004575
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004576 if (IS_ERR(group))
4577 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004578
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004579 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004580 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004581}
4582
4583static void intel_iommu_remove_device(struct device *dev)
4584{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004585 struct intel_iommu *iommu;
4586 u8 bus, devfn;
4587
4588 iommu = device_to_iommu(dev, &bus, &devfn);
4589 if (!iommu)
4590 return;
4591
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004592 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004593
4594 iommu_device_unlink(iommu->iommu_dev, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004595}
4596
Thierry Redingb22f6432014-06-27 09:03:12 +02004597static const struct iommu_ops intel_iommu_ops = {
Joerg Roedel5d587b82014-09-05 10:50:45 +02004598 .capable = intel_iommu_capable,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004599 .domain_init = intel_iommu_domain_init,
4600 .domain_destroy = intel_iommu_domain_destroy,
4601 .attach_dev = intel_iommu_attach_device,
4602 .detach_dev = intel_iommu_detach_device,
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004603 .map = intel_iommu_map,
4604 .unmap = intel_iommu_unmap,
Olav Haugan315786e2014-10-25 09:55:16 -07004605 .map_sg = default_iommu_map_sg,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004606 .iova_to_phys = intel_iommu_iova_to_phys,
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004607 .add_device = intel_iommu_add_device,
4608 .remove_device = intel_iommu_remove_device,
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +02004609 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004610};
David Woodhouse9af88142009-02-13 23:18:03 +00004611
Daniel Vetter94526182013-01-20 23:50:13 +01004612static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
4613{
4614 /* G4x/GM45 integrated gfx dmar support is totally busted. */
4615 printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
4616 dmar_map_gfx = 0;
4617}
4618
4619DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
4620DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
4621DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
4622DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
4623DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
4624DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
4625DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
4626
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004627static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00004628{
4629 /*
4630 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01004631 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00004632 */
4633 printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
4634 rwbf_quirk = 1;
4635}
4636
4637DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01004638DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
4639DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
4640DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
4641DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
4642DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
4643DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07004644
Adam Jacksoneecfd572010-08-25 21:17:34 +01004645#define GGC 0x52
4646#define GGC_MEMORY_SIZE_MASK (0xf << 8)
4647#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
4648#define GGC_MEMORY_SIZE_1M (0x1 << 8)
4649#define GGC_MEMORY_SIZE_2M (0x3 << 8)
4650#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
4651#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
4652#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
4653#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
4654
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004655static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01004656{
4657 unsigned short ggc;
4658
Adam Jacksoneecfd572010-08-25 21:17:34 +01004659 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01004660 return;
4661
Adam Jacksoneecfd572010-08-25 21:17:34 +01004662 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
David Woodhouse9eecabc2010-09-21 22:28:23 +01004663 printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
4664 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004665 } else if (dmar_map_gfx) {
4666 /* we have to ensure the gfx device is idle before we flush */
4667 printk(KERN_INFO "DMAR: Disabling batched IOTLB flush on Ironlake\n");
4668 intel_iommu_strict = 1;
4669 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01004670}
4671DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4672DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
4673DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
4674DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
4675
David Woodhousee0fc7e02009-09-30 09:12:17 -07004676/* On Tylersburg chipsets, some BIOSes have been known to enable the
4677 ISOCH DMAR unit for the Azalia sound device, but not give it any
4678 TLB entries, which causes it to deadlock. Check for that. We do
4679 this in a function called from init_dmars(), instead of in a PCI
4680 quirk, because we don't want to print the obnoxious "BIOS broken"
4681 message if VT-d is actually disabled.
4682*/
4683static void __init check_tylersburg_isoch(void)
4684{
4685 struct pci_dev *pdev;
4686 uint32_t vtisochctrl;
4687
4688 /* If there's no Azalia in the system anyway, forget it. */
4689 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
4690 if (!pdev)
4691 return;
4692 pci_dev_put(pdev);
4693
4694 /* System Management Registers. Might be hidden, in which case
4695 we can't do the sanity check. But that's OK, because the
4696 known-broken BIOSes _don't_ actually hide it, so far. */
4697 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
4698 if (!pdev)
4699 return;
4700
4701 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
4702 pci_dev_put(pdev);
4703 return;
4704 }
4705
4706 pci_dev_put(pdev);
4707
4708 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
4709 if (vtisochctrl & 1)
4710 return;
4711
4712 /* Drop all bits other than the number of TLB entries */
4713 vtisochctrl &= 0x1c;
4714
4715 /* If we have the recommended number of TLB entries (16), fine. */
4716 if (vtisochctrl == 0x10)
4717 return;
4718
4719 /* Zero TLB entries? You get to ride the short bus to school. */
4720 if (!vtisochctrl) {
4721 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
4722 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4723 dmi_get_system_info(DMI_BIOS_VENDOR),
4724 dmi_get_system_info(DMI_BIOS_VERSION),
4725 dmi_get_system_info(DMI_PRODUCT_VERSION));
4726 iommu_identity_mapping |= IDENTMAP_AZALIA;
4727 return;
4728 }
4729
4730 printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
4731 vtisochctrl);
4732}