blob: 0852b7021e4aa514c29c898e404307e3398aff1d [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
Mark McLoughlinf27be032008-11-20 15:49:43 +000074#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
Yang Hongyang284901a2009-04-06 19:01:15 -070075#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
Yang Hongyang6a355282009-04-06 19:01:13 -070076#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
mark gross5e0d2a62008-03-04 15:22:08 -080077
Andrew Mortondf08cdc2010-09-22 13:05:11 -070078/* page table handling */
79#define LEVEL_STRIDE (9)
80#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
81
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020082/*
83 * This bitmap is used to advertise the page sizes our hardware support
84 * to the IOMMU core, which will then use this information to split
85 * physically contiguous memory regions it is mapping into page sizes
86 * that we support.
87 *
88 * Traditionally the IOMMU core just handed us the mappings directly,
89 * after making sure the size is an order of a 4KiB page and that the
90 * mapping has natural alignment.
91 *
92 * To retain this behavior, we currently advertise that we support
93 * all page sizes that are an order of 4KiB.
94 *
95 * If at some point we'd like to utilize the IOMMU core's new behavior,
96 * we could change this to advertise the real page sizes we support.
97 */
98#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
99
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700100static inline int agaw_to_level(int agaw)
101{
102 return agaw + 2;
103}
104
105static inline int agaw_to_width(int agaw)
106{
Jiang Liu5c645b32014-01-06 14:18:12 +0800107 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700108}
109
110static inline int width_to_agaw(int width)
111{
Jiang Liu5c645b32014-01-06 14:18:12 +0800112 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700113}
114
115static inline unsigned int level_to_offset_bits(int level)
116{
117 return (level - 1) * LEVEL_STRIDE;
118}
119
120static inline int pfn_level_offset(unsigned long pfn, int level)
121{
122 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
123}
124
125static inline unsigned long level_mask(int level)
126{
127 return -1UL << level_to_offset_bits(level);
128}
129
130static inline unsigned long level_size(int level)
131{
132 return 1UL << level_to_offset_bits(level);
133}
134
135static inline unsigned long align_to_level(unsigned long pfn, int level)
136{
137 return (pfn + level_size(level) - 1) & level_mask(level);
138}
David Woodhousefd18de52009-05-10 23:57:41 +0100139
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100140static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
141{
Jiang Liu5c645b32014-01-06 14:18:12 +0800142 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100143}
144
David Woodhousedd4e8312009-06-27 16:21:20 +0100145/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
146 are never going to work. */
147static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
148{
149 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
150}
151
152static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
153{
154 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
155}
156static inline unsigned long page_to_dma_pfn(struct page *pg)
157{
158 return mm_to_dma_pfn(page_to_pfn(pg));
159}
160static inline unsigned long virt_to_dma_pfn(void *p)
161{
162 return page_to_dma_pfn(virt_to_page(p));
163}
164
Weidong Hand9630fe2008-12-08 11:06:32 +0800165/* global iommu list, set NULL for ignored DMAR units */
166static struct intel_iommu **g_iommus;
167
David Woodhousee0fc7e02009-09-30 09:12:17 -0700168static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000169static int rwbf_quirk;
170
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000171/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700172 * set to 1 to panic kernel if can't successfully enable VT-d
173 * (used when kernel is launched w/ TXT)
174 */
175static int force_on = 0;
176
177/*
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000178 * 0: Present
179 * 1-11: Reserved
180 * 12-63: Context Ptr (12 - (haw-1))
181 * 64-127: Reserved
182 */
183struct root_entry {
184 u64 val;
185 u64 rsvd1;
186};
187#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
188static inline bool root_present(struct root_entry *root)
189{
190 return (root->val & 1);
191}
192static inline void set_root_present(struct root_entry *root)
193{
194 root->val |= 1;
195}
196static inline void set_root_value(struct root_entry *root, unsigned long value)
197{
198 root->val |= value & VTD_PAGE_MASK;
199}
200
201static inline struct context_entry *
202get_context_addr_from_root(struct root_entry *root)
203{
204 return (struct context_entry *)
205 (root_present(root)?phys_to_virt(
206 root->val & VTD_PAGE_MASK) :
207 NULL);
208}
209
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000210/*
211 * low 64 bits:
212 * 0: present
213 * 1: fault processing disable
214 * 2-3: translation type
215 * 12-63: address space root
216 * high 64 bits:
217 * 0-2: address width
218 * 3-6: aval
219 * 8-23: domain id
220 */
221struct context_entry {
222 u64 lo;
223 u64 hi;
224};
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000225
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000226static inline bool context_present(struct context_entry *context)
227{
228 return (context->lo & 1);
229}
230static inline void context_set_present(struct context_entry *context)
231{
232 context->lo |= 1;
233}
234
235static inline void context_set_fault_enable(struct context_entry *context)
236{
237 context->lo &= (((u64)-1) << 2) | 1;
238}
239
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000240static inline void context_set_translation_type(struct context_entry *context,
241 unsigned long value)
242{
243 context->lo &= (((u64)-1) << 4) | 3;
244 context->lo |= (value & 3) << 2;
245}
246
247static inline void context_set_address_root(struct context_entry *context,
248 unsigned long value)
249{
250 context->lo |= value & VTD_PAGE_MASK;
251}
252
253static inline void context_set_address_width(struct context_entry *context,
254 unsigned long value)
255{
256 context->hi |= value & 7;
257}
258
259static inline void context_set_domain_id(struct context_entry *context,
260 unsigned long value)
261{
262 context->hi |= (value & ((1 << 16) - 1)) << 8;
263}
264
265static inline void context_clear_entry(struct context_entry *context)
266{
267 context->lo = 0;
268 context->hi = 0;
269}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000270
Mark McLoughlin622ba122008-11-20 15:49:46 +0000271/*
272 * 0: readable
273 * 1: writable
274 * 2-6: reserved
275 * 7: super page
Sheng Yang9cf066972009-03-18 15:33:07 +0800276 * 8-10: available
277 * 11: snoop behavior
Mark McLoughlin622ba122008-11-20 15:49:46 +0000278 * 12-63: Host physcial address
279 */
280struct dma_pte {
281 u64 val;
282};
Mark McLoughlin622ba122008-11-20 15:49:46 +0000283
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000284static inline void dma_clear_pte(struct dma_pte *pte)
285{
286 pte->val = 0;
287}
288
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000289static inline u64 dma_pte_addr(struct dma_pte *pte)
290{
David Woodhousec85994e2009-07-01 19:21:24 +0100291#ifdef CONFIG_64BIT
292 return pte->val & VTD_PAGE_MASK;
293#else
294 /* Must have a full atomic 64-bit read */
David Woodhouse1a8bd482010-08-10 01:38:53 +0100295 return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
David Woodhousec85994e2009-07-01 19:21:24 +0100296#endif
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000297}
298
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000299static inline bool dma_pte_present(struct dma_pte *pte)
300{
301 return (pte->val & 3) != 0;
302}
Mark McLoughlin622ba122008-11-20 15:49:46 +0000303
Allen Kay4399c8b2011-10-14 12:32:46 -0700304static inline bool dma_pte_superpage(struct dma_pte *pte)
305{
Joerg Roedelc3c75eb2014-07-04 11:19:10 +0200306 return (pte->val & DMA_PTE_LARGE_PAGE);
Allen Kay4399c8b2011-10-14 12:32:46 -0700307}
308
David Woodhouse75e6bf92009-07-02 11:21:16 +0100309static inline int first_pte_in_page(struct dma_pte *pte)
310{
311 return !((unsigned long)pte & ~VTD_PAGE_MASK);
312}
313
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700314/*
315 * This domain is a statically identity mapping domain.
316 * 1. This domain creats a static 1:1 mapping to all usable memory.
317 * 2. It maps to each iommu if successful.
318 * 3. Each iommu mapps to this domain if successful.
319 */
David Woodhouse19943b02009-08-04 16:19:20 +0100320static struct dmar_domain *si_domain;
321static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700322
Weidong Han1ce28fe2008-12-08 16:35:39 +0800323/* domain represents a virtual machine, more than one devices
324 * across iommus may be owned in one domain, e.g. kvm guest.
325 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800326#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800327
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700328/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800329#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700330
Mike Travis1b198bb2012-03-05 15:05:16 -0800331/* define the limit of IOMMUs supported in each domain */
332#ifdef CONFIG_X86
333# define IOMMU_UNITS_SUPPORTED MAX_IO_APICS
334#else
335# define IOMMU_UNITS_SUPPORTED 64
336#endif
337
Mark McLoughlin99126f72008-11-20 15:49:47 +0000338struct dmar_domain {
339 int id; /* domain id */
Suresh Siddha4c923d42009-10-02 11:01:24 -0700340 int nid; /* node id */
Mike Travis1b198bb2012-03-05 15:05:16 -0800341 DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED);
342 /* bitmap of iommus this domain uses*/
Mark McLoughlin99126f72008-11-20 15:49:47 +0000343
344 struct list_head devices; /* all devices' list */
345 struct iova_domain iovad; /* iova's that belong to this domain */
346
347 struct dma_pte *pgd; /* virtual address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000348 int gaw; /* max guest address width */
349
350 /* adjusted guest address width, 0 is level 2 30-bit */
351 int agaw;
352
Weidong Han3b5410e2008-12-08 09:17:15 +0800353 int flags; /* flags to find out type of domain */
Weidong Han8e6040972008-12-08 15:49:06 +0800354
355 int iommu_coherency;/* indicate coherency of iommu access */
Sheng Yang58c610b2009-03-18 15:33:05 +0800356 int iommu_snooping; /* indicate snooping control feature*/
Weidong Hanc7151a82008-12-08 22:51:37 +0800357 int iommu_count; /* reference count of iommu */
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100358 int iommu_superpage;/* Level of superpages supported:
359 0 == 4KiB (no superpages), 1 == 2MiB,
360 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
Weidong Hanc7151a82008-12-08 22:51:37 +0800361 spinlock_t iommu_lock; /* protect iommu set in domain */
Weidong Hanfe40f1e2008-12-08 23:10:23 +0800362 u64 max_addr; /* maximum mapped address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000363};
364
Mark McLoughlina647dac2008-11-20 15:49:48 +0000365/* PCI domain-device relationship */
366struct device_domain_info {
367 struct list_head link; /* link to domain siblings */
368 struct list_head global; /* link to global list */
David Woodhouse276dbf992009-04-04 01:45:37 +0100369 u8 bus; /* PCI bus number */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000370 u8 devfn; /* PCI devfn number */
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000371 struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
Yu Zhao93a23a72009-05-18 13:51:37 +0800372 struct intel_iommu *iommu; /* IOMMU used by this device */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000373 struct dmar_domain *domain; /* pointer to domain */
374};
375
Jiang Liub94e4112014-02-19 14:07:25 +0800376struct dmar_rmrr_unit {
377 struct list_head list; /* list of rmrr units */
378 struct acpi_dmar_header *hdr; /* ACPI header */
379 u64 base_address; /* reserved base address*/
380 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000381 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800382 int devices_cnt; /* target device count */
383};
384
385struct dmar_atsr_unit {
386 struct list_head list; /* list of ATSR units */
387 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000388 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800389 int devices_cnt; /* target device count */
390 u8 include_all:1; /* include all ports */
391};
392
393static LIST_HEAD(dmar_atsr_units);
394static LIST_HEAD(dmar_rmrr_units);
395
396#define for_each_rmrr_units(rmrr) \
397 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
398
mark gross5e0d2a62008-03-04 15:22:08 -0800399static void flush_unmaps_timeout(unsigned long data);
400
Jiang Liub707cb02014-01-06 14:18:26 +0800401static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
mark gross5e0d2a62008-03-04 15:22:08 -0800402
mark gross80b20dd2008-04-18 13:53:58 -0700403#define HIGH_WATER_MARK 250
404struct deferred_flush_tables {
405 int next;
406 struct iova *iova[HIGH_WATER_MARK];
407 struct dmar_domain *domain[HIGH_WATER_MARK];
David Woodhouseea8ea462014-03-05 17:09:32 +0000408 struct page *freelist[HIGH_WATER_MARK];
mark gross80b20dd2008-04-18 13:53:58 -0700409};
410
411static struct deferred_flush_tables *deferred_flush;
412
mark gross5e0d2a62008-03-04 15:22:08 -0800413/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800414static int g_num_of_iommus;
415
416static DEFINE_SPINLOCK(async_umap_flush_lock);
417static LIST_HEAD(unmaps_to_do);
418
419static int timer_on;
420static long list_size;
mark gross5e0d2a62008-03-04 15:22:08 -0800421
Jiang Liu92d03cc2014-02-19 14:07:28 +0800422static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700423static void domain_remove_dev_info(struct dmar_domain *domain);
Jiang Liub94e4112014-02-19 14:07:25 +0800424static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -0700425 struct device *dev);
Jiang Liu92d03cc2014-02-19 14:07:28 +0800426static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000427 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800428static int domain_detach_iommu(struct dmar_domain *domain,
429 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700430
Suresh Siddhad3f13812011-08-23 17:05:25 -0700431#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800432int dmar_disabled = 0;
433#else
434int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700435#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800436
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200437int intel_iommu_enabled = 0;
438EXPORT_SYMBOL_GPL(intel_iommu_enabled);
439
David Woodhouse2d9e6672010-06-15 10:57:57 +0100440static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700441static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800442static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100443static int intel_iommu_superpage = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700444
David Woodhousec0771df2011-10-14 20:59:46 +0100445int intel_iommu_gfx_mapped;
446EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
447
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700448#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
449static DEFINE_SPINLOCK(device_domain_lock);
450static LIST_HEAD(device_domain_list);
451
Thierry Redingb22f6432014-06-27 09:03:12 +0200452static const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100453
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700454static int __init intel_iommu_setup(char *str)
455{
456 if (!str)
457 return -EINVAL;
458 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800459 if (!strncmp(str, "on", 2)) {
460 dmar_disabled = 0;
461 printk(KERN_INFO "Intel-IOMMU: enabled\n");
462 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700463 dmar_disabled = 1;
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800464 printk(KERN_INFO "Intel-IOMMU: disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700465 } else if (!strncmp(str, "igfx_off", 8)) {
466 dmar_map_gfx = 0;
467 printk(KERN_INFO
468 "Intel-IOMMU: disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700469 } else if (!strncmp(str, "forcedac", 8)) {
mark gross5e0d2a62008-03-04 15:22:08 -0800470 printk(KERN_INFO
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700471 "Intel-IOMMU: Forcing DAC for PCI devices\n");
472 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800473 } else if (!strncmp(str, "strict", 6)) {
474 printk(KERN_INFO
475 "Intel-IOMMU: disable batched IOTLB flush\n");
476 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100477 } else if (!strncmp(str, "sp_off", 6)) {
478 printk(KERN_INFO
479 "Intel-IOMMU: disable supported super page\n");
480 intel_iommu_superpage = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700481 }
482
483 str += strcspn(str, ",");
484 while (*str == ',')
485 str++;
486 }
487 return 0;
488}
489__setup("intel_iommu=", intel_iommu_setup);
490
491static struct kmem_cache *iommu_domain_cache;
492static struct kmem_cache *iommu_devinfo_cache;
493static struct kmem_cache *iommu_iova_cache;
494
Suresh Siddha4c923d42009-10-02 11:01:24 -0700495static inline void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700496{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700497 struct page *page;
498 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700499
Suresh Siddha4c923d42009-10-02 11:01:24 -0700500 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
501 if (page)
502 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700503 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700504}
505
506static inline void free_pgtable_page(void *vaddr)
507{
508 free_page((unsigned long)vaddr);
509}
510
511static inline void *alloc_domain_mem(void)
512{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900513 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700514}
515
Kay, Allen M38717942008-09-09 18:37:29 +0300516static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700517{
518 kmem_cache_free(iommu_domain_cache, vaddr);
519}
520
521static inline void * alloc_devinfo_mem(void)
522{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900523 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700524}
525
526static inline void free_devinfo_mem(void *vaddr)
527{
528 kmem_cache_free(iommu_devinfo_cache, vaddr);
529}
530
531struct iova *alloc_iova_mem(void)
532{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900533 return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700534}
535
536void free_iova_mem(struct iova *iova)
537{
538 kmem_cache_free(iommu_iova_cache, iova);
539}
540
Jiang Liuab8dfe22014-07-11 14:19:27 +0800541static inline int domain_type_is_vm(struct dmar_domain *domain)
542{
543 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
544}
545
546static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
547{
548 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
549 DOMAIN_FLAG_STATIC_IDENTITY);
550}
Weidong Han1b573682008-12-08 15:34:06 +0800551
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700552static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800553{
554 unsigned long sagaw;
555 int agaw = -1;
556
557 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700558 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800559 agaw >= 0; agaw--) {
560 if (test_bit(agaw, &sagaw))
561 break;
562 }
563
564 return agaw;
565}
566
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700567/*
568 * Calculate max SAGAW for each iommu.
569 */
570int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
571{
572 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
573}
574
575/*
576 * calculate agaw for each iommu.
577 * "SAGAW" may be different across iommus, use a default agaw, and
578 * get a supported less agaw for iommus that don't support the default agaw.
579 */
580int iommu_calculate_agaw(struct intel_iommu *iommu)
581{
582 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
583}
584
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700585/* This functionin only returns single iommu in a domain */
Weidong Han8c11e792008-12-08 15:29:22 +0800586static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
587{
588 int iommu_id;
589
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700590 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800591 BUG_ON(domain_type_is_vm_or_si(domain));
Mike Travis1b198bb2012-03-05 15:05:16 -0800592 iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
Weidong Han8c11e792008-12-08 15:29:22 +0800593 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
594 return NULL;
595
596 return g_iommus[iommu_id];
597}
598
Weidong Han8e6040972008-12-08 15:49:06 +0800599static void domain_update_iommu_coherency(struct dmar_domain *domain)
600{
David Woodhoused0501962014-03-11 17:10:29 -0700601 struct dmar_drhd_unit *drhd;
602 struct intel_iommu *iommu;
603 int i, found = 0;
Weidong Han8e6040972008-12-08 15:49:06 +0800604
David Woodhoused0501962014-03-11 17:10:29 -0700605 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800606
Mike Travis1b198bb2012-03-05 15:05:16 -0800607 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
David Woodhoused0501962014-03-11 17:10:29 -0700608 found = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800609 if (!ecap_coherent(g_iommus[i]->ecap)) {
610 domain->iommu_coherency = 0;
611 break;
612 }
Weidong Han8e6040972008-12-08 15:49:06 +0800613 }
David Woodhoused0501962014-03-11 17:10:29 -0700614 if (found)
615 return;
616
617 /* No hardware attached; use lowest common denominator */
618 rcu_read_lock();
619 for_each_active_iommu(iommu, drhd) {
620 if (!ecap_coherent(iommu->ecap)) {
621 domain->iommu_coherency = 0;
622 break;
623 }
624 }
625 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800626}
627
Sheng Yang58c610b2009-03-18 15:33:05 +0800628static void domain_update_iommu_snooping(struct dmar_domain *domain)
629{
630 int i;
631
632 domain->iommu_snooping = 1;
633
Mike Travis1b198bb2012-03-05 15:05:16 -0800634 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
Sheng Yang58c610b2009-03-18 15:33:05 +0800635 if (!ecap_sc_support(g_iommus[i]->ecap)) {
636 domain->iommu_snooping = 0;
637 break;
638 }
Sheng Yang58c610b2009-03-18 15:33:05 +0800639 }
640}
641
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100642static void domain_update_iommu_superpage(struct dmar_domain *domain)
643{
Allen Kay8140a952011-10-14 12:32:17 -0700644 struct dmar_drhd_unit *drhd;
645 struct intel_iommu *iommu = NULL;
646 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100647
648 if (!intel_iommu_superpage) {
649 domain->iommu_superpage = 0;
650 return;
651 }
652
Allen Kay8140a952011-10-14 12:32:17 -0700653 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800654 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700655 for_each_active_iommu(iommu, drhd) {
656 mask &= cap_super_page_val(iommu->cap);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100657 if (!mask) {
658 break;
659 }
660 }
Jiang Liu0e242612014-02-19 14:07:34 +0800661 rcu_read_unlock();
662
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100663 domain->iommu_superpage = fls(mask);
664}
665
Sheng Yang58c610b2009-03-18 15:33:05 +0800666/* Some capabilities may be different across iommus */
667static void domain_update_iommu_cap(struct dmar_domain *domain)
668{
669 domain_update_iommu_coherency(domain);
670 domain_update_iommu_snooping(domain);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100671 domain_update_iommu_superpage(domain);
Sheng Yang58c610b2009-03-18 15:33:05 +0800672}
673
David Woodhouse156baca2014-03-09 14:00:57 -0700674static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800675{
676 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800677 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700678 struct device *tmp;
679 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800680 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800681 int i;
682
David Woodhouse156baca2014-03-09 14:00:57 -0700683 if (dev_is_pci(dev)) {
684 pdev = to_pci_dev(dev);
685 segment = pci_domain_nr(pdev->bus);
686 } else if (ACPI_COMPANION(dev))
687 dev = &ACPI_COMPANION(dev)->dev;
688
Jiang Liu0e242612014-02-19 14:07:34 +0800689 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800690 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700691 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100692 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800693
Jiang Liub683b232014-02-19 14:07:32 +0800694 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700695 drhd->devices_cnt, i, tmp) {
696 if (tmp == dev) {
697 *bus = drhd->devices[i].bus;
698 *devfn = drhd->devices[i].devfn;
699 goto out;
700 }
701
702 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000703 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700704
705 ptmp = to_pci_dev(tmp);
706 if (ptmp->subordinate &&
707 ptmp->subordinate->number <= pdev->bus->number &&
708 ptmp->subordinate->busn_res.end >= pdev->bus->number)
709 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100710 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800711
David Woodhouse156baca2014-03-09 14:00:57 -0700712 if (pdev && drhd->include_all) {
713 got_pdev:
714 *bus = pdev->bus->number;
715 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800716 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700717 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800718 }
Jiang Liub683b232014-02-19 14:07:32 +0800719 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700720 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800721 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800722
Jiang Liub683b232014-02-19 14:07:32 +0800723 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800724}
725
Weidong Han5331fe62008-12-08 23:00:00 +0800726static void domain_flush_cache(struct dmar_domain *domain,
727 void *addr, int size)
728{
729 if (!domain->iommu_coherency)
730 clflush_cache_range(addr, size);
731}
732
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700733/* Gets context entry for a given bus and devfn */
734static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
735 u8 bus, u8 devfn)
736{
737 struct root_entry *root;
738 struct context_entry *context;
739 unsigned long phy_addr;
740 unsigned long flags;
741
742 spin_lock_irqsave(&iommu->lock, flags);
743 root = &iommu->root_entry[bus];
744 context = get_context_addr_from_root(root);
745 if (!context) {
Suresh Siddha4c923d42009-10-02 11:01:24 -0700746 context = (struct context_entry *)
747 alloc_pgtable_page(iommu->node);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700748 if (!context) {
749 spin_unlock_irqrestore(&iommu->lock, flags);
750 return NULL;
751 }
Fenghua Yu5b6985c2008-10-16 18:02:32 -0700752 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700753 phy_addr = virt_to_phys((void *)context);
754 set_root_value(root, phy_addr);
755 set_root_present(root);
756 __iommu_flush_cache(iommu, root, sizeof(*root));
757 }
758 spin_unlock_irqrestore(&iommu->lock, flags);
759 return &context[devfn];
760}
761
762static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
763{
764 struct root_entry *root;
765 struct context_entry *context;
766 int ret;
767 unsigned long flags;
768
769 spin_lock_irqsave(&iommu->lock, flags);
770 root = &iommu->root_entry[bus];
771 context = get_context_addr_from_root(root);
772 if (!context) {
773 ret = 0;
774 goto out;
775 }
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000776 ret = context_present(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700777out:
778 spin_unlock_irqrestore(&iommu->lock, flags);
779 return ret;
780}
781
782static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
783{
784 struct root_entry *root;
785 struct context_entry *context;
786 unsigned long flags;
787
788 spin_lock_irqsave(&iommu->lock, flags);
789 root = &iommu->root_entry[bus];
790 context = get_context_addr_from_root(root);
791 if (context) {
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000792 context_clear_entry(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700793 __iommu_flush_cache(iommu, &context[devfn], \
794 sizeof(*context));
795 }
796 spin_unlock_irqrestore(&iommu->lock, flags);
797}
798
799static void free_context_table(struct intel_iommu *iommu)
800{
801 struct root_entry *root;
802 int i;
803 unsigned long flags;
804 struct context_entry *context;
805
806 spin_lock_irqsave(&iommu->lock, flags);
807 if (!iommu->root_entry) {
808 goto out;
809 }
810 for (i = 0; i < ROOT_ENTRY_NR; i++) {
811 root = &iommu->root_entry[i];
812 context = get_context_addr_from_root(root);
813 if (context)
814 free_pgtable_page(context);
815 }
816 free_pgtable_page(iommu->root_entry);
817 iommu->root_entry = NULL;
818out:
819 spin_unlock_irqrestore(&iommu->lock, flags);
820}
821
David Woodhouseb026fd22009-06-28 10:37:25 +0100822static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000823 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700824{
David Woodhouseb026fd22009-06-28 10:37:25 +0100825 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700826 struct dma_pte *parent, *pte = NULL;
827 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700828 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700829
830 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200831
832 if (addr_width < BITS_PER_LONG && pfn >> addr_width)
833 /* Address beyond IOMMU's addressing capabilities. */
834 return NULL;
835
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700836 parent = domain->pgd;
837
David Woodhouse5cf0a762014-03-19 16:07:49 +0000838 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700839 void *tmp_page;
840
David Woodhouseb026fd22009-06-28 10:37:25 +0100841 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700842 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000843 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100844 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000845 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700846 break;
847
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000848 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100849 uint64_t pteval;
850
Suresh Siddha4c923d42009-10-02 11:01:24 -0700851 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700852
David Woodhouse206a73c12009-07-01 19:30:28 +0100853 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700854 return NULL;
David Woodhouse206a73c12009-07-01 19:30:28 +0100855
David Woodhousec85994e2009-07-01 19:21:24 +0100856 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400857 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 +0800858 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100859 /* Someone else set it while we were thinking; use theirs. */
860 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800861 else
David Woodhousec85994e2009-07-01 19:21:24 +0100862 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700863 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000864 if (level == 1)
865 break;
866
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000867 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700868 level--;
869 }
870
David Woodhouse5cf0a762014-03-19 16:07:49 +0000871 if (!*target_level)
872 *target_level = level;
873
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700874 return pte;
875}
876
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100877
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700878/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100879static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
880 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100881 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700882{
883 struct dma_pte *parent, *pte = NULL;
884 int total = agaw_to_level(domain->agaw);
885 int offset;
886
887 parent = domain->pgd;
888 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100889 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700890 pte = &parent[offset];
891 if (level == total)
892 return pte;
893
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100894 if (!dma_pte_present(pte)) {
895 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700896 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100897 }
898
Yijing Wange16922a2014-05-20 20:37:51 +0800899 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100900 *large_page = total;
901 return pte;
902 }
903
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000904 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700905 total--;
906 }
907 return NULL;
908}
909
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700910/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000911static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf2009-06-27 22:09:11 +0100912 unsigned long start_pfn,
913 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700914{
David Woodhouse04b18e62009-06-27 19:15:01 +0100915 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
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
David Woodhouse04b18e62009-06-27 19:15:01 +0100919 BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
David Woodhouse595badf2009-06-27 22:09:11 +0100920 BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
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{
David Woodhouse6660c632009-06-27 22:41:00 +0100981 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700982
David Woodhouse6660c632009-06-27 22:41:00 +0100983 BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
984 BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
David Woodhouse59c36282009-09-19 07:36:28 -0700985 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700986
Jiang Liud41a4ad2014-07-11 14:19:34 +0800987 dma_pte_clear_range(domain, start_pfn, last_pfn);
988
David Woodhousef3a0a522009-06-30 03:40:07 +0100989 /* We don't need lock here; nobody else touches the iova range */
Alex Williamson3269ee02013-06-15 10:27:19 -0600990 dma_pte_free_level(domain, agaw_to_level(domain->agaw),
991 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +0100992
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700993 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +0100994 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700995 free_pgtable_page(domain->pgd);
996 domain->pgd = NULL;
997 }
998}
999
David Woodhouseea8ea462014-03-05 17:09:32 +00001000/* When a page at a given level is being unlinked from its parent, we don't
1001 need to *modify* it at all. All we need to do is make a list of all the
1002 pages which can be freed just as soon as we've flushed the IOTLB and we
1003 know the hardware page-walk will no longer touch them.
1004 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1005 be freed. */
1006static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1007 int level, struct dma_pte *pte,
1008 struct page *freelist)
1009{
1010 struct page *pg;
1011
1012 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1013 pg->freelist = freelist;
1014 freelist = pg;
1015
1016 if (level == 1)
1017 return freelist;
1018
Jiang Liuadeb2592014-04-09 10:20:39 +08001019 pte = page_address(pg);
1020 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001021 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1022 freelist = dma_pte_list_pagetables(domain, level - 1,
1023 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001024 pte++;
1025 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001026
1027 return freelist;
1028}
1029
1030static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1031 struct dma_pte *pte, unsigned long pfn,
1032 unsigned long start_pfn,
1033 unsigned long last_pfn,
1034 struct page *freelist)
1035{
1036 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1037
1038 pfn = max(start_pfn, pfn);
1039 pte = &pte[pfn_level_offset(pfn, level)];
1040
1041 do {
1042 unsigned long level_pfn;
1043
1044 if (!dma_pte_present(pte))
1045 goto next;
1046
1047 level_pfn = pfn & level_mask(level);
1048
1049 /* If range covers entire pagetable, free it */
1050 if (start_pfn <= level_pfn &&
1051 last_pfn >= level_pfn + level_size(level) - 1) {
1052 /* These suborbinate page tables are going away entirely. Don't
1053 bother to clear them; we're just going to *free* them. */
1054 if (level > 1 && !dma_pte_superpage(pte))
1055 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1056
1057 dma_clear_pte(pte);
1058 if (!first_pte)
1059 first_pte = pte;
1060 last_pte = pte;
1061 } else if (level > 1) {
1062 /* Recurse down into a level that isn't *entirely* obsolete */
1063 freelist = dma_pte_clear_level(domain, level - 1,
1064 phys_to_virt(dma_pte_addr(pte)),
1065 level_pfn, start_pfn, last_pfn,
1066 freelist);
1067 }
1068next:
1069 pfn += level_size(level);
1070 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1071
1072 if (first_pte)
1073 domain_flush_cache(domain, first_pte,
1074 (void *)++last_pte - (void *)first_pte);
1075
1076 return freelist;
1077}
1078
1079/* We can't just free the pages because the IOMMU may still be walking
1080 the page tables, and may have cached the intermediate levels. The
1081 pages can only be freed after the IOTLB flush has been done. */
1082struct page *domain_unmap(struct dmar_domain *domain,
1083 unsigned long start_pfn,
1084 unsigned long last_pfn)
1085{
1086 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
1087 struct page *freelist = NULL;
1088
1089 BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
1090 BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
1091 BUG_ON(start_pfn > last_pfn);
1092
1093 /* we don't need lock here; nobody else touches the iova range */
1094 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1095 domain->pgd, 0, start_pfn, last_pfn, NULL);
1096
1097 /* free pgd */
1098 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1099 struct page *pgd_page = virt_to_page(domain->pgd);
1100 pgd_page->freelist = freelist;
1101 freelist = pgd_page;
1102
1103 domain->pgd = NULL;
1104 }
1105
1106 return freelist;
1107}
1108
1109void dma_free_pagelist(struct page *freelist)
1110{
1111 struct page *pg;
1112
1113 while ((pg = freelist)) {
1114 freelist = pg->freelist;
1115 free_pgtable_page(page_address(pg));
1116 }
1117}
1118
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001119/* iommu handling */
1120static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1121{
1122 struct root_entry *root;
1123 unsigned long flags;
1124
Suresh Siddha4c923d42009-10-02 11:01:24 -07001125 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001126 if (!root)
1127 return -ENOMEM;
1128
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{
Yu Zhao93a23a72009-05-18 13:51:37 +08001271 int found = 0;
1272 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) {
Yu Zhao93a23a72009-05-18 13:51:37 +08001286 found = 1;
1287 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 Liua868e6b2014-01-06 14:18:20 +08001467static void free_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);
1491
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001492 kfree(iommu->domains);
1493 kfree(iommu->domain_ids);
Jiang Liua868e6b2014-01-06 14:18:20 +08001494 iommu->domains = NULL;
1495 iommu->domain_ids = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001496
Weidong Hand9630fe2008-12-08 11:06:32 +08001497 g_iommus[iommu->seq_id] = NULL;
1498
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001499 /* free context mapping */
1500 free_context_table(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001501}
1502
Jiang Liuab8dfe22014-07-11 14:19:27 +08001503static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001504{
Jiang Liu92d03cc2014-02-19 14:07:28 +08001505 /* domain id for virtual machine, it won't be set in context */
1506 static atomic_t vm_domid = ATOMIC_INIT(0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001507 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001508
1509 domain = alloc_domain_mem();
1510 if (!domain)
1511 return NULL;
1512
Jiang Liuab8dfe22014-07-11 14:19:27 +08001513 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001514 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001515 domain->flags = flags;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001516 spin_lock_init(&domain->iommu_lock);
1517 INIT_LIST_HEAD(&domain->devices);
Jiang Liuab8dfe22014-07-11 14:19:27 +08001518 if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
Jiang Liu92d03cc2014-02-19 14:07:28 +08001519 domain->id = atomic_inc_return(&vm_domid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001520
1521 return domain;
1522}
1523
Jiang Liufb170fb2014-07-11 14:19:28 +08001524static int __iommu_attach_domain(struct dmar_domain *domain,
1525 struct intel_iommu *iommu)
1526{
1527 int num;
1528 unsigned long ndomains;
1529
1530 ndomains = cap_ndoms(iommu->cap);
1531 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1532 if (num < ndomains) {
1533 set_bit(num, iommu->domain_ids);
1534 iommu->domains[num] = domain;
1535 } else {
1536 num = -ENOSPC;
1537 }
1538
1539 return num;
1540}
1541
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001542static int iommu_attach_domain(struct dmar_domain *domain,
1543 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001544{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001545 int num;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001546 unsigned long flags;
1547
Weidong Han8c11e792008-12-08 15:29:22 +08001548 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001549 num = __iommu_attach_domain(domain, iommu);
Jiang Liu44bde612014-07-11 14:19:29 +08001550 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001551 if (num < 0)
1552 pr_err("IOMMU: no free domain ids\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001553
Jiang Liufb170fb2014-07-11 14:19:28 +08001554 return num;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001555}
1556
Jiang Liu44bde612014-07-11 14:19:29 +08001557static int iommu_attach_vm_domain(struct dmar_domain *domain,
1558 struct intel_iommu *iommu)
1559{
1560 int num;
1561 unsigned long ndomains;
1562
1563 ndomains = cap_ndoms(iommu->cap);
1564 for_each_set_bit(num, iommu->domain_ids, ndomains)
1565 if (iommu->domains[num] == domain)
1566 return num;
1567
1568 return __iommu_attach_domain(domain, iommu);
1569}
1570
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001571static void iommu_detach_domain(struct dmar_domain *domain,
1572 struct intel_iommu *iommu)
1573{
1574 unsigned long flags;
1575 int num, ndomains;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001576
1577 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001578 if (domain_type_is_vm_or_si(domain)) {
1579 ndomains = cap_ndoms(iommu->cap);
1580 for_each_set_bit(num, iommu->domain_ids, ndomains) {
1581 if (iommu->domains[num] == domain) {
1582 clear_bit(num, iommu->domain_ids);
1583 iommu->domains[num] = NULL;
1584 break;
1585 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001586 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001587 } else {
1588 clear_bit(domain->id, iommu->domain_ids);
1589 iommu->domains[domain->id] = NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001590 }
Weidong Han8c11e792008-12-08 15:29:22 +08001591 spin_unlock_irqrestore(&iommu->lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001592}
1593
Jiang Liufb170fb2014-07-11 14:19:28 +08001594static void domain_attach_iommu(struct dmar_domain *domain,
1595 struct intel_iommu *iommu)
1596{
1597 unsigned long flags;
1598
1599 spin_lock_irqsave(&domain->iommu_lock, flags);
1600 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
1601 domain->iommu_count++;
1602 if (domain->iommu_count == 1)
1603 domain->nid = iommu->node;
1604 domain_update_iommu_cap(domain);
1605 }
1606 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1607}
1608
1609static int domain_detach_iommu(struct dmar_domain *domain,
1610 struct intel_iommu *iommu)
1611{
1612 unsigned long flags;
1613 int count = INT_MAX;
1614
1615 spin_lock_irqsave(&domain->iommu_lock, flags);
1616 if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
1617 count = --domain->iommu_count;
1618 domain_update_iommu_cap(domain);
1619 }
1620 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1621
1622 return count;
1623}
1624
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001625static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001626static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001627
Joseph Cihula51a63e62011-03-21 11:04:24 -07001628static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001629{
1630 struct pci_dev *pdev = NULL;
1631 struct iova *iova;
1632 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001633
David Millerf6611972008-02-06 01:36:23 -08001634 init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001635
Mark Gross8a443df2008-03-04 14:59:31 -08001636 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1637 &reserved_rbtree_key);
1638
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001639 /* IOAPIC ranges shouldn't be accessed by DMA */
1640 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1641 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001642 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001643 printk(KERN_ERR "Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001644 return -ENODEV;
1645 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001646
1647 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1648 for_each_pci_dev(pdev) {
1649 struct resource *r;
1650
1651 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1652 r = &pdev->resource[i];
1653 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1654 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001655 iova = reserve_iova(&reserved_iova_list,
1656 IOVA_PFN(r->start),
1657 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001658 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001659 printk(KERN_ERR "Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001660 return -ENODEV;
1661 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001662 }
1663 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001664 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001665}
1666
1667static void domain_reserve_special_ranges(struct dmar_domain *domain)
1668{
1669 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1670}
1671
1672static inline int guestwidth_to_adjustwidth(int gaw)
1673{
1674 int agaw;
1675 int r = (gaw - 12) % 9;
1676
1677 if (r == 0)
1678 agaw = gaw;
1679 else
1680 agaw = gaw + 9 - r;
1681 if (agaw > 64)
1682 agaw = 64;
1683 return agaw;
1684}
1685
1686static int domain_init(struct dmar_domain *domain, int guest_width)
1687{
1688 struct intel_iommu *iommu;
1689 int adjust_width, agaw;
1690 unsigned long sagaw;
1691
David Millerf6611972008-02-06 01:36:23 -08001692 init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001693 domain_reserve_special_ranges(domain);
1694
1695 /* calculate AGAW */
Weidong Han8c11e792008-12-08 15:29:22 +08001696 iommu = domain_get_iommu(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001697 if (guest_width > cap_mgaw(iommu->cap))
1698 guest_width = cap_mgaw(iommu->cap);
1699 domain->gaw = guest_width;
1700 adjust_width = guestwidth_to_adjustwidth(guest_width);
1701 agaw = width_to_agaw(adjust_width);
1702 sagaw = cap_sagaw(iommu->cap);
1703 if (!test_bit(agaw, &sagaw)) {
1704 /* hardware doesn't support it, choose a bigger one */
1705 pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
1706 agaw = find_next_bit(&sagaw, 5, agaw);
1707 if (agaw >= 5)
1708 return -ENODEV;
1709 }
1710 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711
Weidong Han8e6040972008-12-08 15:49:06 +08001712 if (ecap_coherent(iommu->ecap))
1713 domain->iommu_coherency = 1;
1714 else
1715 domain->iommu_coherency = 0;
1716
Sheng Yang58c610b2009-03-18 15:33:05 +08001717 if (ecap_sc_support(iommu->ecap))
1718 domain->iommu_snooping = 1;
1719 else
1720 domain->iommu_snooping = 0;
1721
David Woodhouse214e39a2014-03-19 10:38:49 +00001722 if (intel_iommu_superpage)
1723 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1724 else
1725 domain->iommu_superpage = 0;
1726
Suresh Siddha4c923d42009-10-02 11:01:24 -07001727 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001728
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001729 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001730 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001731 if (!domain->pgd)
1732 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001733 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001734 return 0;
1735}
1736
1737static void domain_exit(struct dmar_domain *domain)
1738{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001739 struct dmar_drhd_unit *drhd;
1740 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00001741 struct page *freelist = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001742
1743 /* Domain 0 is reserved, so dont process it */
1744 if (!domain)
1745 return;
1746
Alex Williamson7b668352011-05-24 12:02:41 +01001747 /* Flush any lazy unmaps that may reference this domain */
1748 if (!intel_iommu_strict)
1749 flush_unmaps_timeout(0);
1750
Jiang Liu92d03cc2014-02-19 14:07:28 +08001751 /* remove associated devices */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001752 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001753
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001754 /* destroy iovas */
1755 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001756
David Woodhouseea8ea462014-03-05 17:09:32 +00001757 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001758
Jiang Liu92d03cc2014-02-19 14:07:28 +08001759 /* clear attached or cached domains */
Jiang Liu0e242612014-02-19 14:07:34 +08001760 rcu_read_lock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001761 for_each_active_iommu(iommu, drhd)
Jiang Liufb170fb2014-07-11 14:19:28 +08001762 iommu_detach_domain(domain, iommu);
Jiang Liu0e242612014-02-19 14:07:34 +08001763 rcu_read_unlock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001764
David Woodhouseea8ea462014-03-05 17:09:32 +00001765 dma_free_pagelist(freelist);
1766
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001767 free_domain_mem(domain);
1768}
1769
David Woodhouse64ae8922014-03-09 12:52:30 -07001770static int domain_context_mapping_one(struct dmar_domain *domain,
1771 struct intel_iommu *iommu,
1772 u8 bus, u8 devfn, int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001773{
1774 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001775 unsigned long flags;
Weidong Hanea6606b2008-12-08 23:08:15 +08001776 struct dma_pte *pgd;
Weidong Hanea6606b2008-12-08 23:08:15 +08001777 int id;
1778 int agaw;
Yu Zhao93a23a72009-05-18 13:51:37 +08001779 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001780
1781 pr_debug("Set context mapping for %02x:%02x.%d\n",
1782 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001783
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001784 BUG_ON(!domain->pgd);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001785 BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
1786 translation != CONTEXT_TT_MULTI_LEVEL);
Weidong Han5331fe62008-12-08 23:00:00 +08001787
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001788 context = device_to_context_entry(iommu, bus, devfn);
1789 if (!context)
1790 return -ENOMEM;
1791 spin_lock_irqsave(&iommu->lock, flags);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001792 if (context_present(context)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001793 spin_unlock_irqrestore(&iommu->lock, flags);
1794 return 0;
1795 }
1796
Weidong Hanea6606b2008-12-08 23:08:15 +08001797 id = domain->id;
1798 pgd = domain->pgd;
1799
Jiang Liuab8dfe22014-07-11 14:19:27 +08001800 if (domain_type_is_vm_or_si(domain)) {
Jiang Liu44bde612014-07-11 14:19:29 +08001801 if (domain_type_is_vm(domain)) {
1802 id = iommu_attach_vm_domain(domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08001803 if (id < 0) {
Weidong Hanea6606b2008-12-08 23:08:15 +08001804 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001805 pr_err("IOMMU: no free domain ids\n");
Weidong Hanea6606b2008-12-08 23:08:15 +08001806 return -EFAULT;
1807 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001808 }
1809
1810 /* Skip top levels of page tables for
1811 * iommu which has less agaw than default.
Chris Wright1672af12009-12-02 12:06:34 -08001812 * Unnecessary for PT mode.
Weidong Hanea6606b2008-12-08 23:08:15 +08001813 */
Chris Wright1672af12009-12-02 12:06:34 -08001814 if (translation != CONTEXT_TT_PASS_THROUGH) {
1815 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
1816 pgd = phys_to_virt(dma_pte_addr(pgd));
1817 if (!dma_pte_present(pgd)) {
1818 spin_unlock_irqrestore(&iommu->lock, flags);
1819 return -ENOMEM;
1820 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001821 }
1822 }
1823 }
1824
1825 context_set_domain_id(context, id);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001826
Yu Zhao93a23a72009-05-18 13:51:37 +08001827 if (translation != CONTEXT_TT_PASS_THROUGH) {
David Woodhouse64ae8922014-03-09 12:52:30 -07001828 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
Yu Zhao93a23a72009-05-18 13:51:37 +08001829 translation = info ? CONTEXT_TT_DEV_IOTLB :
1830 CONTEXT_TT_MULTI_LEVEL;
1831 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001832 /*
1833 * In pass through mode, AW must be programmed to indicate the largest
1834 * AGAW value supported by hardware. And ASR is ignored by hardware.
1835 */
Yu Zhao93a23a72009-05-18 13:51:37 +08001836 if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001837 context_set_address_width(context, iommu->msagaw);
Yu Zhao93a23a72009-05-18 13:51:37 +08001838 else {
1839 context_set_address_root(context, virt_to_phys(pgd));
1840 context_set_address_width(context, iommu->agaw);
1841 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001842
1843 context_set_translation_type(context, translation);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001844 context_set_fault_enable(context);
1845 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08001846 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001847
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001848 /*
1849 * It's a non-present to present mapping. If hardware doesn't cache
1850 * non-present entry we only need to flush the write-buffer. If the
1851 * _does_ cache non-present entries, then it does so in the special
1852 * domain #0, which we have to flush:
1853 */
1854 if (cap_caching_mode(iommu->cap)) {
1855 iommu->flush.flush_context(iommu, 0,
1856 (((u16)bus) << 8) | devfn,
1857 DMA_CCMD_MASK_NOBIT,
1858 DMA_CCMD_DEVICE_INVL);
Jiang Liu18fd7792014-07-11 14:19:26 +08001859 iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001860 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001861 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001862 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001863 iommu_enable_dev_iotlb(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001864 spin_unlock_irqrestore(&iommu->lock, flags);
Weidong Hanc7151a82008-12-08 22:51:37 +08001865
Jiang Liufb170fb2014-07-11 14:19:28 +08001866 domain_attach_iommu(domain, iommu);
1867
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001868 return 0;
1869}
1870
Alex Williamson579305f2014-07-03 09:51:43 -06001871struct domain_context_mapping_data {
1872 struct dmar_domain *domain;
1873 struct intel_iommu *iommu;
1874 int translation;
1875};
1876
1877static int domain_context_mapping_cb(struct pci_dev *pdev,
1878 u16 alias, void *opaque)
1879{
1880 struct domain_context_mapping_data *data = opaque;
1881
1882 return domain_context_mapping_one(data->domain, data->iommu,
1883 PCI_BUS_NUM(alias), alias & 0xff,
1884 data->translation);
1885}
1886
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001887static int
David Woodhousee1f167f2014-03-09 15:24:46 -07001888domain_context_mapping(struct dmar_domain *domain, struct device *dev,
1889 int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001890{
David Woodhouse64ae8922014-03-09 12:52:30 -07001891 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001892 u8 bus, devfn;
Alex Williamson579305f2014-07-03 09:51:43 -06001893 struct domain_context_mapping_data data;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001894
David Woodhousee1f167f2014-03-09 15:24:46 -07001895 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07001896 if (!iommu)
1897 return -ENODEV;
1898
Alex Williamson579305f2014-07-03 09:51:43 -06001899 if (!dev_is_pci(dev))
1900 return domain_context_mapping_one(domain, iommu, bus, devfn,
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001901 translation);
Alex Williamson579305f2014-07-03 09:51:43 -06001902
1903 data.domain = domain;
1904 data.iommu = iommu;
1905 data.translation = translation;
1906
1907 return pci_for_each_dma_alias(to_pci_dev(dev),
1908 &domain_context_mapping_cb, &data);
1909}
1910
1911static int domain_context_mapped_cb(struct pci_dev *pdev,
1912 u16 alias, void *opaque)
1913{
1914 struct intel_iommu *iommu = opaque;
1915
1916 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001917}
1918
David Woodhousee1f167f2014-03-09 15:24:46 -07001919static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001920{
Weidong Han5331fe62008-12-08 23:00:00 +08001921 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001922 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08001923
David Woodhousee1f167f2014-03-09 15:24:46 -07001924 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08001925 if (!iommu)
1926 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001927
Alex Williamson579305f2014-07-03 09:51:43 -06001928 if (!dev_is_pci(dev))
1929 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07001930
Alex Williamson579305f2014-07-03 09:51:43 -06001931 return !pci_for_each_dma_alias(to_pci_dev(dev),
1932 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001933}
1934
Fenghua Yuf5329592009-08-04 15:09:37 -07001935/* Returns a number of VTD pages, but aligned to MM page size */
1936static inline unsigned long aligned_nrpages(unsigned long host_addr,
1937 size_t size)
1938{
1939 host_addr &= ~PAGE_MASK;
1940 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
1941}
1942
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001943/* Return largest possible superpage level for a given mapping */
1944static inline int hardware_largepage_caps(struct dmar_domain *domain,
1945 unsigned long iov_pfn,
1946 unsigned long phy_pfn,
1947 unsigned long pages)
1948{
1949 int support, level = 1;
1950 unsigned long pfnmerge;
1951
1952 support = domain->iommu_superpage;
1953
1954 /* To use a large page, the virtual *and* physical addresses
1955 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
1956 of them will mean we have to use smaller pages. So just
1957 merge them and check both at once. */
1958 pfnmerge = iov_pfn | phy_pfn;
1959
1960 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
1961 pages >>= VTD_STRIDE_SHIFT;
1962 if (!pages)
1963 break;
1964 pfnmerge >>= VTD_STRIDE_SHIFT;
1965 level++;
1966 support--;
1967 }
1968 return level;
1969}
1970
David Woodhouse9051aa02009-06-29 12:30:54 +01001971static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
1972 struct scatterlist *sg, unsigned long phys_pfn,
1973 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01001974{
1975 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01001976 phys_addr_t uninitialized_var(pteval);
David Woodhousee1605492009-06-29 11:17:38 +01001977 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
David Woodhouse9051aa02009-06-29 12:30:54 +01001978 unsigned long sg_res;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001979 unsigned int largepage_lvl = 0;
1980 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01001981
1982 BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
1983
1984 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
1985 return -EINVAL;
1986
1987 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
1988
David Woodhouse9051aa02009-06-29 12:30:54 +01001989 if (sg)
1990 sg_res = 0;
1991 else {
1992 sg_res = nr_pages + 1;
1993 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
1994 }
1995
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001996 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01001997 uint64_t tmp;
1998
David Woodhousee1605492009-06-29 11:17:38 +01001999 if (!sg_res) {
Fenghua Yuf5329592009-08-04 15:09:37 -07002000 sg_res = aligned_nrpages(sg->offset, sg->length);
David Woodhousee1605492009-06-29 11:17:38 +01002001 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
2002 sg->dma_length = sg->length;
2003 pteval = page_to_phys(sg_page(sg)) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002004 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002005 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002006
David Woodhousee1605492009-06-29 11:17:38 +01002007 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002008 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2009
David Woodhouse5cf0a762014-03-19 16:07:49 +00002010 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002011 if (!pte)
2012 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002013 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002014 if (largepage_lvl > 1) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002015 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002016 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2017 /*
2018 * Ensure that old small page tables are
2019 * removed to make room for superpage,
2020 * if they exist.
2021 */
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002022 dma_pte_free_pagetable(domain, iov_pfn,
Jiang Liud41a4ad2014-07-11 14:19:34 +08002023 iov_pfn + lvl_pages - 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002024 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002025 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002026 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002027
David Woodhousee1605492009-06-29 11:17:38 +01002028 }
2029 /* We don't need lock here, nobody else
2030 * touches the iova range
2031 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002032 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002033 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002034 static int dumps = 5;
David Woodhousec85994e2009-07-01 19:21:24 +01002035 printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2036 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002037 if (dumps) {
2038 dumps--;
2039 debug_dma_dump_mappings(NULL);
2040 }
2041 WARN_ON(1);
2042 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002043
2044 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2045
2046 BUG_ON(nr_pages < lvl_pages);
2047 BUG_ON(sg_res < lvl_pages);
2048
2049 nr_pages -= lvl_pages;
2050 iov_pfn += lvl_pages;
2051 phys_pfn += lvl_pages;
2052 pteval += lvl_pages * VTD_PAGE_SIZE;
2053 sg_res -= lvl_pages;
2054
2055 /* If the next PTE would be the first in a new page, then we
2056 need to flush the cache on the entries we've just written.
2057 And then we'll need to recalculate 'pte', so clear it and
2058 let it get set again in the if (!pte) block above.
2059
2060 If we're done (!nr_pages) we need to flush the cache too.
2061
2062 Also if we've been setting superpages, we may need to
2063 recalculate 'pte' and switch back to smaller pages for the
2064 end of the mapping, if the trailing size is not enough to
2065 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002066 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002067 if (!nr_pages || first_pte_in_page(pte) ||
2068 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002069 domain_flush_cache(domain, first_pte,
2070 (void *)pte - (void *)first_pte);
2071 pte = NULL;
2072 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002073
2074 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002075 sg = sg_next(sg);
2076 }
2077 return 0;
2078}
2079
David Woodhouse9051aa02009-06-29 12:30:54 +01002080static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2081 struct scatterlist *sg, unsigned long nr_pages,
2082 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002083{
David Woodhouse9051aa02009-06-29 12:30:54 +01002084 return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
2085}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002086
David Woodhouse9051aa02009-06-29 12:30:54 +01002087static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2088 unsigned long phys_pfn, unsigned long nr_pages,
2089 int prot)
2090{
2091 return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002092}
2093
Weidong Hanc7151a82008-12-08 22:51:37 +08002094static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002095{
Weidong Hanc7151a82008-12-08 22:51:37 +08002096 if (!iommu)
2097 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002098
2099 clear_context_table(iommu, bus, devfn);
2100 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002101 DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002102 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002103}
2104
David Woodhouse109b9b02012-05-25 17:43:02 +01002105static inline void unlink_domain_info(struct device_domain_info *info)
2106{
2107 assert_spin_locked(&device_domain_lock);
2108 list_del(&info->link);
2109 list_del(&info->global);
2110 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002111 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002112}
2113
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002114static void domain_remove_dev_info(struct dmar_domain *domain)
2115{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002116 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002117 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002118
2119 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wang3a74ca02014-05-20 20:37:47 +08002120 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhouse109b9b02012-05-25 17:43:02 +01002121 unlink_domain_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002122 spin_unlock_irqrestore(&device_domain_lock, flags);
2123
Yu Zhao93a23a72009-05-18 13:51:37 +08002124 iommu_disable_dev_iotlb(info);
David Woodhouse7c7faa12014-03-09 13:33:06 -07002125 iommu_detach_dev(info->iommu, info->bus, info->devfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002126
Jiang Liuab8dfe22014-07-11 14:19:27 +08002127 if (domain_type_is_vm(domain)) {
David Woodhouse7c7faa12014-03-09 13:33:06 -07002128 iommu_detach_dependent_devices(info->iommu, info->dev);
Jiang Liufb170fb2014-07-11 14:19:28 +08002129 domain_detach_iommu(domain, info->iommu);
Jiang Liu92d03cc2014-02-19 14:07:28 +08002130 }
2131
2132 free_devinfo_mem(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002133 spin_lock_irqsave(&device_domain_lock, flags);
2134 }
2135 spin_unlock_irqrestore(&device_domain_lock, flags);
2136}
2137
2138/*
2139 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002140 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002141 */
David Woodhouse1525a292014-03-06 16:19:30 +00002142static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002143{
2144 struct device_domain_info *info;
2145
2146 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002147 info = dev->archdata.iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002148 if (info)
2149 return info->domain;
2150 return NULL;
2151}
2152
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002153static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002154dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2155{
2156 struct device_domain_info *info;
2157
2158 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002159 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002160 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002161 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002162
2163 return NULL;
2164}
2165
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002166static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
David Woodhouse41e80dca2014-03-09 13:55:54 -07002167 int bus, int devfn,
David Woodhouseb718cd32014-03-09 13:11:33 -07002168 struct device *dev,
2169 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002170{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002171 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002172 struct device_domain_info *info;
2173 unsigned long flags;
2174
2175 info = alloc_devinfo_mem();
2176 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002177 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002178
Jiang Liu745f2582014-02-19 14:07:26 +08002179 info->bus = bus;
2180 info->devfn = devfn;
2181 info->dev = dev;
2182 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002183 info->iommu = iommu;
Jiang Liu745f2582014-02-19 14:07:26 +08002184
2185 spin_lock_irqsave(&device_domain_lock, flags);
2186 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002187 found = find_domain(dev);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002188 else {
2189 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002190 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002191 if (info2)
2192 found = info2->domain;
2193 }
Jiang Liu745f2582014-02-19 14:07:26 +08002194 if (found) {
2195 spin_unlock_irqrestore(&device_domain_lock, flags);
2196 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002197 /* Caller must free the original domain */
2198 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002199 }
2200
David Woodhouseb718cd32014-03-09 13:11:33 -07002201 list_add(&info->link, &domain->devices);
2202 list_add(&info->global, &device_domain_list);
2203 if (dev)
2204 dev->archdata.iommu = info;
2205 spin_unlock_irqrestore(&device_domain_lock, flags);
2206
2207 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002208}
2209
Alex Williamson579305f2014-07-03 09:51:43 -06002210static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2211{
2212 *(u16 *)opaque = alias;
2213 return 0;
2214}
2215
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002216/* domain is initialized */
David Woodhouse146922e2014-03-09 15:44:17 -07002217static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002218{
Alex Williamson579305f2014-07-03 09:51:43 -06002219 struct dmar_domain *domain, *tmp;
2220 struct intel_iommu *iommu;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002221 struct device_domain_info *info;
Alex Williamson579305f2014-07-03 09:51:43 -06002222 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002223 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002224 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002225
David Woodhouse146922e2014-03-09 15:44:17 -07002226 domain = find_domain(dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002227 if (domain)
2228 return domain;
2229
David Woodhouse146922e2014-03-09 15:44:17 -07002230 iommu = device_to_iommu(dev, &bus, &devfn);
2231 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002232 return NULL;
2233
2234 if (dev_is_pci(dev)) {
2235 struct pci_dev *pdev = to_pci_dev(dev);
2236
2237 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2238
2239 spin_lock_irqsave(&device_domain_lock, flags);
2240 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2241 PCI_BUS_NUM(dma_alias),
2242 dma_alias & 0xff);
2243 if (info) {
2244 iommu = info->iommu;
2245 domain = info->domain;
2246 }
2247 spin_unlock_irqrestore(&device_domain_lock, flags);
2248
2249 /* DMA alias already has a domain, uses it */
2250 if (info)
2251 goto found_domain;
2252 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002253
David Woodhouse146922e2014-03-09 15:44:17 -07002254 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002255 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002256 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002257 return NULL;
Jiang Liu44bde612014-07-11 14:19:29 +08002258 domain->id = iommu_attach_domain(domain, iommu);
2259 if (domain->id < 0) {
Alex Williamson2fe9723d2011-03-04 14:52:30 -07002260 free_domain_mem(domain);
Alex Williamson579305f2014-07-03 09:51:43 -06002261 return NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002262 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002263 domain_attach_iommu(domain, iommu);
Alex Williamson579305f2014-07-03 09:51:43 -06002264 if (domain_init(domain, gaw)) {
2265 domain_exit(domain);
2266 return NULL;
2267 }
2268
2269 /* register PCI DMA alias device */
2270 if (dev_is_pci(dev)) {
2271 tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2272 dma_alias & 0xff, NULL, domain);
2273
2274 if (!tmp || tmp != domain) {
2275 domain_exit(domain);
2276 domain = tmp;
2277 }
2278
David Woodhouseb718cd32014-03-09 13:11:33 -07002279 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002280 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002281 }
2282
2283found_domain:
Alex Williamson579305f2014-07-03 09:51:43 -06002284 tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
2285
2286 if (!tmp || tmp != domain) {
2287 domain_exit(domain);
2288 domain = tmp;
2289 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002290
2291 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002292}
2293
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002294static int iommu_identity_mapping;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002295#define IDENTMAP_ALL 1
2296#define IDENTMAP_GFX 2
2297#define IDENTMAP_AZALIA 4
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002298
David Woodhouseb2132032009-06-26 18:50:28 +01002299static int iommu_domain_identity_map(struct dmar_domain *domain,
2300 unsigned long long start,
2301 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002302{
David Woodhousec5395d52009-06-28 16:35:56 +01002303 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2304 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002305
David Woodhousec5395d52009-06-28 16:35:56 +01002306 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2307 dma_to_mm_pfn(last_vpfn))) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002308 printk(KERN_ERR "IOMMU: reserve iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002309 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002310 }
2311
David Woodhousec5395d52009-06-28 16:35:56 +01002312 pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
2313 start, end, domain->id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002314 /*
2315 * RMRR range might have overlap with physical memory range,
2316 * clear it first
2317 */
David Woodhousec5395d52009-06-28 16:35:56 +01002318 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002319
David Woodhousec5395d52009-06-28 16:35:56 +01002320 return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
2321 last_vpfn - first_vpfn + 1,
David Woodhouse61df7442009-06-28 11:55:58 +01002322 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002323}
2324
David Woodhouse0b9d9752014-03-09 15:48:15 -07002325static int iommu_prepare_identity_map(struct device *dev,
David Woodhouseb2132032009-06-26 18:50:28 +01002326 unsigned long long start,
2327 unsigned long long end)
2328{
2329 struct dmar_domain *domain;
2330 int ret;
2331
David Woodhouse0b9d9752014-03-09 15:48:15 -07002332 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
David Woodhouseb2132032009-06-26 18:50:28 +01002333 if (!domain)
2334 return -ENOMEM;
2335
David Woodhouse19943b02009-08-04 16:19:20 +01002336 /* For _hardware_ passthrough, don't bother. But for software
2337 passthrough, we do it anyway -- it may indicate a memory
2338 range which is reserved in E820, so which didn't get set
2339 up to start with in si_domain */
2340 if (domain == si_domain && hw_pass_through) {
2341 printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002342 dev_name(dev), start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002343 return 0;
2344 }
2345
2346 printk(KERN_INFO
2347 "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002348 dev_name(dev), start, end);
David Woodhouse2ff729f2009-08-26 14:25:41 +01002349
David Woodhouse5595b522009-12-02 09:21:55 +00002350 if (end < start) {
2351 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2352 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2353 dmi_get_system_info(DMI_BIOS_VENDOR),
2354 dmi_get_system_info(DMI_BIOS_VERSION),
2355 dmi_get_system_info(DMI_PRODUCT_VERSION));
2356 ret = -EIO;
2357 goto error;
2358 }
2359
David Woodhouse2ff729f2009-08-26 14:25:41 +01002360 if (end >> agaw_to_width(domain->agaw)) {
2361 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2362 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2363 agaw_to_width(domain->agaw),
2364 dmi_get_system_info(DMI_BIOS_VENDOR),
2365 dmi_get_system_info(DMI_BIOS_VERSION),
2366 dmi_get_system_info(DMI_PRODUCT_VERSION));
2367 ret = -EIO;
2368 goto error;
2369 }
David Woodhouse19943b02009-08-04 16:19:20 +01002370
David Woodhouseb2132032009-06-26 18:50:28 +01002371 ret = iommu_domain_identity_map(domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002372 if (ret)
2373 goto error;
2374
2375 /* context entry init */
David Woodhouse0b9d9752014-03-09 15:48:15 -07002376 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
David Woodhouseb2132032009-06-26 18:50:28 +01002377 if (ret)
2378 goto error;
2379
2380 return 0;
2381
2382 error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002383 domain_exit(domain);
2384 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002385}
2386
2387static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002388 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002389{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002390 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002391 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002392 return iommu_prepare_identity_map(dev, rmrr->base_address,
2393 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002394}
2395
Suresh Siddhad3f13812011-08-23 17:05:25 -07002396#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002397static inline void iommu_prepare_isa(void)
2398{
2399 struct pci_dev *pdev;
2400 int ret;
2401
2402 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2403 if (!pdev)
2404 return;
2405
David Woodhousec7ab48d2009-06-26 19:10:36 +01002406 printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002407 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002408
2409 if (ret)
David Woodhousec7ab48d2009-06-26 19:10:36 +01002410 printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
2411 "floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002412
Yijing Wang9b27e822014-05-20 20:37:52 +08002413 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002414}
2415#else
2416static inline void iommu_prepare_isa(void)
2417{
2418 return;
2419}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002420#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002421
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002422static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002423
Matt Kraai071e1372009-08-23 22:30:22 -07002424static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002425{
2426 struct dmar_drhd_unit *drhd;
2427 struct intel_iommu *iommu;
David Woodhousec7ab48d2009-06-26 19:10:36 +01002428 int nid, ret = 0;
Jiang Liu44bde612014-07-11 14:19:29 +08002429 bool first = true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002430
Jiang Liuab8dfe22014-07-11 14:19:27 +08002431 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002432 if (!si_domain)
2433 return -EFAULT;
2434
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002435 for_each_active_iommu(iommu, drhd) {
2436 ret = iommu_attach_domain(si_domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08002437 if (ret < 0) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002438 domain_exit(si_domain);
2439 return -EFAULT;
Jiang Liu44bde612014-07-11 14:19:29 +08002440 } else if (first) {
2441 si_domain->id = ret;
2442 first = false;
2443 } else if (si_domain->id != ret) {
2444 domain_exit(si_domain);
2445 return -EFAULT;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002446 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002447 domain_attach_iommu(si_domain, iommu);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002448 }
2449
2450 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2451 domain_exit(si_domain);
2452 return -EFAULT;
2453 }
2454
Jiang Liu9544c002014-01-06 14:18:13 +08002455 pr_debug("IOMMU: identity mapping domain is domain %d\n",
2456 si_domain->id);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002457
David Woodhouse19943b02009-08-04 16:19:20 +01002458 if (hw)
2459 return 0;
2460
David Woodhousec7ab48d2009-06-26 19:10:36 +01002461 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002462 unsigned long start_pfn, end_pfn;
2463 int i;
2464
2465 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2466 ret = iommu_domain_identity_map(si_domain,
2467 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2468 if (ret)
2469 return ret;
2470 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002471 }
2472
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002473 return 0;
2474}
2475
David Woodhouse9b226622014-03-09 14:03:28 -07002476static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002477{
2478 struct device_domain_info *info;
2479
2480 if (likely(!iommu_identity_mapping))
2481 return 0;
2482
David Woodhouse9b226622014-03-09 14:03:28 -07002483 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002484 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2485 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002486
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002487 return 0;
2488}
2489
2490static int domain_add_dev_info(struct dmar_domain *domain,
David Woodhouse5913c9b2014-03-09 16:27:31 -07002491 struct device *dev, int translation)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002492{
David Woodhouse0ac72662014-03-09 13:19:22 -07002493 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002494 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002495 u8 bus, devfn;
David Woodhouse5fe60f42009-08-09 10:53:41 +01002496 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002497
David Woodhouse5913c9b2014-03-09 16:27:31 -07002498 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002499 if (!iommu)
2500 return -ENODEV;
2501
David Woodhouse5913c9b2014-03-09 16:27:31 -07002502 ndomain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002503 if (ndomain != domain)
2504 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002505
David Woodhouse5913c9b2014-03-09 16:27:31 -07002506 ret = domain_context_mapping(domain, dev, translation);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002507 if (ret) {
David Woodhouse5913c9b2014-03-09 16:27:31 -07002508 domain_remove_one_dev_info(domain, dev);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002509 return ret;
2510 }
2511
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002512 return 0;
2513}
2514
David Woodhouse0b9d9752014-03-09 15:48:15 -07002515static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002516{
2517 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002518 struct device *tmp;
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002519 int i;
2520
Jiang Liu0e242612014-02-19 14:07:34 +08002521 rcu_read_lock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002522 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002523 /*
2524 * Return TRUE if this RMRR contains the device that
2525 * is passed in.
2526 */
2527 for_each_active_dev_scope(rmrr->devices,
2528 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002529 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002530 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002531 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002532 }
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002533 }
Jiang Liu0e242612014-02-19 14:07:34 +08002534 rcu_read_unlock();
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002535 return false;
2536}
2537
David Woodhouse3bdb2592014-03-09 16:03:08 -07002538static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002539{
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002540
David Woodhouse3bdb2592014-03-09 16:03:08 -07002541 if (dev_is_pci(dev)) {
2542 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002543
David Woodhouse3bdb2592014-03-09 16:03:08 -07002544 /*
2545 * We want to prevent any device associated with an RMRR from
2546 * getting placed into the SI Domain. This is done because
2547 * problems exist when devices are moved in and out of domains
2548 * and their respective RMRR info is lost. We exempt USB devices
2549 * from this process due to their usage of RMRRs that are known
2550 * to not be needed after BIOS hand-off to OS.
2551 */
2552 if (device_has_rmrr(dev) &&
2553 (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
2554 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002555
David Woodhouse3bdb2592014-03-09 16:03:08 -07002556 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2557 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002558
David Woodhouse3bdb2592014-03-09 16:03:08 -07002559 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2560 return 1;
2561
2562 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2563 return 0;
2564
2565 /*
2566 * We want to start off with all devices in the 1:1 domain, and
2567 * take them out later if we find they can't access all of memory.
2568 *
2569 * However, we can't do this for PCI devices behind bridges,
2570 * because all PCI devices behind the same bridge will end up
2571 * with the same source-id on their transactions.
2572 *
2573 * Practically speaking, we can't change things around for these
2574 * devices at run-time, because we can't be sure there'll be no
2575 * DMA transactions in flight for any of their siblings.
2576 *
2577 * So PCI devices (unless they're on the root bus) as well as
2578 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2579 * the 1:1 domain, just in _case_ one of their siblings turns out
2580 * not to be able to map all of memory.
2581 */
2582 if (!pci_is_pcie(pdev)) {
2583 if (!pci_is_root_bus(pdev->bus))
2584 return 0;
2585 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2586 return 0;
2587 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2588 return 0;
2589 } else {
2590 if (device_has_rmrr(dev))
2591 return 0;
2592 }
David Woodhouse6941af22009-07-04 18:24:27 +01002593
David Woodhouse3dfc8132009-07-04 19:11:08 +01002594 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002595 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002596 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002597 * take them out of the 1:1 domain later.
2598 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002599 if (!startup) {
2600 /*
2601 * If the device's dma_mask is less than the system's memory
2602 * size then this is not a candidate for identity mapping.
2603 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002604 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002605
David Woodhouse3bdb2592014-03-09 16:03:08 -07002606 if (dev->coherent_dma_mask &&
2607 dev->coherent_dma_mask < dma_mask)
2608 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002609
David Woodhouse3bdb2592014-03-09 16:03:08 -07002610 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05002611 }
David Woodhouse6941af22009-07-04 18:24:27 +01002612
2613 return 1;
2614}
2615
David Woodhousecf04eee2014-03-21 16:49:04 +00002616static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
2617{
2618 int ret;
2619
2620 if (!iommu_should_identity_map(dev, 1))
2621 return 0;
2622
2623 ret = domain_add_dev_info(si_domain, dev,
2624 hw ? CONTEXT_TT_PASS_THROUGH :
2625 CONTEXT_TT_MULTI_LEVEL);
2626 if (!ret)
2627 pr_info("IOMMU: %s identity mapping for device %s\n",
2628 hw ? "hardware" : "software", dev_name(dev));
2629 else if (ret == -ENODEV)
2630 /* device not associated with an iommu */
2631 ret = 0;
2632
2633 return ret;
2634}
2635
2636
Matt Kraai071e1372009-08-23 22:30:22 -07002637static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002638{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002639 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00002640 struct dmar_drhd_unit *drhd;
2641 struct intel_iommu *iommu;
2642 struct device *dev;
2643 int i;
2644 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002645
David Woodhouse19943b02009-08-04 16:19:20 +01002646 ret = si_domain_init(hw);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002647 if (ret)
2648 return -EFAULT;
2649
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002650 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00002651 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
2652 if (ret)
2653 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002654 }
2655
David Woodhousecf04eee2014-03-21 16:49:04 +00002656 for_each_active_iommu(iommu, drhd)
2657 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
2658 struct acpi_device_physical_node *pn;
2659 struct acpi_device *adev;
2660
2661 if (dev->bus != &acpi_bus_type)
2662 continue;
2663
2664 adev= to_acpi_device(dev);
2665 mutex_lock(&adev->physical_node_lock);
2666 list_for_each_entry(pn, &adev->physical_node_list, node) {
2667 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
2668 if (ret)
2669 break;
2670 }
2671 mutex_unlock(&adev->physical_node_lock);
2672 if (ret)
2673 return ret;
2674 }
2675
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002676 return 0;
2677}
2678
Joseph Cihulab7792602011-05-03 00:08:37 -07002679static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002680{
2681 struct dmar_drhd_unit *drhd;
2682 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002683 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002684 struct intel_iommu *iommu;
Suresh Siddha9d783ba2009-03-16 17:04:55 -07002685 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002686
2687 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002688 * for each drhd
2689 * allocate root
2690 * initialize and program root entry to not present
2691 * endfor
2692 */
2693 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08002694 /*
2695 * lock not needed as this is only incremented in the single
2696 * threaded kernel __init code path all other access are read
2697 * only
2698 */
Mike Travis1b198bb2012-03-05 15:05:16 -08002699 if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) {
2700 g_num_of_iommus++;
2701 continue;
2702 }
2703 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
2704 IOMMU_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08002705 }
2706
Weidong Hand9630fe2008-12-08 11:06:32 +08002707 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
2708 GFP_KERNEL);
2709 if (!g_iommus) {
2710 printk(KERN_ERR "Allocating global iommu array failed\n");
2711 ret = -ENOMEM;
2712 goto error;
2713 }
2714
mark gross80b20dd2008-04-18 13:53:58 -07002715 deferred_flush = kzalloc(g_num_of_iommus *
2716 sizeof(struct deferred_flush_tables), GFP_KERNEL);
2717 if (!deferred_flush) {
mark gross5e0d2a62008-03-04 15:22:08 -08002718 ret = -ENOMEM;
Jiang Liu989d51f2014-02-19 14:07:21 +08002719 goto free_g_iommus;
mark gross5e0d2a62008-03-04 15:22:08 -08002720 }
2721
Jiang Liu7c919772014-01-06 14:18:18 +08002722 for_each_active_iommu(iommu, drhd) {
Weidong Hand9630fe2008-12-08 11:06:32 +08002723 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002724
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002725 ret = iommu_init_domains(iommu);
2726 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002727 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002728
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002729 /*
2730 * TBD:
2731 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002732 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002733 */
2734 ret = iommu_alloc_root_entry(iommu);
2735 if (ret) {
2736 printk(KERN_ERR "IOMMU: allocate root entry failed\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08002737 goto free_iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002738 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002739 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01002740 hw_pass_through = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002741 }
2742
Suresh Siddha1531a6a2009-03-16 17:04:57 -07002743 /*
2744 * Start from the sane iommu hardware state.
2745 */
Jiang Liu7c919772014-01-06 14:18:18 +08002746 for_each_active_iommu(iommu, drhd) {
Suresh Siddha1531a6a2009-03-16 17:04:57 -07002747 /*
2748 * If the queued invalidation is already initialized by us
2749 * (for example, while enabling interrupt-remapping) then
2750 * we got the things already rolling from a sane state.
2751 */
2752 if (iommu->qi)
2753 continue;
2754
2755 /*
2756 * Clear any previous faults.
2757 */
2758 dmar_fault(-1, iommu);
2759 /*
2760 * Disable queued invalidation if supported and already enabled
2761 * before OS handover.
2762 */
2763 dmar_disable_qi(iommu);
2764 }
2765
Jiang Liu7c919772014-01-06 14:18:18 +08002766 for_each_active_iommu(iommu, drhd) {
Youquan Songa77b67d2008-10-16 16:31:56 -07002767 if (dmar_enable_qi(iommu)) {
2768 /*
2769 * Queued Invalidate not enabled, use Register Based
2770 * Invalidate
2771 */
2772 iommu->flush.flush_context = __iommu_flush_context;
2773 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Yinghai Lu680a7522010-04-08 19:58:23 +01002774 printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based "
FUJITA Tomonorib4e0f9e2008-11-19 13:53:42 +09002775 "invalidation\n",
Yinghai Lu680a7522010-04-08 19:58:23 +01002776 iommu->seq_id,
FUJITA Tomonorib4e0f9e2008-11-19 13:53:42 +09002777 (unsigned long long)drhd->reg_base_addr);
Youquan Songa77b67d2008-10-16 16:31:56 -07002778 } else {
2779 iommu->flush.flush_context = qi_flush_context;
2780 iommu->flush.flush_iotlb = qi_flush_iotlb;
Yinghai Lu680a7522010-04-08 19:58:23 +01002781 printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued "
FUJITA Tomonorib4e0f9e2008-11-19 13:53:42 +09002782 "invalidation\n",
Yinghai Lu680a7522010-04-08 19:58:23 +01002783 iommu->seq_id,
FUJITA Tomonorib4e0f9e2008-11-19 13:53:42 +09002784 (unsigned long long)drhd->reg_base_addr);
Youquan Songa77b67d2008-10-16 16:31:56 -07002785 }
2786 }
2787
David Woodhouse19943b02009-08-04 16:19:20 +01002788 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07002789 iommu_identity_mapping |= IDENTMAP_ALL;
2790
Suresh Siddhad3f13812011-08-23 17:05:25 -07002791#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07002792 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01002793#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07002794
2795 check_tylersburg_isoch();
2796
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002797 /*
2798 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002799 * identity mappings for rmrr, gfx, and isa and may fall back to static
2800 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002801 */
David Woodhouse19943b02009-08-04 16:19:20 +01002802 if (iommu_identity_mapping) {
2803 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
2804 if (ret) {
2805 printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08002806 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002807 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002808 }
David Woodhouse19943b02009-08-04 16:19:20 +01002809 /*
2810 * For each rmrr
2811 * for each dev attached to rmrr
2812 * do
2813 * locate drhd for dev, alloc domain for dev
2814 * allocate free domain
2815 * allocate page table entries for rmrr
2816 * if context not allocated for bus
2817 * allocate and init context
2818 * set present in root table for this bus
2819 * init context with domain, translation etc
2820 * endfor
2821 * endfor
2822 */
2823 printk(KERN_INFO "IOMMU: Setting RMRR:\n");
2824 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002825 /* some BIOS lists non-exist devices in DMAR table. */
2826 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00002827 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07002828 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01002829 if (ret)
2830 printk(KERN_ERR
2831 "IOMMU: mapping reserved region failed\n");
2832 }
2833 }
2834
2835 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002836
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002837 /*
2838 * for each drhd
2839 * enable fault log
2840 * global invalidate context cache
2841 * global invalidate iotlb
2842 * enable translation
2843 */
Jiang Liu7c919772014-01-06 14:18:18 +08002844 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07002845 if (drhd->ignored) {
2846 /*
2847 * we always have to disable PMRs or DMA may fail on
2848 * this device
2849 */
2850 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08002851 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002852 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07002853 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002854
2855 iommu_flush_write_buffer(iommu);
2856
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002857 ret = dmar_set_interrupt(iommu);
2858 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002859 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002860
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002861 iommu_set_root_entry(iommu);
2862
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002863 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002864 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Jiang Liu2a41cce2014-07-11 14:19:33 +08002865 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07002866 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002867 }
2868
2869 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08002870
2871free_iommu:
Jiang Liu7c919772014-01-06 14:18:18 +08002872 for_each_active_iommu(iommu, drhd)
Jiang Liua868e6b2014-01-06 14:18:20 +08002873 free_dmar_iommu(iommu);
Jiang Liu9bdc5312014-01-06 14:18:27 +08002874 kfree(deferred_flush);
Jiang Liu989d51f2014-02-19 14:07:21 +08002875free_g_iommus:
Weidong Hand9630fe2008-12-08 11:06:32 +08002876 kfree(g_iommus);
Jiang Liu989d51f2014-02-19 14:07:21 +08002877error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002878 return ret;
2879}
2880
David Woodhouse5a5e02a2009-07-04 09:35:44 +01002881/* This takes a number of _MM_ pages, not VTD pages */
David Woodhouse875764d2009-06-28 21:20:51 +01002882static struct iova *intel_alloc_iova(struct device *dev,
2883 struct dmar_domain *domain,
2884 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002885{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002886 struct iova *iova = NULL;
2887
David Woodhouse875764d2009-06-28 21:20:51 +01002888 /* Restrict dma_mask to the width that the iommu can handle */
2889 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
2890
2891 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002892 /*
2893 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07002894 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08002895 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002896 */
David Woodhouse875764d2009-06-28 21:20:51 +01002897 iova = alloc_iova(&domain->iovad, nrpages,
2898 IOVA_PFN(DMA_BIT_MASK(32)), 1);
2899 if (iova)
2900 return iova;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002901 }
David Woodhouse875764d2009-06-28 21:20:51 +01002902 iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
2903 if (unlikely(!iova)) {
2904 printk(KERN_ERR "Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07002905 nrpages, dev_name(dev));
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002906 return NULL;
2907 }
2908
2909 return iova;
2910}
2911
David Woodhoused4b709f2014-03-09 16:07:40 -07002912static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002913{
2914 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002915 int ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002916
David Woodhoused4b709f2014-03-09 16:07:40 -07002917 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002918 if (!domain) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002919 printk(KERN_ERR "Allocating domain for %s failed",
2920 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002921 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002922 }
2923
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002924 /* make sure context mapping is ok */
David Woodhoused4b709f2014-03-09 16:07:40 -07002925 if (unlikely(!domain_context_mapped(dev))) {
2926 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002927 if (ret) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002928 printk(KERN_ERR "Domain context map for %s failed",
2929 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002930 return NULL;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002931 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002932 }
2933
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002934 return domain;
2935}
2936
David Woodhoused4b709f2014-03-09 16:07:40 -07002937static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
David Woodhouse147202a2009-07-07 19:43:20 +01002938{
2939 struct device_domain_info *info;
2940
2941 /* No lock here, assumes no domain exit in normal case */
David Woodhoused4b709f2014-03-09 16:07:40 -07002942 info = dev->archdata.iommu;
David Woodhouse147202a2009-07-07 19:43:20 +01002943 if (likely(info))
2944 return info->domain;
2945
2946 return __get_valid_domain_for_dev(dev);
2947}
2948
David Woodhouse3d891942014-03-06 15:59:26 +00002949static int iommu_dummy(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002950{
David Woodhouse3d891942014-03-06 15:59:26 +00002951 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002952}
2953
David Woodhouseecb509e2014-03-09 16:29:55 -07002954/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01002955static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002956{
2957 int found;
2958
David Woodhouse3d891942014-03-06 15:59:26 +00002959 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002960 return 1;
2961
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002962 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002963 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002964
David Woodhouse9b226622014-03-09 14:03:28 -07002965 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002966 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07002967 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002968 return 1;
2969 else {
2970 /*
2971 * 32 bit DMA is removed from si_domain and fall back
2972 * to non-identity mapping.
2973 */
David Woodhousebf9c9ed2014-03-09 16:19:13 -07002974 domain_remove_one_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002975 printk(KERN_INFO "32bit %s uses non-identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07002976 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002977 return 0;
2978 }
2979 } else {
2980 /*
2981 * In case of a detached 64 bit DMA device from vm, the device
2982 * is put into si_domain for identity mapping.
2983 */
David Woodhouseecb509e2014-03-09 16:29:55 -07002984 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002985 int ret;
David Woodhouse5913c9b2014-03-09 16:27:31 -07002986 ret = domain_add_dev_info(si_domain, dev,
David Woodhouse5fe60f42009-08-09 10:53:41 +01002987 hw_pass_through ?
2988 CONTEXT_TT_PASS_THROUGH :
2989 CONTEXT_TT_MULTI_LEVEL);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002990 if (!ret) {
2991 printk(KERN_INFO "64bit %s uses identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07002992 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002993 return 1;
2994 }
2995 }
2996 }
2997
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002998 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002999}
3000
David Woodhouse5040a912014-03-09 16:14:00 -07003001static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003002 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003003{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003004 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003005 phys_addr_t start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003006 struct iova *iova;
3007 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003008 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003009 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003010 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003011
3012 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003013
David Woodhouse5040a912014-03-09 16:14:00 -07003014 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003015 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003016
David Woodhouse5040a912014-03-09 16:14:00 -07003017 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003018 if (!domain)
3019 return 0;
3020
Weidong Han8c11e792008-12-08 15:29:22 +08003021 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003022 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003023
David Woodhouse5040a912014-03-09 16:14:00 -07003024 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003025 if (!iova)
3026 goto error;
3027
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003028 /*
3029 * Check if DMAR supports zero-length reads on write only
3030 * mappings..
3031 */
3032 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003033 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003034 prot |= DMA_PTE_READ;
3035 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3036 prot |= DMA_PTE_WRITE;
3037 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003038 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003039 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003040 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003041 * is not a big problem
3042 */
David Woodhouse0ab36de2009-06-28 14:01:43 +01003043 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003044 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003045 if (ret)
3046 goto error;
3047
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003048 /* it's a non-present to present mapping. Only flush if caching mode */
3049 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003050 iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003051 else
Weidong Han8c11e792008-12-08 15:29:22 +08003052 iommu_flush_write_buffer(iommu);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003053
David Woodhouse03d6a242009-06-28 15:33:46 +01003054 start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
3055 start_paddr += paddr & ~PAGE_MASK;
3056 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003057
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003058error:
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003059 if (iova)
3060 __free_iova(&domain->iovad, iova);
David Woodhouse4cf2e752009-02-11 17:23:43 +00003061 printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003062 dev_name(dev), size, (unsigned long long)paddr, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003063 return 0;
3064}
3065
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003066static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3067 unsigned long offset, size_t size,
3068 enum dma_data_direction dir,
3069 struct dma_attrs *attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003070{
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003071 return __intel_map_single(dev, page_to_phys(page) + offset, size,
David Woodhouse46333e32014-03-10 20:01:21 -07003072 dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003073}
3074
mark gross5e0d2a62008-03-04 15:22:08 -08003075static void flush_unmaps(void)
3076{
mark gross80b20dd2008-04-18 13:53:58 -07003077 int i, j;
mark gross5e0d2a62008-03-04 15:22:08 -08003078
mark gross5e0d2a62008-03-04 15:22:08 -08003079 timer_on = 0;
3080
3081 /* just flush them all */
3082 for (i = 0; i < g_num_of_iommus; i++) {
Weidong Hana2bb8452008-12-08 11:24:12 +08003083 struct intel_iommu *iommu = g_iommus[i];
3084 if (!iommu)
3085 continue;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003086
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003087 if (!deferred_flush[i].next)
3088 continue;
3089
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003090 /* In caching mode, global flushes turn emulation expensive */
3091 if (!cap_caching_mode(iommu->cap))
3092 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
Yu Zhao93a23a72009-05-18 13:51:37 +08003093 DMA_TLB_GLOBAL_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003094 for (j = 0; j < deferred_flush[i].next; j++) {
Yu Zhao93a23a72009-05-18 13:51:37 +08003095 unsigned long mask;
3096 struct iova *iova = deferred_flush[i].iova[j];
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003097 struct dmar_domain *domain = deferred_flush[i].domain[j];
Yu Zhao93a23a72009-05-18 13:51:37 +08003098
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003099 /* On real hardware multiple invalidations are expensive */
3100 if (cap_caching_mode(iommu->cap))
3101 iommu_flush_iotlb_psi(iommu, domain->id,
David Woodhouseea8ea462014-03-05 17:09:32 +00003102 iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1,
3103 !deferred_flush[i].freelist[j], 0);
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003104 else {
3105 mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
3106 iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
3107 (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
3108 }
Yu Zhao93a23a72009-05-18 13:51:37 +08003109 __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003110 if (deferred_flush[i].freelist[j])
3111 dma_free_pagelist(deferred_flush[i].freelist[j]);
mark gross80b20dd2008-04-18 13:53:58 -07003112 }
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003113 deferred_flush[i].next = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003114 }
3115
mark gross5e0d2a62008-03-04 15:22:08 -08003116 list_size = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003117}
3118
3119static void flush_unmaps_timeout(unsigned long data)
3120{
mark gross80b20dd2008-04-18 13:53:58 -07003121 unsigned long flags;
3122
3123 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003124 flush_unmaps();
mark gross80b20dd2008-04-18 13:53:58 -07003125 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003126}
3127
David Woodhouseea8ea462014-03-05 17:09:32 +00003128static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist)
mark gross5e0d2a62008-03-04 15:22:08 -08003129{
3130 unsigned long flags;
mark gross80b20dd2008-04-18 13:53:58 -07003131 int next, iommu_id;
Weidong Han8c11e792008-12-08 15:29:22 +08003132 struct intel_iommu *iommu;
mark gross5e0d2a62008-03-04 15:22:08 -08003133
3134 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross80b20dd2008-04-18 13:53:58 -07003135 if (list_size == HIGH_WATER_MARK)
3136 flush_unmaps();
3137
Weidong Han8c11e792008-12-08 15:29:22 +08003138 iommu = domain_get_iommu(dom);
3139 iommu_id = iommu->seq_id;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003140
mark gross80b20dd2008-04-18 13:53:58 -07003141 next = deferred_flush[iommu_id].next;
3142 deferred_flush[iommu_id].domain[next] = dom;
3143 deferred_flush[iommu_id].iova[next] = iova;
David Woodhouseea8ea462014-03-05 17:09:32 +00003144 deferred_flush[iommu_id].freelist[next] = freelist;
mark gross80b20dd2008-04-18 13:53:58 -07003145 deferred_flush[iommu_id].next++;
mark gross5e0d2a62008-03-04 15:22:08 -08003146
3147 if (!timer_on) {
3148 mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
3149 timer_on = 1;
3150 }
3151 list_size++;
3152 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
3153}
3154
Jiang Liud41a4ad2014-07-11 14:19:34 +08003155static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003156{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003157 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003158 unsigned long start_pfn, last_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003159 struct iova *iova;
Weidong Han8c11e792008-12-08 15:29:22 +08003160 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003161 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003162
David Woodhouse73676832009-07-04 14:08:36 +01003163 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003164 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003165
David Woodhouse1525a292014-03-06 16:19:30 +00003166 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003167 BUG_ON(!domain);
3168
Weidong Han8c11e792008-12-08 15:29:22 +08003169 iommu = domain_get_iommu(domain);
3170
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003171 iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
David Woodhouse85b98272009-07-01 19:27:53 +01003172 if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
3173 (unsigned long long)dev_addr))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003174 return;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003175
David Woodhoused794dc92009-06-28 00:27:49 +01003176 start_pfn = mm_to_dma_pfn(iova->pfn_lo);
3177 last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003178
David Woodhoused794dc92009-06-28 00:27:49 +01003179 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003180 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003181
David Woodhouseea8ea462014-03-05 17:09:32 +00003182 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003183
mark gross5e0d2a62008-03-04 15:22:08 -08003184 if (intel_iommu_strict) {
David Woodhouse03d6a242009-06-28 15:33:46 +01003185 iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
David Woodhouseea8ea462014-03-05 17:09:32 +00003186 last_pfn - start_pfn + 1, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003187 /* free iova */
3188 __free_iova(&domain->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003189 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003190 } else {
David Woodhouseea8ea462014-03-05 17:09:32 +00003191 add_unmap(domain, iova, freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003192 /*
3193 * queue up the release of the unmap to save the 1/6th of the
3194 * cpu used up by the iotlb flush operation...
3195 */
mark gross5e0d2a62008-03-04 15:22:08 -08003196 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003197}
3198
Jiang Liud41a4ad2014-07-11 14:19:34 +08003199static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3200 size_t size, enum dma_data_direction dir,
3201 struct dma_attrs *attrs)
3202{
3203 intel_unmap(dev, dev_addr);
3204}
3205
David Woodhouse5040a912014-03-09 16:14:00 -07003206static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003207 dma_addr_t *dma_handle, gfp_t flags,
3208 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003209{
Akinobu Mita36746432014-06-04 16:06:51 -07003210 struct page *page = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003211 int order;
3212
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003213 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003214 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003215
David Woodhouse5040a912014-03-09 16:14:00 -07003216 if (!iommu_no_mapping(dev))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003217 flags &= ~(GFP_DMA | GFP_DMA32);
David Woodhouse5040a912014-03-09 16:14:00 -07003218 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3219 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003220 flags |= GFP_DMA;
3221 else
3222 flags |= GFP_DMA32;
3223 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003224
Akinobu Mita36746432014-06-04 16:06:51 -07003225 if (flags & __GFP_WAIT) {
3226 unsigned int count = size >> PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003227
Akinobu Mita36746432014-06-04 16:06:51 -07003228 page = dma_alloc_from_contiguous(dev, count, order);
3229 if (page && iommu_no_mapping(dev) &&
3230 page_to_phys(page) + size > dev->coherent_dma_mask) {
3231 dma_release_from_contiguous(dev, page, count);
3232 page = NULL;
3233 }
3234 }
3235
3236 if (!page)
3237 page = alloc_pages(flags, order);
3238 if (!page)
3239 return NULL;
3240 memset(page_address(page), 0, size);
3241
3242 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003243 DMA_BIDIRECTIONAL,
David Woodhouse5040a912014-03-09 16:14:00 -07003244 dev->coherent_dma_mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003245 if (*dma_handle)
Akinobu Mita36746432014-06-04 16:06:51 -07003246 return page_address(page);
3247 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3248 __free_pages(page, order);
3249
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003250 return NULL;
3251}
3252
David Woodhouse5040a912014-03-09 16:14:00 -07003253static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003254 dma_addr_t dma_handle, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003255{
3256 int order;
Akinobu Mita36746432014-06-04 16:06:51 -07003257 struct page *page = virt_to_page(vaddr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003258
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003259 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003260 order = get_order(size);
3261
Jiang Liud41a4ad2014-07-11 14:19:34 +08003262 intel_unmap(dev, dma_handle);
Akinobu Mita36746432014-06-04 16:06:51 -07003263 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3264 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003265}
3266
David Woodhouse5040a912014-03-09 16:14:00 -07003267static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003268 int nelems, enum dma_data_direction dir,
3269 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003270{
Jiang Liud41a4ad2014-07-11 14:19:34 +08003271 intel_unmap(dev, sglist[0].dma_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003272}
3273
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003274static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003275 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003276{
3277 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003278 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003279
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003280 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003281 BUG_ON(!sg_page(sg));
David Woodhouse4cf2e752009-02-11 17:23:43 +00003282 sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003283 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003284 }
3285 return nelems;
3286}
3287
David Woodhouse5040a912014-03-09 16:14:00 -07003288static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003289 enum dma_data_direction dir, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003290{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003291 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003292 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003293 size_t size = 0;
3294 int prot = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003295 struct iova *iova = NULL;
3296 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003297 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003298 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003299 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003300
3301 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003302 if (iommu_no_mapping(dev))
3303 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003304
David Woodhouse5040a912014-03-09 16:14:00 -07003305 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003306 if (!domain)
3307 return 0;
3308
Weidong Han8c11e792008-12-08 15:29:22 +08003309 iommu = domain_get_iommu(domain);
3310
David Woodhouseb536d242009-06-28 14:49:31 +01003311 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003312 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003313
David Woodhouse5040a912014-03-09 16:14:00 -07003314 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
3315 *dev->dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003316 if (!iova) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003317 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003318 return 0;
3319 }
3320
3321 /*
3322 * Check if DMAR supports zero-length reads on write only
3323 * mappings..
3324 */
3325 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003326 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003327 prot |= DMA_PTE_READ;
3328 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3329 prot |= DMA_PTE_WRITE;
3330
David Woodhouseb536d242009-06-28 14:49:31 +01003331 start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
David Woodhousee1605492009-06-29 11:17:38 +01003332
Fenghua Yuf5329592009-08-04 15:09:37 -07003333 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003334 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003335 dma_pte_free_pagetable(domain, start_vpfn,
3336 start_vpfn + size - 1);
David Woodhousee1605492009-06-29 11:17:38 +01003337 __free_iova(&domain->iovad, iova);
3338 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003339 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003340
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003341 /* it's a non-present to present mapping. Only flush if caching mode */
3342 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003343 iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003344 else
Weidong Han8c11e792008-12-08 15:29:22 +08003345 iommu_flush_write_buffer(iommu);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003346
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003347 return nelems;
3348}
3349
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003350static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
3351{
3352 return !dma_addr;
3353}
3354
FUJITA Tomonori160c1d82009-01-05 23:59:02 +09003355struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003356 .alloc = intel_alloc_coherent,
3357 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003358 .map_sg = intel_map_sg,
3359 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003360 .map_page = intel_map_page,
3361 .unmap_page = intel_unmap_page,
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003362 .mapping_error = intel_mapping_error,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003363};
3364
3365static inline int iommu_domain_cache_init(void)
3366{
3367 int ret = 0;
3368
3369 iommu_domain_cache = kmem_cache_create("iommu_domain",
3370 sizeof(struct dmar_domain),
3371 0,
3372 SLAB_HWCACHE_ALIGN,
3373
3374 NULL);
3375 if (!iommu_domain_cache) {
3376 printk(KERN_ERR "Couldn't create iommu_domain cache\n");
3377 ret = -ENOMEM;
3378 }
3379
3380 return ret;
3381}
3382
3383static inline int iommu_devinfo_cache_init(void)
3384{
3385 int ret = 0;
3386
3387 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3388 sizeof(struct device_domain_info),
3389 0,
3390 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003391 NULL);
3392 if (!iommu_devinfo_cache) {
3393 printk(KERN_ERR "Couldn't create devinfo cache\n");
3394 ret = -ENOMEM;
3395 }
3396
3397 return ret;
3398}
3399
3400static inline int iommu_iova_cache_init(void)
3401{
3402 int ret = 0;
3403
3404 iommu_iova_cache = kmem_cache_create("iommu_iova",
3405 sizeof(struct iova),
3406 0,
3407 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003408 NULL);
3409 if (!iommu_iova_cache) {
3410 printk(KERN_ERR "Couldn't create iova cache\n");
3411 ret = -ENOMEM;
3412 }
3413
3414 return ret;
3415}
3416
3417static int __init iommu_init_mempool(void)
3418{
3419 int ret;
3420 ret = iommu_iova_cache_init();
3421 if (ret)
3422 return ret;
3423
3424 ret = iommu_domain_cache_init();
3425 if (ret)
3426 goto domain_error;
3427
3428 ret = iommu_devinfo_cache_init();
3429 if (!ret)
3430 return ret;
3431
3432 kmem_cache_destroy(iommu_domain_cache);
3433domain_error:
3434 kmem_cache_destroy(iommu_iova_cache);
3435
3436 return -ENOMEM;
3437}
3438
3439static void __init iommu_exit_mempool(void)
3440{
3441 kmem_cache_destroy(iommu_devinfo_cache);
3442 kmem_cache_destroy(iommu_domain_cache);
3443 kmem_cache_destroy(iommu_iova_cache);
3444
3445}
3446
Dan Williams556ab452010-07-23 15:47:56 -07003447static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3448{
3449 struct dmar_drhd_unit *drhd;
3450 u32 vtbar;
3451 int rc;
3452
3453 /* We know that this device on this chipset has its own IOMMU.
3454 * If we find it under a different IOMMU, then the BIOS is lying
3455 * to us. Hope that the IOMMU for this device is actually
3456 * disabled, and it needs no translation...
3457 */
3458 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3459 if (rc) {
3460 /* "can't" happen */
3461 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3462 return;
3463 }
3464 vtbar &= 0xffff0000;
3465
3466 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3467 drhd = dmar_find_matched_drhd_unit(pdev);
3468 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3469 TAINT_FIRMWARE_WORKAROUND,
3470 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3471 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3472}
3473DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3474
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003475static void __init init_no_remapping_devices(void)
3476{
3477 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003478 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003479 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003480
3481 for_each_drhd_unit(drhd) {
3482 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003483 for_each_active_dev_scope(drhd->devices,
3484 drhd->devices_cnt, i, dev)
3485 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003486 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003487 if (i == drhd->devices_cnt)
3488 drhd->ignored = 1;
3489 }
3490 }
3491
Jiang Liu7c919772014-01-06 14:18:18 +08003492 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003493 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003494 continue;
3495
Jiang Liub683b232014-02-19 14:07:32 +08003496 for_each_active_dev_scope(drhd->devices,
3497 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003498 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003499 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003500 if (i < drhd->devices_cnt)
3501 continue;
3502
David Woodhousec0771df2011-10-14 20:59:46 +01003503 /* This IOMMU has *only* gfx devices. Either bypass it or
3504 set the gfx_mapped flag, as appropriate */
3505 if (dmar_map_gfx) {
3506 intel_iommu_gfx_mapped = 1;
3507 } else {
3508 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003509 for_each_active_dev_scope(drhd->devices,
3510 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003511 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003512 }
3513 }
3514}
3515
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003516#ifdef CONFIG_SUSPEND
3517static int init_iommu_hw(void)
3518{
3519 struct dmar_drhd_unit *drhd;
3520 struct intel_iommu *iommu = NULL;
3521
3522 for_each_active_iommu(iommu, drhd)
3523 if (iommu->qi)
3524 dmar_reenable_qi(iommu);
3525
Joseph Cihulab7792602011-05-03 00:08:37 -07003526 for_each_iommu(iommu, drhd) {
3527 if (drhd->ignored) {
3528 /*
3529 * we always have to disable PMRs or DMA may fail on
3530 * this device
3531 */
3532 if (force_on)
3533 iommu_disable_protect_mem_regions(iommu);
3534 continue;
3535 }
3536
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003537 iommu_flush_write_buffer(iommu);
3538
3539 iommu_set_root_entry(iommu);
3540
3541 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003542 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003543 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3544 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003545 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003546 }
3547
3548 return 0;
3549}
3550
3551static void iommu_flush_all(void)
3552{
3553 struct dmar_drhd_unit *drhd;
3554 struct intel_iommu *iommu;
3555
3556 for_each_active_iommu(iommu, drhd) {
3557 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003558 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003559 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003560 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003561 }
3562}
3563
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003564static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003565{
3566 struct dmar_drhd_unit *drhd;
3567 struct intel_iommu *iommu = NULL;
3568 unsigned long flag;
3569
3570 for_each_active_iommu(iommu, drhd) {
3571 iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
3572 GFP_ATOMIC);
3573 if (!iommu->iommu_state)
3574 goto nomem;
3575 }
3576
3577 iommu_flush_all();
3578
3579 for_each_active_iommu(iommu, drhd) {
3580 iommu_disable_translation(iommu);
3581
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003582 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003583
3584 iommu->iommu_state[SR_DMAR_FECTL_REG] =
3585 readl(iommu->reg + DMAR_FECTL_REG);
3586 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
3587 readl(iommu->reg + DMAR_FEDATA_REG);
3588 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
3589 readl(iommu->reg + DMAR_FEADDR_REG);
3590 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
3591 readl(iommu->reg + DMAR_FEUADDR_REG);
3592
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003593 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003594 }
3595 return 0;
3596
3597nomem:
3598 for_each_active_iommu(iommu, drhd)
3599 kfree(iommu->iommu_state);
3600
3601 return -ENOMEM;
3602}
3603
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003604static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003605{
3606 struct dmar_drhd_unit *drhd;
3607 struct intel_iommu *iommu = NULL;
3608 unsigned long flag;
3609
3610 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07003611 if (force_on)
3612 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
3613 else
3614 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003615 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003616 }
3617
3618 for_each_active_iommu(iommu, drhd) {
3619
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003620 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003621
3622 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
3623 iommu->reg + DMAR_FECTL_REG);
3624 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
3625 iommu->reg + DMAR_FEDATA_REG);
3626 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
3627 iommu->reg + DMAR_FEADDR_REG);
3628 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
3629 iommu->reg + DMAR_FEUADDR_REG);
3630
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003631 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003632 }
3633
3634 for_each_active_iommu(iommu, drhd)
3635 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003636}
3637
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003638static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003639 .resume = iommu_resume,
3640 .suspend = iommu_suspend,
3641};
3642
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003643static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003644{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003645 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003646}
3647
3648#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02003649static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003650#endif /* CONFIG_PM */
3651
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003652
3653int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header)
3654{
3655 struct acpi_dmar_reserved_memory *rmrr;
3656 struct dmar_rmrr_unit *rmrru;
3657
3658 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
3659 if (!rmrru)
3660 return -ENOMEM;
3661
3662 rmrru->hdr = header;
3663 rmrr = (struct acpi_dmar_reserved_memory *)header;
3664 rmrru->base_address = rmrr->base_address;
3665 rmrru->end_address = rmrr->end_address;
Jiang Liu2e455282014-02-19 14:07:36 +08003666 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
3667 ((void *)rmrr) + rmrr->header.length,
3668 &rmrru->devices_cnt);
3669 if (rmrru->devices_cnt && rmrru->devices == NULL) {
3670 kfree(rmrru);
3671 return -ENOMEM;
3672 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003673
Jiang Liu2e455282014-02-19 14:07:36 +08003674 list_add(&rmrru->list, &dmar_rmrr_units);
3675
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003676 return 0;
3677}
3678
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003679int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
3680{
3681 struct acpi_dmar_atsr *atsr;
3682 struct dmar_atsr_unit *atsru;
3683
3684 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3685 atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
3686 if (!atsru)
3687 return -ENOMEM;
3688
3689 atsru->hdr = hdr;
3690 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08003691 if (!atsru->include_all) {
3692 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
3693 (void *)atsr + atsr->header.length,
3694 &atsru->devices_cnt);
3695 if (atsru->devices_cnt && atsru->devices == NULL) {
3696 kfree(atsru);
3697 return -ENOMEM;
3698 }
3699 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003700
Jiang Liu0e242612014-02-19 14:07:34 +08003701 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003702
3703 return 0;
3704}
3705
Jiang Liu9bdc5312014-01-06 14:18:27 +08003706static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3707{
3708 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
3709 kfree(atsru);
3710}
3711
3712static void intel_iommu_free_dmars(void)
3713{
3714 struct dmar_rmrr_unit *rmrru, *rmrr_n;
3715 struct dmar_atsr_unit *atsru, *atsr_n;
3716
3717 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
3718 list_del(&rmrru->list);
3719 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
3720 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003721 }
3722
Jiang Liu9bdc5312014-01-06 14:18:27 +08003723 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
3724 list_del(&atsru->list);
3725 intel_iommu_free_atsr(atsru);
3726 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003727}
3728
3729int dmar_find_matched_atsr_unit(struct pci_dev *dev)
3730{
Jiang Liub683b232014-02-19 14:07:32 +08003731 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003732 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00003733 struct pci_dev *bridge = NULL;
3734 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003735 struct acpi_dmar_atsr *atsr;
3736 struct dmar_atsr_unit *atsru;
3737
3738 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003739 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08003740 bridge = bus->self;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003741 if (!bridge || !pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08003742 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003743 return 0;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003744 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003745 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003746 }
Jiang Liub5f82dd2014-02-19 14:07:31 +08003747 if (!bridge)
3748 return 0;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003749
Jiang Liu0e242612014-02-19 14:07:34 +08003750 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08003751 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3752 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3753 if (atsr->segment != pci_domain_nr(dev->bus))
3754 continue;
3755
Jiang Liub683b232014-02-19 14:07:32 +08003756 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00003757 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08003758 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003759
3760 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08003761 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003762 }
Jiang Liub683b232014-02-19 14:07:32 +08003763 ret = 0;
3764out:
Jiang Liu0e242612014-02-19 14:07:34 +08003765 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003766
Jiang Liub683b232014-02-19 14:07:32 +08003767 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003768}
3769
Jiang Liu59ce0512014-02-19 14:07:35 +08003770int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3771{
3772 int ret = 0;
3773 struct dmar_rmrr_unit *rmrru;
3774 struct dmar_atsr_unit *atsru;
3775 struct acpi_dmar_atsr *atsr;
3776 struct acpi_dmar_reserved_memory *rmrr;
3777
3778 if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
3779 return 0;
3780
3781 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
3782 rmrr = container_of(rmrru->hdr,
3783 struct acpi_dmar_reserved_memory, header);
3784 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3785 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
3786 ((void *)rmrr) + rmrr->header.length,
3787 rmrr->segment, rmrru->devices,
3788 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08003789 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08003790 return ret;
3791 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08003792 dmar_remove_dev_scope(info, rmrr->segment,
3793 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08003794 }
3795 }
3796
3797 list_for_each_entry(atsru, &dmar_atsr_units, list) {
3798 if (atsru->include_all)
3799 continue;
3800
3801 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3802 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3803 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
3804 (void *)atsr + atsr->header.length,
3805 atsr->segment, atsru->devices,
3806 atsru->devices_cnt);
3807 if (ret > 0)
3808 break;
3809 else if(ret < 0)
3810 return ret;
3811 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
3812 if (dmar_remove_dev_scope(info, atsr->segment,
3813 atsru->devices, atsru->devices_cnt))
3814 break;
3815 }
3816 }
3817
3818 return 0;
3819}
3820
Fenghua Yu99dcade2009-11-11 07:23:06 -08003821/*
3822 * Here we only respond to action of unbound device from driver.
3823 *
3824 * Added device is not attached to its DMAR domain here yet. That will happen
3825 * when mapping the device to iova.
3826 */
3827static int device_notifier(struct notifier_block *nb,
3828 unsigned long action, void *data)
3829{
3830 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08003831 struct dmar_domain *domain;
3832
David Woodhouse3d891942014-03-06 15:59:26 +00003833 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00003834 return 0;
3835
Jiang Liu7e7dfab2014-02-19 14:07:23 +08003836 if (action != BUS_NOTIFY_UNBOUND_DRIVER &&
3837 action != BUS_NOTIFY_DEL_DEVICE)
3838 return 0;
3839
David Woodhouse1525a292014-03-06 16:19:30 +00003840 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08003841 if (!domain)
3842 return 0;
3843
Jiang Liu3a5670e2014-02-19 14:07:33 +08003844 down_read(&dmar_global_lock);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07003845 domain_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08003846 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08003847 domain_exit(domain);
Jiang Liu3a5670e2014-02-19 14:07:33 +08003848 up_read(&dmar_global_lock);
Alex Williamsona97590e2011-03-04 14:52:16 -07003849
Fenghua Yu99dcade2009-11-11 07:23:06 -08003850 return 0;
3851}
3852
3853static struct notifier_block device_nb = {
3854 .notifier_call = device_notifier,
3855};
3856
Jiang Liu75f05562014-02-19 14:07:37 +08003857static int intel_iommu_memory_notifier(struct notifier_block *nb,
3858 unsigned long val, void *v)
3859{
3860 struct memory_notify *mhp = v;
3861 unsigned long long start, end;
3862 unsigned long start_vpfn, last_vpfn;
3863
3864 switch (val) {
3865 case MEM_GOING_ONLINE:
3866 start = mhp->start_pfn << PAGE_SHIFT;
3867 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
3868 if (iommu_domain_identity_map(si_domain, start, end)) {
3869 pr_warn("dmar: failed to build identity map for [%llx-%llx]\n",
3870 start, end);
3871 return NOTIFY_BAD;
3872 }
3873 break;
3874
3875 case MEM_OFFLINE:
3876 case MEM_CANCEL_ONLINE:
3877 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
3878 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
3879 while (start_vpfn <= last_vpfn) {
3880 struct iova *iova;
3881 struct dmar_drhd_unit *drhd;
3882 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003883 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08003884
3885 iova = find_iova(&si_domain->iovad, start_vpfn);
3886 if (iova == NULL) {
3887 pr_debug("dmar: failed get IOVA for PFN %lx\n",
3888 start_vpfn);
3889 break;
3890 }
3891
3892 iova = split_and_remove_iova(&si_domain->iovad, iova,
3893 start_vpfn, last_vpfn);
3894 if (iova == NULL) {
3895 pr_warn("dmar: failed to split IOVA PFN [%lx-%lx]\n",
3896 start_vpfn, last_vpfn);
3897 return NOTIFY_BAD;
3898 }
3899
David Woodhouseea8ea462014-03-05 17:09:32 +00003900 freelist = domain_unmap(si_domain, iova->pfn_lo,
3901 iova->pfn_hi);
3902
Jiang Liu75f05562014-02-19 14:07:37 +08003903 rcu_read_lock();
3904 for_each_active_iommu(iommu, drhd)
3905 iommu_flush_iotlb_psi(iommu, si_domain->id,
3906 iova->pfn_lo,
David Woodhouseea8ea462014-03-05 17:09:32 +00003907 iova->pfn_hi - iova->pfn_lo + 1,
3908 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08003909 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00003910 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08003911
3912 start_vpfn = iova->pfn_hi + 1;
3913 free_iova_mem(iova);
3914 }
3915 break;
3916 }
3917
3918 return NOTIFY_OK;
3919}
3920
3921static struct notifier_block intel_iommu_memory_nb = {
3922 .notifier_call = intel_iommu_memory_notifier,
3923 .priority = 0
3924};
3925
Alex Williamsona5459cf2014-06-12 16:12:31 -06003926
3927static ssize_t intel_iommu_show_version(struct device *dev,
3928 struct device_attribute *attr,
3929 char *buf)
3930{
3931 struct intel_iommu *iommu = dev_get_drvdata(dev);
3932 u32 ver = readl(iommu->reg + DMAR_VER_REG);
3933 return sprintf(buf, "%d:%d\n",
3934 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
3935}
3936static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
3937
3938static ssize_t intel_iommu_show_address(struct device *dev,
3939 struct device_attribute *attr,
3940 char *buf)
3941{
3942 struct intel_iommu *iommu = dev_get_drvdata(dev);
3943 return sprintf(buf, "%llx\n", iommu->reg_phys);
3944}
3945static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
3946
3947static ssize_t intel_iommu_show_cap(struct device *dev,
3948 struct device_attribute *attr,
3949 char *buf)
3950{
3951 struct intel_iommu *iommu = dev_get_drvdata(dev);
3952 return sprintf(buf, "%llx\n", iommu->cap);
3953}
3954static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
3955
3956static ssize_t intel_iommu_show_ecap(struct device *dev,
3957 struct device_attribute *attr,
3958 char *buf)
3959{
3960 struct intel_iommu *iommu = dev_get_drvdata(dev);
3961 return sprintf(buf, "%llx\n", iommu->ecap);
3962}
3963static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
3964
3965static struct attribute *intel_iommu_attrs[] = {
3966 &dev_attr_version.attr,
3967 &dev_attr_address.attr,
3968 &dev_attr_cap.attr,
3969 &dev_attr_ecap.attr,
3970 NULL,
3971};
3972
3973static struct attribute_group intel_iommu_group = {
3974 .name = "intel-iommu",
3975 .attrs = intel_iommu_attrs,
3976};
3977
3978const struct attribute_group *intel_iommu_groups[] = {
3979 &intel_iommu_group,
3980 NULL,
3981};
3982
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003983int __init intel_iommu_init(void)
3984{
Jiang Liu9bdc5312014-01-06 14:18:27 +08003985 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09003986 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08003987 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003988
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07003989 /* VT-d is required for a TXT/tboot launch, so enforce that */
3990 force_on = tboot_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003991
Jiang Liu3a5670e2014-02-19 14:07:33 +08003992 if (iommu_init_mempool()) {
3993 if (force_on)
3994 panic("tboot: Failed to initialize iommu memory\n");
3995 return -ENOMEM;
3996 }
3997
3998 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07003999 if (dmar_table_init()) {
4000 if (force_on)
4001 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004002 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004003 }
4004
Takao Indoh3a93c842013-04-23 17:35:03 +09004005 /*
4006 * Disable translation if already enabled prior to OS handover.
4007 */
Jiang Liu7c919772014-01-06 14:18:18 +08004008 for_each_active_iommu(iommu, drhd)
Takao Indoh3a93c842013-04-23 17:35:03 +09004009 if (iommu->gcmd & DMA_GCMD_TE)
4010 iommu_disable_translation(iommu);
Takao Indoh3a93c842013-04-23 17:35:03 +09004011
Suresh Siddhac2c72862011-08-23 17:05:19 -07004012 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004013 if (force_on)
4014 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004015 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004016 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004017
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004018 if (no_iommu || dmar_disabled)
Jiang Liu9bdc5312014-01-06 14:18:27 +08004019 goto out_free_dmar;
Suresh Siddha2ae21012008-07-10 11:16:43 -07004020
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004021 if (list_empty(&dmar_rmrr_units))
4022 printk(KERN_INFO "DMAR: No RMRR found\n");
4023
4024 if (list_empty(&dmar_atsr_units))
4025 printk(KERN_INFO "DMAR: No ATSR found\n");
4026
Joseph Cihula51a63e62011-03-21 11:04:24 -07004027 if (dmar_init_reserved_ranges()) {
4028 if (force_on)
4029 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004030 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004031 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004032
4033 init_no_remapping_devices();
4034
Joseph Cihulab7792602011-05-03 00:08:37 -07004035 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004036 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004037 if (force_on)
4038 panic("tboot: Failed to initialize DMARs\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004039 printk(KERN_ERR "IOMMU: dmar init failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004040 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004041 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004042 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004043 printk(KERN_INFO
4044 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
4045
mark gross5e0d2a62008-03-04 15:22:08 -08004046 init_timer(&unmap_timer);
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004047#ifdef CONFIG_SWIOTLB
4048 swiotlb = 0;
4049#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004050 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004051
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004052 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004053
Alex Williamsona5459cf2014-06-12 16:12:31 -06004054 for_each_active_iommu(iommu, drhd)
4055 iommu->iommu_dev = iommu_device_create(NULL, iommu,
4056 intel_iommu_groups,
4057 iommu->name);
4058
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004059 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004060 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004061 if (si_domain && !hw_pass_through)
4062 register_memory_notifier(&intel_iommu_memory_nb);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004063
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004064 intel_iommu_enabled = 1;
4065
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004066 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004067
4068out_free_reserved_range:
4069 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004070out_free_dmar:
4071 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004072 up_write(&dmar_global_lock);
4073 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004074 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004075}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004076
Alex Williamson579305f2014-07-03 09:51:43 -06004077static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
4078{
4079 struct intel_iommu *iommu = opaque;
4080
4081 iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4082 return 0;
4083}
4084
4085/*
4086 * NB - intel-iommu lacks any sort of reference counting for the users of
4087 * dependent devices. If multiple endpoints have intersecting dependent
4088 * devices, unbinding the driver from any one of them will possibly leave
4089 * the others unable to operate.
4090 */
Han, Weidong3199aa62009-02-26 17:31:12 +08004091static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004092 struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004093{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004094 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004095 return;
4096
Alex Williamson579305f2014-07-03 09:51:43 -06004097 pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004098}
4099
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004100static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004101 struct device *dev)
Weidong Hanc7151a82008-12-08 22:51:37 +08004102{
Yijing Wangbca2b912013-10-31 17:26:04 +08004103 struct device_domain_info *info, *tmp;
Weidong Hanc7151a82008-12-08 22:51:37 +08004104 struct intel_iommu *iommu;
4105 unsigned long flags;
4106 int found = 0;
David Woodhouse156baca2014-03-09 14:00:57 -07004107 u8 bus, devfn;
Weidong Hanc7151a82008-12-08 22:51:37 +08004108
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004109 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanc7151a82008-12-08 22:51:37 +08004110 if (!iommu)
4111 return;
4112
4113 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wangbca2b912013-10-31 17:26:04 +08004114 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004115 if (info->iommu == iommu && info->bus == bus &&
4116 info->devfn == devfn) {
David Woodhouse109b9b02012-05-25 17:43:02 +01004117 unlink_domain_info(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004118 spin_unlock_irqrestore(&device_domain_lock, flags);
4119
Yu Zhao93a23a72009-05-18 13:51:37 +08004120 iommu_disable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004121 iommu_detach_dev(iommu, info->bus, info->devfn);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004122 iommu_detach_dependent_devices(iommu, dev);
Weidong Hanc7151a82008-12-08 22:51:37 +08004123 free_devinfo_mem(info);
4124
4125 spin_lock_irqsave(&device_domain_lock, flags);
4126
4127 if (found)
4128 break;
4129 else
4130 continue;
4131 }
4132
4133 /* if there is no other devices under the same iommu
4134 * owned by this domain, clear this iommu in iommu_bmp
4135 * update iommu count and coherency
4136 */
David Woodhouse8bbc4412014-03-09 13:52:37 -07004137 if (info->iommu == iommu)
Weidong Hanc7151a82008-12-08 22:51:37 +08004138 found = 1;
4139 }
4140
Roland Dreier3e7abe22011-07-20 06:22:21 -07004141 spin_unlock_irqrestore(&device_domain_lock, flags);
4142
Weidong Hanc7151a82008-12-08 22:51:37 +08004143 if (found == 0) {
Jiang Liufb170fb2014-07-11 14:19:28 +08004144 domain_detach_iommu(domain, iommu);
4145 if (!domain_type_is_vm_or_si(domain))
4146 iommu_detach_domain(domain, iommu);
Weidong Hanc7151a82008-12-08 22:51:37 +08004147 }
Weidong Hanc7151a82008-12-08 22:51:37 +08004148}
4149
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004150static int md_domain_init(struct dmar_domain *domain, int guest_width)
Weidong Han5e98c4b2008-12-08 23:03:27 +08004151{
4152 int adjust_width;
4153
4154 init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004155 domain_reserve_special_ranges(domain);
4156
4157 /* calculate AGAW */
4158 domain->gaw = guest_width;
4159 adjust_width = guestwidth_to_adjustwidth(guest_width);
4160 domain->agaw = width_to_agaw(adjust_width);
4161
Weidong Han5e98c4b2008-12-08 23:03:27 +08004162 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004163 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004164 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004165 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004166
4167 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004168 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004169 if (!domain->pgd)
4170 return -ENOMEM;
4171 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4172 return 0;
4173}
4174
Joerg Roedel5d450802008-12-03 14:52:32 +01004175static int intel_iommu_domain_init(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004176{
Joerg Roedel5d450802008-12-03 14:52:32 +01004177 struct dmar_domain *dmar_domain;
Kay, Allen M38717942008-09-09 18:37:29 +03004178
Jiang Liuab8dfe22014-07-11 14:19:27 +08004179 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01004180 if (!dmar_domain) {
Kay, Allen M38717942008-09-09 18:37:29 +03004181 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004182 "intel_iommu_domain_init: dmar_domain == NULL\n");
4183 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004184 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004185 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Kay, Allen M38717942008-09-09 18:37:29 +03004186 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004187 "intel_iommu_domain_init() failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08004188 domain_exit(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004189 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004190 }
Allen Kay8140a952011-10-14 12:32:17 -07004191 domain_update_iommu_cap(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004192 domain->priv = dmar_domain;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004193
Joerg Roedel8a0e7152012-01-26 19:40:54 +01004194 domain->geometry.aperture_start = 0;
4195 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4196 domain->geometry.force_aperture = true;
4197
Joerg Roedel5d450802008-12-03 14:52:32 +01004198 return 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004199}
Kay, Allen M38717942008-09-09 18:37:29 +03004200
Joerg Roedel5d450802008-12-03 14:52:32 +01004201static void intel_iommu_domain_destroy(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004202{
Joerg Roedel5d450802008-12-03 14:52:32 +01004203 struct dmar_domain *dmar_domain = domain->priv;
4204
4205 domain->priv = NULL;
Jiang Liu92d03cc2014-02-19 14:07:28 +08004206 domain_exit(dmar_domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004207}
Kay, Allen M38717942008-09-09 18:37:29 +03004208
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004209static int intel_iommu_attach_device(struct iommu_domain *domain,
4210 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004211{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004212 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004213 struct intel_iommu *iommu;
4214 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07004215 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03004216
David Woodhouse7207d8f2014-03-09 16:31:06 -07004217 /* normally dev is not mapped */
4218 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004219 struct dmar_domain *old_domain;
4220
David Woodhouse1525a292014-03-06 16:19:30 +00004221 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004222 if (old_domain) {
Jiang Liuab8dfe22014-07-11 14:19:27 +08004223 if (domain_type_is_vm_or_si(dmar_domain))
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004224 domain_remove_one_dev_info(old_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004225 else
4226 domain_remove_dev_info(old_domain);
4227 }
4228 }
4229
David Woodhouse156baca2014-03-09 14:00:57 -07004230 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004231 if (!iommu)
4232 return -ENODEV;
4233
4234 /* check if this iommu agaw is sufficient for max mapped address */
4235 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01004236 if (addr_width > cap_mgaw(iommu->cap))
4237 addr_width = cap_mgaw(iommu->cap);
4238
4239 if (dmar_domain->max_addr > (1LL << addr_width)) {
4240 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004241 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01004242 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004243 return -EFAULT;
4244 }
Tom Lyona99c47a2010-05-17 08:20:45 +01004245 dmar_domain->gaw = addr_width;
4246
4247 /*
4248 * Knock out extra levels of page tables if necessary
4249 */
4250 while (iommu->agaw < dmar_domain->agaw) {
4251 struct dma_pte *pte;
4252
4253 pte = dmar_domain->pgd;
4254 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08004255 dmar_domain->pgd = (struct dma_pte *)
4256 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01004257 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01004258 }
4259 dmar_domain->agaw--;
4260 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004261
David Woodhouse5913c9b2014-03-09 16:27:31 -07004262 return domain_add_dev_info(dmar_domain, dev, CONTEXT_TT_MULTI_LEVEL);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004263}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004264
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004265static void intel_iommu_detach_device(struct iommu_domain *domain,
4266 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004267{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004268 struct dmar_domain *dmar_domain = domain->priv;
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004269
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004270 domain_remove_one_dev_info(dmar_domain, dev);
Kay, Allen M38717942008-09-09 18:37:29 +03004271}
Kay, Allen M38717942008-09-09 18:37:29 +03004272
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004273static int intel_iommu_map(struct iommu_domain *domain,
4274 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004275 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03004276{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004277 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004278 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004279 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004280 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004281
Joerg Roedeldde57a22008-12-03 15:04:09 +01004282 if (iommu_prot & IOMMU_READ)
4283 prot |= DMA_PTE_READ;
4284 if (iommu_prot & IOMMU_WRITE)
4285 prot |= DMA_PTE_WRITE;
Sheng Yang9cf066972009-03-18 15:33:07 +08004286 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
4287 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004288
David Woodhouse163cc522009-06-28 00:51:17 +01004289 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004290 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004291 u64 end;
4292
4293 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01004294 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004295 if (end < max_addr) {
Tom Lyon8954da12010-05-17 08:19:52 +01004296 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004297 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01004298 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004299 return -EFAULT;
4300 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01004301 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004302 }
David Woodhousead051222009-06-28 14:22:28 +01004303 /* Round up size to next multiple of PAGE_SIZE, if it and
4304 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01004305 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01004306 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
4307 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004308 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03004309}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004310
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004311static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00004312 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004313{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004314 struct dmar_domain *dmar_domain = domain->priv;
David Woodhouseea8ea462014-03-05 17:09:32 +00004315 struct page *freelist = NULL;
4316 struct intel_iommu *iommu;
4317 unsigned long start_pfn, last_pfn;
4318 unsigned int npages;
4319 int iommu_id, num, ndomains, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01004320
David Woodhouse5cf0a762014-03-19 16:07:49 +00004321 /* Cope with horrid API which requires us to unmap more than the
4322 size argument if it happens to be a large-page mapping. */
4323 if (!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level))
4324 BUG();
4325
4326 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
4327 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
4328
David Woodhouseea8ea462014-03-05 17:09:32 +00004329 start_pfn = iova >> VTD_PAGE_SHIFT;
4330 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
4331
4332 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
4333
4334 npages = last_pfn - start_pfn + 1;
4335
4336 for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) {
4337 iommu = g_iommus[iommu_id];
4338
4339 /*
4340 * find bit position of dmar_domain
4341 */
4342 ndomains = cap_ndoms(iommu->cap);
4343 for_each_set_bit(num, iommu->domain_ids, ndomains) {
4344 if (iommu->domains[num] == dmar_domain)
4345 iommu_flush_iotlb_psi(iommu, num, start_pfn,
4346 npages, !freelist, 0);
4347 }
4348
4349 }
4350
4351 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004352
David Woodhouse163cc522009-06-28 00:51:17 +01004353 if (dmar_domain->max_addr == iova + size)
4354 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004355
David Woodhouse5cf0a762014-03-19 16:07:49 +00004356 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004357}
Kay, Allen M38717942008-09-09 18:37:29 +03004358
Joerg Roedeld14d6572008-12-03 15:06:57 +01004359static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547ac2013-03-29 01:23:58 +05304360 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03004361{
Joerg Roedeld14d6572008-12-03 15:06:57 +01004362 struct dmar_domain *dmar_domain = domain->priv;
Kay, Allen M38717942008-09-09 18:37:29 +03004363 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00004364 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004365 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004366
David Woodhouse5cf0a762014-03-19 16:07:49 +00004367 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03004368 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004369 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03004370
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004371 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03004372}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004373
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004374static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
4375 unsigned long cap)
4376{
4377 struct dmar_domain *dmar_domain = domain->priv;
4378
4379 if (cap == IOMMU_CAP_CACHE_COHERENCY)
4380 return dmar_domain->iommu_snooping;
Tom Lyon323f99c2010-07-02 16:56:14 -04004381 if (cap == IOMMU_CAP_INTR_REMAP)
Suresh Siddha95a02e92012-03-30 11:47:07 -07004382 return irq_remapping_enabled;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004383
4384 return 0;
4385}
4386
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004387static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004388{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004389 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004390 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07004391 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04004392
Alex Williamsona5459cf2014-06-12 16:12:31 -06004393 iommu = device_to_iommu(dev, &bus, &devfn);
4394 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004395 return -ENODEV;
4396
Alex Williamsona5459cf2014-06-12 16:12:31 -06004397 iommu_device_link(iommu->iommu_dev, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004398
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004399 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06004400
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004401 if (IS_ERR(group))
4402 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004403
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004404 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004405 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004406}
4407
4408static void intel_iommu_remove_device(struct device *dev)
4409{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004410 struct intel_iommu *iommu;
4411 u8 bus, devfn;
4412
4413 iommu = device_to_iommu(dev, &bus, &devfn);
4414 if (!iommu)
4415 return;
4416
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004417 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004418
4419 iommu_device_unlink(iommu->iommu_dev, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004420}
4421
Thierry Redingb22f6432014-06-27 09:03:12 +02004422static const struct iommu_ops intel_iommu_ops = {
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004423 .domain_init = intel_iommu_domain_init,
4424 .domain_destroy = intel_iommu_domain_destroy,
4425 .attach_dev = intel_iommu_attach_device,
4426 .detach_dev = intel_iommu_detach_device,
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004427 .map = intel_iommu_map,
4428 .unmap = intel_iommu_unmap,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004429 .iova_to_phys = intel_iommu_iova_to_phys,
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004430 .domain_has_cap = intel_iommu_domain_has_cap,
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004431 .add_device = intel_iommu_add_device,
4432 .remove_device = intel_iommu_remove_device,
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +02004433 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004434};
David Woodhouse9af88142009-02-13 23:18:03 +00004435
Daniel Vetter94526182013-01-20 23:50:13 +01004436static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
4437{
4438 /* G4x/GM45 integrated gfx dmar support is totally busted. */
4439 printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
4440 dmar_map_gfx = 0;
4441}
4442
4443DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
4444DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
4445DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
4446DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
4447DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
4448DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
4449DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
4450
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004451static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00004452{
4453 /*
4454 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01004455 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00004456 */
4457 printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
4458 rwbf_quirk = 1;
4459}
4460
4461DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01004462DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
4463DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
4464DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
4465DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
4466DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
4467DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07004468
Adam Jacksoneecfd572010-08-25 21:17:34 +01004469#define GGC 0x52
4470#define GGC_MEMORY_SIZE_MASK (0xf << 8)
4471#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
4472#define GGC_MEMORY_SIZE_1M (0x1 << 8)
4473#define GGC_MEMORY_SIZE_2M (0x3 << 8)
4474#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
4475#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
4476#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
4477#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
4478
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004479static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01004480{
4481 unsigned short ggc;
4482
Adam Jacksoneecfd572010-08-25 21:17:34 +01004483 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01004484 return;
4485
Adam Jacksoneecfd572010-08-25 21:17:34 +01004486 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
David Woodhouse9eecabc2010-09-21 22:28:23 +01004487 printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
4488 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004489 } else if (dmar_map_gfx) {
4490 /* we have to ensure the gfx device is idle before we flush */
4491 printk(KERN_INFO "DMAR: Disabling batched IOTLB flush on Ironlake\n");
4492 intel_iommu_strict = 1;
4493 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01004494}
4495DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4496DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
4497DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
4498DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
4499
David Woodhousee0fc7e02009-09-30 09:12:17 -07004500/* On Tylersburg chipsets, some BIOSes have been known to enable the
4501 ISOCH DMAR unit for the Azalia sound device, but not give it any
4502 TLB entries, which causes it to deadlock. Check for that. We do
4503 this in a function called from init_dmars(), instead of in a PCI
4504 quirk, because we don't want to print the obnoxious "BIOS broken"
4505 message if VT-d is actually disabled.
4506*/
4507static void __init check_tylersburg_isoch(void)
4508{
4509 struct pci_dev *pdev;
4510 uint32_t vtisochctrl;
4511
4512 /* If there's no Azalia in the system anyway, forget it. */
4513 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
4514 if (!pdev)
4515 return;
4516 pci_dev_put(pdev);
4517
4518 /* System Management Registers. Might be hidden, in which case
4519 we can't do the sanity check. But that's OK, because the
4520 known-broken BIOSes _don't_ actually hide it, so far. */
4521 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
4522 if (!pdev)
4523 return;
4524
4525 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
4526 pci_dev_put(pdev);
4527 return;
4528 }
4529
4530 pci_dev_put(pdev);
4531
4532 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
4533 if (vtisochctrl & 1)
4534 return;
4535
4536 /* Drop all bits other than the number of TLB entries */
4537 vtisochctrl &= 0x1c;
4538
4539 /* If we have the recommended number of TLB entries (16), fine. */
4540 if (vtisochctrl == 0x10)
4541 return;
4542
4543 /* Zero TLB entries? You get to ride the short bus to school. */
4544 if (!vtisochctrl) {
4545 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
4546 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4547 dmi_get_system_info(DMI_BIOS_VENDOR),
4548 dmi_get_system_info(DMI_BIOS_VERSION),
4549 dmi_get_system_info(DMI_PRODUCT_VERSION));
4550 iommu_identity_mapping |= IDENTMAP_AZALIA;
4551 return;
4552 }
4553
4554 printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
4555 vtisochctrl);
4556}