blob: e758d8ed8fb5568930e002cd8e13476000b0b5ac [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{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800198 root->val &= ~VTD_PAGE_MASK;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000199 root->val |= value & VTD_PAGE_MASK;
200}
201
202static inline struct context_entry *
203get_context_addr_from_root(struct root_entry *root)
204{
205 return (struct context_entry *)
206 (root_present(root)?phys_to_virt(
207 root->val & VTD_PAGE_MASK) :
208 NULL);
209}
210
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000211/*
212 * low 64 bits:
213 * 0: present
214 * 1: fault processing disable
215 * 2-3: translation type
216 * 12-63: address space root
217 * high 64 bits:
218 * 0-2: address width
219 * 3-6: aval
220 * 8-23: domain id
221 */
222struct context_entry {
223 u64 lo;
224 u64 hi;
225};
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000226
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000227static inline bool context_present(struct context_entry *context)
228{
229 return (context->lo & 1);
230}
231static inline void context_set_present(struct context_entry *context)
232{
233 context->lo |= 1;
234}
235
236static inline void context_set_fault_enable(struct context_entry *context)
237{
238 context->lo &= (((u64)-1) << 2) | 1;
239}
240
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000241static inline void context_set_translation_type(struct context_entry *context,
242 unsigned long value)
243{
244 context->lo &= (((u64)-1) << 4) | 3;
245 context->lo |= (value & 3) << 2;
246}
247
248static inline void context_set_address_root(struct context_entry *context,
249 unsigned long value)
250{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800251 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000252 context->lo |= value & VTD_PAGE_MASK;
253}
254
255static inline void context_set_address_width(struct context_entry *context,
256 unsigned long value)
257{
258 context->hi |= value & 7;
259}
260
261static inline void context_set_domain_id(struct context_entry *context,
262 unsigned long value)
263{
264 context->hi |= (value & ((1 << 16) - 1)) << 8;
265}
266
267static inline void context_clear_entry(struct context_entry *context)
268{
269 context->lo = 0;
270 context->hi = 0;
271}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000272
Mark McLoughlin622ba122008-11-20 15:49:46 +0000273/*
274 * 0: readable
275 * 1: writable
276 * 2-6: reserved
277 * 7: super page
Sheng Yang9cf06692009-03-18 15:33:07 +0800278 * 8-10: available
279 * 11: snoop behavior
Mark McLoughlin622ba122008-11-20 15:49:46 +0000280 * 12-63: Host physcial address
281 */
282struct dma_pte {
283 u64 val;
284};
Mark McLoughlin622ba122008-11-20 15:49:46 +0000285
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000286static inline void dma_clear_pte(struct dma_pte *pte)
287{
288 pte->val = 0;
289}
290
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000291static inline u64 dma_pte_addr(struct dma_pte *pte)
292{
David Woodhousec85994e2009-07-01 19:21:24 +0100293#ifdef CONFIG_64BIT
294 return pte->val & VTD_PAGE_MASK;
295#else
296 /* Must have a full atomic 64-bit read */
David Woodhouse1a8bd482010-08-10 01:38:53 +0100297 return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
David Woodhousec85994e2009-07-01 19:21:24 +0100298#endif
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000299}
300
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000301static inline bool dma_pte_present(struct dma_pte *pte)
302{
303 return (pte->val & 3) != 0;
304}
Mark McLoughlin622ba122008-11-20 15:49:46 +0000305
Allen Kay4399c8b2011-10-14 12:32:46 -0700306static inline bool dma_pte_superpage(struct dma_pte *pte)
307{
Joerg Roedelc3c75eb2014-07-04 11:19:10 +0200308 return (pte->val & DMA_PTE_LARGE_PAGE);
Allen Kay4399c8b2011-10-14 12:32:46 -0700309}
310
David Woodhouse75e6bf92009-07-02 11:21:16 +0100311static inline int first_pte_in_page(struct dma_pte *pte)
312{
313 return !((unsigned long)pte & ~VTD_PAGE_MASK);
314}
315
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700316/*
317 * This domain is a statically identity mapping domain.
318 * 1. This domain creats a static 1:1 mapping to all usable memory.
319 * 2. It maps to each iommu if successful.
320 * 3. Each iommu mapps to this domain if successful.
321 */
David Woodhouse19943b02009-08-04 16:19:20 +0100322static struct dmar_domain *si_domain;
323static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700324
Weidong Han1ce28fe2008-12-08 16:35:39 +0800325/* domain represents a virtual machine, more than one devices
326 * across iommus may be owned in one domain, e.g. kvm guest.
327 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800328#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800329
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700330/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800331#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700332
Mark McLoughlin99126f72008-11-20 15:49:47 +0000333struct dmar_domain {
334 int id; /* domain id */
Suresh Siddha4c923d42009-10-02 11:01:24 -0700335 int nid; /* node id */
Jiang Liu78d8e702014-11-09 22:47:57 +0800336 DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
Mike Travis1b198bb2012-03-05 15:05:16 -0800337 /* bitmap of iommus this domain uses*/
Mark McLoughlin99126f72008-11-20 15:49:47 +0000338
339 struct list_head devices; /* all devices' list */
340 struct iova_domain iovad; /* iova's that belong to this domain */
341
342 struct dma_pte *pgd; /* virtual address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000343 int gaw; /* max guest address width */
344
345 /* adjusted guest address width, 0 is level 2 30-bit */
346 int agaw;
347
Weidong Han3b5410e2008-12-08 09:17:15 +0800348 int flags; /* flags to find out type of domain */
Weidong Han8e6040972008-12-08 15:49:06 +0800349
350 int iommu_coherency;/* indicate coherency of iommu access */
Sheng Yang58c610b2009-03-18 15:33:05 +0800351 int iommu_snooping; /* indicate snooping control feature*/
Weidong Hanc7151a82008-12-08 22:51:37 +0800352 int iommu_count; /* reference count of iommu */
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100353 int iommu_superpage;/* Level of superpages supported:
354 0 == 4KiB (no superpages), 1 == 2MiB,
355 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
Weidong Hanc7151a82008-12-08 22:51:37 +0800356 spinlock_t iommu_lock; /* protect iommu set in domain */
Weidong Hanfe40f1e2008-12-08 23:10:23 +0800357 u64 max_addr; /* maximum mapped address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000358};
359
Mark McLoughlina647dacb2008-11-20 15:49:48 +0000360/* PCI domain-device relationship */
361struct device_domain_info {
362 struct list_head link; /* link to domain siblings */
363 struct list_head global; /* link to global list */
David Woodhouse276dbf992009-04-04 01:45:37 +0100364 u8 bus; /* PCI bus number */
Mark McLoughlina647dacb2008-11-20 15:49:48 +0000365 u8 devfn; /* PCI devfn number */
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000366 struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
Yu Zhao93a23a72009-05-18 13:51:37 +0800367 struct intel_iommu *iommu; /* IOMMU used by this device */
Mark McLoughlina647dacb2008-11-20 15:49:48 +0000368 struct dmar_domain *domain; /* pointer to domain */
369};
370
Jiang Liub94e4112014-02-19 14:07:25 +0800371struct dmar_rmrr_unit {
372 struct list_head list; /* list of rmrr units */
373 struct acpi_dmar_header *hdr; /* ACPI header */
374 u64 base_address; /* reserved base address*/
375 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000376 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800377 int devices_cnt; /* target device count */
378};
379
380struct dmar_atsr_unit {
381 struct list_head list; /* list of ATSR units */
382 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000383 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800384 int devices_cnt; /* target device count */
385 u8 include_all:1; /* include all ports */
386};
387
388static LIST_HEAD(dmar_atsr_units);
389static LIST_HEAD(dmar_rmrr_units);
390
391#define for_each_rmrr_units(rmrr) \
392 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
393
mark gross5e0d2a62008-03-04 15:22:08 -0800394static void flush_unmaps_timeout(unsigned long data);
395
Jiang Liub707cb02014-01-06 14:18:26 +0800396static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
mark gross5e0d2a62008-03-04 15:22:08 -0800397
mark gross80b20dd2008-04-18 13:53:58 -0700398#define HIGH_WATER_MARK 250
399struct deferred_flush_tables {
400 int next;
401 struct iova *iova[HIGH_WATER_MARK];
402 struct dmar_domain *domain[HIGH_WATER_MARK];
David Woodhouseea8ea462014-03-05 17:09:32 +0000403 struct page *freelist[HIGH_WATER_MARK];
mark gross80b20dd2008-04-18 13:53:58 -0700404};
405
406static struct deferred_flush_tables *deferred_flush;
407
mark gross5e0d2a62008-03-04 15:22:08 -0800408/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800409static int g_num_of_iommus;
410
411static DEFINE_SPINLOCK(async_umap_flush_lock);
412static LIST_HEAD(unmaps_to_do);
413
414static int timer_on;
415static long list_size;
mark gross5e0d2a62008-03-04 15:22:08 -0800416
Jiang Liu92d03cc2014-02-19 14:07:28 +0800417static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700418static void domain_remove_dev_info(struct dmar_domain *domain);
Jiang Liub94e4112014-02-19 14:07:25 +0800419static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -0700420 struct device *dev);
Jiang Liu92d03cc2014-02-19 14:07:28 +0800421static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000422 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800423static int domain_detach_iommu(struct dmar_domain *domain,
424 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700425
Suresh Siddhad3f13812011-08-23 17:05:25 -0700426#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800427int dmar_disabled = 0;
428#else
429int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700430#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800431
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200432int intel_iommu_enabled = 0;
433EXPORT_SYMBOL_GPL(intel_iommu_enabled);
434
David Woodhouse2d9e6672010-06-15 10:57:57 +0100435static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700436static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800437static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100438static int intel_iommu_superpage = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700439
David Woodhousec0771df2011-10-14 20:59:46 +0100440int intel_iommu_gfx_mapped;
441EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
442
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700443#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
444static DEFINE_SPINLOCK(device_domain_lock);
445static LIST_HEAD(device_domain_list);
446
Thierry Redingb22f6432014-06-27 09:03:12 +0200447static const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100448
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700449static int __init intel_iommu_setup(char *str)
450{
451 if (!str)
452 return -EINVAL;
453 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800454 if (!strncmp(str, "on", 2)) {
455 dmar_disabled = 0;
456 printk(KERN_INFO "Intel-IOMMU: enabled\n");
457 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700458 dmar_disabled = 1;
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800459 printk(KERN_INFO "Intel-IOMMU: disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700460 } else if (!strncmp(str, "igfx_off", 8)) {
461 dmar_map_gfx = 0;
462 printk(KERN_INFO
463 "Intel-IOMMU: disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700464 } else if (!strncmp(str, "forcedac", 8)) {
mark gross5e0d2a62008-03-04 15:22:08 -0800465 printk(KERN_INFO
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700466 "Intel-IOMMU: Forcing DAC for PCI devices\n");
467 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800468 } else if (!strncmp(str, "strict", 6)) {
469 printk(KERN_INFO
470 "Intel-IOMMU: disable batched IOTLB flush\n");
471 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100472 } else if (!strncmp(str, "sp_off", 6)) {
473 printk(KERN_INFO
474 "Intel-IOMMU: disable supported super page\n");
475 intel_iommu_superpage = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700476 }
477
478 str += strcspn(str, ",");
479 while (*str == ',')
480 str++;
481 }
482 return 0;
483}
484__setup("intel_iommu=", intel_iommu_setup);
485
486static struct kmem_cache *iommu_domain_cache;
487static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700488
Suresh Siddha4c923d42009-10-02 11:01:24 -0700489static inline void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700490{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700491 struct page *page;
492 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700493
Suresh Siddha4c923d42009-10-02 11:01:24 -0700494 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
495 if (page)
496 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700497 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700498}
499
500static inline void free_pgtable_page(void *vaddr)
501{
502 free_page((unsigned long)vaddr);
503}
504
505static inline void *alloc_domain_mem(void)
506{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900507 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700508}
509
Kay, Allen M38717942008-09-09 18:37:29 +0300510static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700511{
512 kmem_cache_free(iommu_domain_cache, vaddr);
513}
514
515static inline void * alloc_devinfo_mem(void)
516{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900517 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700518}
519
520static inline void free_devinfo_mem(void *vaddr)
521{
522 kmem_cache_free(iommu_devinfo_cache, vaddr);
523}
524
Jiang Liuab8dfe22014-07-11 14:19:27 +0800525static inline int domain_type_is_vm(struct dmar_domain *domain)
526{
527 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
528}
529
530static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
531{
532 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
533 DOMAIN_FLAG_STATIC_IDENTITY);
534}
Weidong Han1b573682008-12-08 15:34:06 +0800535
Jiang Liu162d1b12014-07-11 14:19:35 +0800536static inline int domain_pfn_supported(struct dmar_domain *domain,
537 unsigned long pfn)
538{
539 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
540
541 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
542}
543
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700544static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800545{
546 unsigned long sagaw;
547 int agaw = -1;
548
549 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700550 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800551 agaw >= 0; agaw--) {
552 if (test_bit(agaw, &sagaw))
553 break;
554 }
555
556 return agaw;
557}
558
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700559/*
560 * Calculate max SAGAW for each iommu.
561 */
562int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
563{
564 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
565}
566
567/*
568 * calculate agaw for each iommu.
569 * "SAGAW" may be different across iommus, use a default agaw, and
570 * get a supported less agaw for iommus that don't support the default agaw.
571 */
572int iommu_calculate_agaw(struct intel_iommu *iommu)
573{
574 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
575}
576
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700577/* This functionin only returns single iommu in a domain */
Weidong Han8c11e792008-12-08 15:29:22 +0800578static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
579{
580 int iommu_id;
581
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700582 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800583 BUG_ON(domain_type_is_vm_or_si(domain));
Mike Travis1b198bb2012-03-05 15:05:16 -0800584 iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
Weidong Han8c11e792008-12-08 15:29:22 +0800585 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
586 return NULL;
587
588 return g_iommus[iommu_id];
589}
590
Weidong Han8e6040972008-12-08 15:49:06 +0800591static void domain_update_iommu_coherency(struct dmar_domain *domain)
592{
David Woodhoused0501962014-03-11 17:10:29 -0700593 struct dmar_drhd_unit *drhd;
594 struct intel_iommu *iommu;
595 int i, found = 0;
Weidong Han8e6040972008-12-08 15:49:06 +0800596
David Woodhoused0501962014-03-11 17:10:29 -0700597 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800598
Mike Travis1b198bb2012-03-05 15:05:16 -0800599 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
David Woodhoused0501962014-03-11 17:10:29 -0700600 found = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800601 if (!ecap_coherent(g_iommus[i]->ecap)) {
602 domain->iommu_coherency = 0;
603 break;
604 }
Weidong Han8e6040972008-12-08 15:49:06 +0800605 }
David Woodhoused0501962014-03-11 17:10:29 -0700606 if (found)
607 return;
608
609 /* No hardware attached; use lowest common denominator */
610 rcu_read_lock();
611 for_each_active_iommu(iommu, drhd) {
612 if (!ecap_coherent(iommu->ecap)) {
613 domain->iommu_coherency = 0;
614 break;
615 }
616 }
617 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800618}
619
Jiang Liu161f6932014-07-11 14:19:37 +0800620static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100621{
Allen Kay8140a952011-10-14 12:32:17 -0700622 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800623 struct intel_iommu *iommu;
624 int ret = 1;
625
626 rcu_read_lock();
627 for_each_active_iommu(iommu, drhd) {
628 if (iommu != skip) {
629 if (!ecap_sc_support(iommu->ecap)) {
630 ret = 0;
631 break;
632 }
633 }
634 }
635 rcu_read_unlock();
636
637 return ret;
638}
639
640static int domain_update_iommu_superpage(struct intel_iommu *skip)
641{
642 struct dmar_drhd_unit *drhd;
643 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700644 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100645
646 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800647 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100648 }
649
Allen Kay8140a952011-10-14 12:32:17 -0700650 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800651 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700652 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800653 if (iommu != skip) {
654 mask &= cap_super_page_val(iommu->cap);
655 if (!mask)
656 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100657 }
658 }
Jiang Liu0e242612014-02-19 14:07:34 +0800659 rcu_read_unlock();
660
Jiang Liu161f6932014-07-11 14:19:37 +0800661 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100662}
663
Sheng Yang58c610b2009-03-18 15:33:05 +0800664/* Some capabilities may be different across iommus */
665static void domain_update_iommu_cap(struct dmar_domain *domain)
666{
667 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800668 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
669 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800670}
671
David Woodhouse156baca2014-03-09 14:00:57 -0700672static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800673{
674 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800675 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700676 struct device *tmp;
677 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800678 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800679 int i;
680
David Woodhouse156baca2014-03-09 14:00:57 -0700681 if (dev_is_pci(dev)) {
682 pdev = to_pci_dev(dev);
683 segment = pci_domain_nr(pdev->bus);
684 } else if (ACPI_COMPANION(dev))
685 dev = &ACPI_COMPANION(dev)->dev;
686
Jiang Liu0e242612014-02-19 14:07:34 +0800687 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800688 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700689 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100690 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800691
Jiang Liub683b232014-02-19 14:07:32 +0800692 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700693 drhd->devices_cnt, i, tmp) {
694 if (tmp == dev) {
695 *bus = drhd->devices[i].bus;
696 *devfn = drhd->devices[i].devfn;
697 goto out;
698 }
699
700 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000701 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700702
703 ptmp = to_pci_dev(tmp);
704 if (ptmp->subordinate &&
705 ptmp->subordinate->number <= pdev->bus->number &&
706 ptmp->subordinate->busn_res.end >= pdev->bus->number)
707 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100708 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800709
David Woodhouse156baca2014-03-09 14:00:57 -0700710 if (pdev && drhd->include_all) {
711 got_pdev:
712 *bus = pdev->bus->number;
713 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800714 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700715 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800716 }
Jiang Liub683b232014-02-19 14:07:32 +0800717 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700718 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800719 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800720
Jiang Liub683b232014-02-19 14:07:32 +0800721 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800722}
723
Weidong Han5331fe62008-12-08 23:00:00 +0800724static void domain_flush_cache(struct dmar_domain *domain,
725 void *addr, int size)
726{
727 if (!domain->iommu_coherency)
728 clflush_cache_range(addr, size);
729}
730
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700731/* Gets context entry for a given bus and devfn */
732static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
733 u8 bus, u8 devfn)
734{
735 struct root_entry *root;
736 struct context_entry *context;
737 unsigned long phy_addr;
738 unsigned long flags;
739
740 spin_lock_irqsave(&iommu->lock, flags);
741 root = &iommu->root_entry[bus];
742 context = get_context_addr_from_root(root);
743 if (!context) {
Suresh Siddha4c923d42009-10-02 11:01:24 -0700744 context = (struct context_entry *)
745 alloc_pgtable_page(iommu->node);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700746 if (!context) {
747 spin_unlock_irqrestore(&iommu->lock, flags);
748 return NULL;
749 }
Fenghua Yu5b6985c2008-10-16 18:02:32 -0700750 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700751 phy_addr = virt_to_phys((void *)context);
752 set_root_value(root, phy_addr);
753 set_root_present(root);
754 __iommu_flush_cache(iommu, root, sizeof(*root));
755 }
756 spin_unlock_irqrestore(&iommu->lock, flags);
757 return &context[devfn];
758}
759
760static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
761{
762 struct root_entry *root;
763 struct context_entry *context;
764 int ret;
765 unsigned long flags;
766
767 spin_lock_irqsave(&iommu->lock, flags);
768 root = &iommu->root_entry[bus];
769 context = get_context_addr_from_root(root);
770 if (!context) {
771 ret = 0;
772 goto out;
773 }
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000774 ret = context_present(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700775out:
776 spin_unlock_irqrestore(&iommu->lock, flags);
777 return ret;
778}
779
780static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
781{
782 struct root_entry *root;
783 struct context_entry *context;
784 unsigned long flags;
785
786 spin_lock_irqsave(&iommu->lock, flags);
787 root = &iommu->root_entry[bus];
788 context = get_context_addr_from_root(root);
789 if (context) {
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000790 context_clear_entry(&context[devfn]);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700791 __iommu_flush_cache(iommu, &context[devfn], \
792 sizeof(*context));
793 }
794 spin_unlock_irqrestore(&iommu->lock, flags);
795}
796
797static void free_context_table(struct intel_iommu *iommu)
798{
799 struct root_entry *root;
800 int i;
801 unsigned long flags;
802 struct context_entry *context;
803
804 spin_lock_irqsave(&iommu->lock, flags);
805 if (!iommu->root_entry) {
806 goto out;
807 }
808 for (i = 0; i < ROOT_ENTRY_NR; i++) {
809 root = &iommu->root_entry[i];
810 context = get_context_addr_from_root(root);
811 if (context)
812 free_pgtable_page(context);
813 }
814 free_pgtable_page(iommu->root_entry);
815 iommu->root_entry = NULL;
816out:
817 spin_unlock_irqrestore(&iommu->lock, flags);
818}
819
David Woodhouseb026fd22009-06-28 10:37:25 +0100820static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000821 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700822{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700823 struct dma_pte *parent, *pte = NULL;
824 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700825 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700826
827 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200828
Jiang Liu162d1b12014-07-11 14:19:35 +0800829 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200830 /* Address beyond IOMMU's addressing capabilities. */
831 return NULL;
832
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700833 parent = domain->pgd;
834
David Woodhouse5cf0a762014-03-19 16:07:49 +0000835 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700836 void *tmp_page;
837
David Woodhouseb026fd22009-06-28 10:37:25 +0100838 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700839 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000840 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100841 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000842 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700843 break;
844
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000845 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100846 uint64_t pteval;
847
Suresh Siddha4c923d42009-10-02 11:01:24 -0700848 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700849
David Woodhouse206a73c2009-07-01 19:30:28 +0100850 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700851 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100852
David Woodhousec85994e2009-07-01 19:21:24 +0100853 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400854 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 +0800855 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100856 /* Someone else set it while we were thinking; use theirs. */
857 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800858 else
David Woodhousec85994e2009-07-01 19:21:24 +0100859 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700860 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000861 if (level == 1)
862 break;
863
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000864 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700865 level--;
866 }
867
David Woodhouse5cf0a762014-03-19 16:07:49 +0000868 if (!*target_level)
869 *target_level = level;
870
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700871 return pte;
872}
873
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100874
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700875/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100876static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
877 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100878 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700879{
880 struct dma_pte *parent, *pte = NULL;
881 int total = agaw_to_level(domain->agaw);
882 int offset;
883
884 parent = domain->pgd;
885 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100886 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700887 pte = &parent[offset];
888 if (level == total)
889 return pte;
890
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100891 if (!dma_pte_present(pte)) {
892 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700893 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100894 }
895
Yijing Wange16922a2014-05-20 20:37:51 +0800896 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100897 *large_page = total;
898 return pte;
899 }
900
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000901 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700902 total--;
903 }
904 return NULL;
905}
906
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700907/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000908static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +0100909 unsigned long start_pfn,
910 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700911{
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100912 unsigned int large_page = 1;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100913 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700914
Jiang Liu162d1b12014-07-11 14:19:35 +0800915 BUG_ON(!domain_pfn_supported(domain, start_pfn));
916 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700917 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100918
David Woodhouse04b18e62009-06-27 19:15:01 +0100919 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700920 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100921 large_page = 1;
922 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100923 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100924 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100925 continue;
926 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100927 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100928 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100929 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100930 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100931 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
932
David Woodhouse310a5ab2009-06-28 18:52:20 +0100933 domain_flush_cache(domain, first_pte,
934 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700935
936 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700937}
938
Alex Williamson3269ee02013-06-15 10:27:19 -0600939static void dma_pte_free_level(struct dmar_domain *domain, int level,
940 struct dma_pte *pte, unsigned long pfn,
941 unsigned long start_pfn, unsigned long last_pfn)
942{
943 pfn = max(start_pfn, pfn);
944 pte = &pte[pfn_level_offset(pfn, level)];
945
946 do {
947 unsigned long level_pfn;
948 struct dma_pte *level_pte;
949
950 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
951 goto next;
952
953 level_pfn = pfn & level_mask(level - 1);
954 level_pte = phys_to_virt(dma_pte_addr(pte));
955
956 if (level > 2)
957 dma_pte_free_level(domain, level - 1, level_pte,
958 level_pfn, start_pfn, last_pfn);
959
960 /* If range covers entire pagetable, free it */
961 if (!(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -0800962 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -0600963 dma_clear_pte(pte);
964 domain_flush_cache(domain, pte, sizeof(*pte));
965 free_pgtable_page(level_pte);
966 }
967next:
968 pfn += level_size(level);
969 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
970}
971
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700972/* free page table pages. last level pte should already be cleared */
973static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +0100974 unsigned long start_pfn,
975 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700976{
Jiang Liu162d1b12014-07-11 14:19:35 +0800977 BUG_ON(!domain_pfn_supported(domain, start_pfn));
978 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700979 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700980
Jiang Liud41a4ad2014-07-11 14:19:34 +0800981 dma_pte_clear_range(domain, start_pfn, last_pfn);
982
David Woodhousef3a0a522009-06-30 03:40:07 +0100983 /* We don't need lock here; nobody else touches the iova range */
Alex Williamson3269ee02013-06-15 10:27:19 -0600984 dma_pte_free_level(domain, agaw_to_level(domain->agaw),
985 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +0100986
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700987 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +0100988 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700989 free_pgtable_page(domain->pgd);
990 domain->pgd = NULL;
991 }
992}
993
David Woodhouseea8ea462014-03-05 17:09:32 +0000994/* When a page at a given level is being unlinked from its parent, we don't
995 need to *modify* it at all. All we need to do is make a list of all the
996 pages which can be freed just as soon as we've flushed the IOTLB and we
997 know the hardware page-walk will no longer touch them.
998 The 'pte' argument is the *parent* PTE, pointing to the page that is to
999 be freed. */
1000static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1001 int level, struct dma_pte *pte,
1002 struct page *freelist)
1003{
1004 struct page *pg;
1005
1006 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1007 pg->freelist = freelist;
1008 freelist = pg;
1009
1010 if (level == 1)
1011 return freelist;
1012
Jiang Liuadeb2592014-04-09 10:20:39 +08001013 pte = page_address(pg);
1014 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001015 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1016 freelist = dma_pte_list_pagetables(domain, level - 1,
1017 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001018 pte++;
1019 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001020
1021 return freelist;
1022}
1023
1024static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1025 struct dma_pte *pte, unsigned long pfn,
1026 unsigned long start_pfn,
1027 unsigned long last_pfn,
1028 struct page *freelist)
1029{
1030 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1031
1032 pfn = max(start_pfn, pfn);
1033 pte = &pte[pfn_level_offset(pfn, level)];
1034
1035 do {
1036 unsigned long level_pfn;
1037
1038 if (!dma_pte_present(pte))
1039 goto next;
1040
1041 level_pfn = pfn & level_mask(level);
1042
1043 /* If range covers entire pagetable, free it */
1044 if (start_pfn <= level_pfn &&
1045 last_pfn >= level_pfn + level_size(level) - 1) {
1046 /* These suborbinate page tables are going away entirely. Don't
1047 bother to clear them; we're just going to *free* them. */
1048 if (level > 1 && !dma_pte_superpage(pte))
1049 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1050
1051 dma_clear_pte(pte);
1052 if (!first_pte)
1053 first_pte = pte;
1054 last_pte = pte;
1055 } else if (level > 1) {
1056 /* Recurse down into a level that isn't *entirely* obsolete */
1057 freelist = dma_pte_clear_level(domain, level - 1,
1058 phys_to_virt(dma_pte_addr(pte)),
1059 level_pfn, start_pfn, last_pfn,
1060 freelist);
1061 }
1062next:
1063 pfn += level_size(level);
1064 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1065
1066 if (first_pte)
1067 domain_flush_cache(domain, first_pte,
1068 (void *)++last_pte - (void *)first_pte);
1069
1070 return freelist;
1071}
1072
1073/* We can't just free the pages because the IOMMU may still be walking
1074 the page tables, and may have cached the intermediate levels. The
1075 pages can only be freed after the IOTLB flush has been done. */
1076struct page *domain_unmap(struct dmar_domain *domain,
1077 unsigned long start_pfn,
1078 unsigned long last_pfn)
1079{
David Woodhouseea8ea462014-03-05 17:09:32 +00001080 struct page *freelist = NULL;
1081
Jiang Liu162d1b12014-07-11 14:19:35 +08001082 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1083 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001084 BUG_ON(start_pfn > last_pfn);
1085
1086 /* we don't need lock here; nobody else touches the iova range */
1087 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1088 domain->pgd, 0, start_pfn, last_pfn, NULL);
1089
1090 /* free pgd */
1091 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1092 struct page *pgd_page = virt_to_page(domain->pgd);
1093 pgd_page->freelist = freelist;
1094 freelist = pgd_page;
1095
1096 domain->pgd = NULL;
1097 }
1098
1099 return freelist;
1100}
1101
1102void dma_free_pagelist(struct page *freelist)
1103{
1104 struct page *pg;
1105
1106 while ((pg = freelist)) {
1107 freelist = pg->freelist;
1108 free_pgtable_page(page_address(pg));
1109 }
1110}
1111
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001112/* iommu handling */
1113static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1114{
1115 struct root_entry *root;
1116 unsigned long flags;
1117
Suresh Siddha4c923d42009-10-02 11:01:24 -07001118 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001119 if (!root) {
1120 pr_err("IOMMU: allocating root entry for %s failed\n",
1121 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001122 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001123 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001124
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001125 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001126
1127 spin_lock_irqsave(&iommu->lock, flags);
1128 iommu->root_entry = root;
1129 spin_unlock_irqrestore(&iommu->lock, flags);
1130
1131 return 0;
1132}
1133
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001134static void iommu_set_root_entry(struct intel_iommu *iommu)
1135{
1136 void *addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001137 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001138 unsigned long flag;
1139
1140 addr = iommu->root_entry;
1141
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001142 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001143 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
1144
David Woodhousec416daa2009-05-10 20:30:58 +01001145 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001146
1147 /* Make sure hardware complete it */
1148 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001149 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001150
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001151 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001152}
1153
1154static void iommu_flush_write_buffer(struct intel_iommu *iommu)
1155{
1156 u32 val;
1157 unsigned long flag;
1158
David Woodhouse9af88142009-02-13 23:18:03 +00001159 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001160 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001161
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001162 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001163 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001164
1165 /* Make sure hardware complete it */
1166 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001167 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001168
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001169 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001170}
1171
1172/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001173static void __iommu_flush_context(struct intel_iommu *iommu,
1174 u16 did, u16 source_id, u8 function_mask,
1175 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001176{
1177 u64 val = 0;
1178 unsigned long flag;
1179
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001180 switch (type) {
1181 case DMA_CCMD_GLOBAL_INVL:
1182 val = DMA_CCMD_GLOBAL_INVL;
1183 break;
1184 case DMA_CCMD_DOMAIN_INVL:
1185 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1186 break;
1187 case DMA_CCMD_DEVICE_INVL:
1188 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1189 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1190 break;
1191 default:
1192 BUG();
1193 }
1194 val |= DMA_CCMD_ICC;
1195
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001196 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001197 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1198
1199 /* Make sure hardware complete it */
1200 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1201 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1202
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001203 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001204}
1205
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001206/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001207static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1208 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001209{
1210 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1211 u64 val = 0, val_iva = 0;
1212 unsigned long flag;
1213
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001214 switch (type) {
1215 case DMA_TLB_GLOBAL_FLUSH:
1216 /* global flush doesn't need set IVA_REG */
1217 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1218 break;
1219 case DMA_TLB_DSI_FLUSH:
1220 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1221 break;
1222 case DMA_TLB_PSI_FLUSH:
1223 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001224 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001225 val_iva = size_order | addr;
1226 break;
1227 default:
1228 BUG();
1229 }
1230 /* Note: set drain read/write */
1231#if 0
1232 /*
1233 * This is probably to be super secure.. Looks like we can
1234 * ignore it without any impact.
1235 */
1236 if (cap_read_drain(iommu->cap))
1237 val |= DMA_TLB_READ_DRAIN;
1238#endif
1239 if (cap_write_drain(iommu->cap))
1240 val |= DMA_TLB_WRITE_DRAIN;
1241
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001242 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001243 /* Note: Only uses first TLB reg currently */
1244 if (val_iva)
1245 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1246 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1247
1248 /* Make sure hardware complete it */
1249 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1250 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1251
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001252 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001253
1254 /* check IOTLB invalidation granularity */
1255 if (DMA_TLB_IAIG(val) == 0)
1256 printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
1257 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
1258 pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001259 (unsigned long long)DMA_TLB_IIRG(type),
1260 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001261}
1262
David Woodhouse64ae8922014-03-09 12:52:30 -07001263static struct device_domain_info *
1264iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1265 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001266{
Yu Zhao93a23a72009-05-18 13:51:37 +08001267 int found = 0;
1268 unsigned long flags;
1269 struct device_domain_info *info;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001270 struct pci_dev *pdev;
Yu Zhao93a23a72009-05-18 13:51:37 +08001271
1272 if (!ecap_dev_iotlb_support(iommu->ecap))
1273 return NULL;
1274
1275 if (!iommu->qi)
1276 return NULL;
1277
1278 spin_lock_irqsave(&device_domain_lock, flags);
1279 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001280 if (info->iommu == iommu && info->bus == bus &&
1281 info->devfn == devfn) {
Yu Zhao93a23a72009-05-18 13:51:37 +08001282 found = 1;
1283 break;
1284 }
1285 spin_unlock_irqrestore(&device_domain_lock, flags);
1286
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001287 if (!found || !info->dev || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001288 return NULL;
1289
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001290 pdev = to_pci_dev(info->dev);
1291
1292 if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
Yu Zhao93a23a72009-05-18 13:51:37 +08001293 return NULL;
1294
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001295 if (!dmar_find_matched_atsr_unit(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001296 return NULL;
1297
Yu Zhao93a23a72009-05-18 13:51:37 +08001298 return info;
1299}
1300
1301static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1302{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001303 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001304 return;
1305
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001306 pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
Yu Zhao93a23a72009-05-18 13:51:37 +08001307}
1308
1309static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1310{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001311 if (!info->dev || !dev_is_pci(info->dev) ||
1312 !pci_ats_enabled(to_pci_dev(info->dev)))
Yu Zhao93a23a72009-05-18 13:51:37 +08001313 return;
1314
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001315 pci_disable_ats(to_pci_dev(info->dev));
Yu Zhao93a23a72009-05-18 13:51:37 +08001316}
1317
1318static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1319 u64 addr, unsigned mask)
1320{
1321 u16 sid, qdep;
1322 unsigned long flags;
1323 struct device_domain_info *info;
1324
1325 spin_lock_irqsave(&device_domain_lock, flags);
1326 list_for_each_entry(info, &domain->devices, link) {
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001327 struct pci_dev *pdev;
1328 if (!info->dev || !dev_is_pci(info->dev))
1329 continue;
1330
1331 pdev = to_pci_dev(info->dev);
1332 if (!pci_ats_enabled(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001333 continue;
1334
1335 sid = info->bus << 8 | info->devfn;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001336 qdep = pci_ats_queue_depth(pdev);
Yu Zhao93a23a72009-05-18 13:51:37 +08001337 qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
1338 }
1339 spin_unlock_irqrestore(&device_domain_lock, flags);
1340}
1341
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001342static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
David Woodhouseea8ea462014-03-05 17:09:32 +00001343 unsigned long pfn, unsigned int pages, int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001344{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001345 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001346 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001347
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001348 BUG_ON(pages == 0);
1349
David Woodhouseea8ea462014-03-05 17:09:32 +00001350 if (ih)
1351 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001352 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001353 * Fallback to domain selective flush if no PSI support or the size is
1354 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001355 * PSI requires page size to be 2 ^ x, and the base address is naturally
1356 * aligned to the size
1357 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001358 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1359 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001360 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001361 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001362 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001363 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001364
1365 /*
Nadav Amit82653632010-04-01 13:24:40 +03001366 * In caching mode, changes of pages from non-present to present require
1367 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001368 */
Nadav Amit82653632010-04-01 13:24:40 +03001369 if (!cap_caching_mode(iommu->cap) || !map)
Yu Zhao93a23a72009-05-18 13:51:37 +08001370 iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001371}
1372
mark grossf8bab732008-02-08 04:18:38 -08001373static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1374{
1375 u32 pmen;
1376 unsigned long flags;
1377
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001378 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001379 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1380 pmen &= ~DMA_PMEN_EPM;
1381 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1382
1383 /* wait for the protected region status bit to clear */
1384 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1385 readl, !(pmen & DMA_PMEN_PRS), pmen);
1386
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001387 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001388}
1389
Jiang Liu2a41cce2014-07-11 14:19:33 +08001390static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001391{
1392 u32 sts;
1393 unsigned long flags;
1394
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001395 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001396 iommu->gcmd |= DMA_GCMD_TE;
1397 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001398
1399 /* Make sure hardware complete it */
1400 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001401 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001402
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001403 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001404}
1405
Jiang Liu2a41cce2014-07-11 14:19:33 +08001406static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001407{
1408 u32 sts;
1409 unsigned long flag;
1410
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001411 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001412 iommu->gcmd &= ~DMA_GCMD_TE;
1413 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1414
1415 /* Make sure hardware complete it */
1416 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001417 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001418
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001419 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001420}
1421
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001422
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001423static int iommu_init_domains(struct intel_iommu *iommu)
1424{
1425 unsigned long ndomains;
1426 unsigned long nlongs;
1427
1428 ndomains = cap_ndoms(iommu->cap);
Jiang Liu852bdb02014-01-06 14:18:11 +08001429 pr_debug("IOMMU%d: Number of Domains supported <%ld>\n",
1430 iommu->seq_id, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001431 nlongs = BITS_TO_LONGS(ndomains);
1432
Donald Dutile94a91b502009-08-20 16:51:34 -04001433 spin_lock_init(&iommu->lock);
1434
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001435 /* TBD: there might be 64K domains,
1436 * consider other allocation for future chip
1437 */
1438 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1439 if (!iommu->domain_ids) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001440 pr_err("IOMMU%d: allocating domain id array failed\n",
1441 iommu->seq_id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001442 return -ENOMEM;
1443 }
1444 iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
1445 GFP_KERNEL);
1446 if (!iommu->domains) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001447 pr_err("IOMMU%d: allocating domain array failed\n",
1448 iommu->seq_id);
1449 kfree(iommu->domain_ids);
1450 iommu->domain_ids = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001451 return -ENOMEM;
1452 }
1453
1454 /*
1455 * if Caching mode is set, then invalid translations are tagged
1456 * with domainid 0. Hence we need to pre-allocate it.
1457 */
1458 if (cap_caching_mode(iommu->cap))
1459 set_bit(0, iommu->domain_ids);
1460 return 0;
1461}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001462
Jiang Liuffebeb42014-11-09 22:48:02 +08001463static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001464{
1465 struct dmar_domain *domain;
Jiang Liu2a46ddf2014-07-11 14:19:30 +08001466 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001467
Donald Dutile94a91b502009-08-20 16:51:34 -04001468 if ((iommu->domains) && (iommu->domain_ids)) {
Akinobu Mitaa45946a2010-03-11 14:04:08 -08001469 for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
Jiang Liua4eaa862014-02-19 14:07:30 +08001470 /*
1471 * Domain id 0 is reserved for invalid translation
1472 * if hardware supports caching mode.
1473 */
1474 if (cap_caching_mode(iommu->cap) && i == 0)
1475 continue;
1476
Donald Dutile94a91b502009-08-20 16:51:34 -04001477 domain = iommu->domains[i];
1478 clear_bit(i, iommu->domain_ids);
Jiang Liu129ad282014-07-11 14:19:31 +08001479 if (domain_detach_iommu(domain, iommu) == 0 &&
1480 !domain_type_is_vm(domain))
Jiang Liu92d03cc2014-02-19 14:07:28 +08001481 domain_exit(domain);
Weidong Han5e98c4b2008-12-08 23:03:27 +08001482 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001483 }
1484
1485 if (iommu->gcmd & DMA_GCMD_TE)
1486 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001487}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001488
Jiang Liuffebeb42014-11-09 22:48:02 +08001489static void free_dmar_iommu(struct intel_iommu *iommu)
1490{
1491 if ((iommu->domains) && (iommu->domain_ids)) {
1492 kfree(iommu->domains);
1493 kfree(iommu->domain_ids);
1494 iommu->domains = NULL;
1495 iommu->domain_ids = NULL;
1496 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001497
Weidong Hand9630fe2008-12-08 11:06:32 +08001498 g_iommus[iommu->seq_id] = NULL;
1499
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001500 /* free context mapping */
1501 free_context_table(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001502}
1503
Jiang Liuab8dfe22014-07-11 14:19:27 +08001504static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001505{
Jiang Liu92d03cc2014-02-19 14:07:28 +08001506 /* domain id for virtual machine, it won't be set in context */
1507 static atomic_t vm_domid = ATOMIC_INIT(0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001508 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001509
1510 domain = alloc_domain_mem();
1511 if (!domain)
1512 return NULL;
1513
Jiang Liuab8dfe22014-07-11 14:19:27 +08001514 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001515 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001516 domain->flags = flags;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001517 spin_lock_init(&domain->iommu_lock);
1518 INIT_LIST_HEAD(&domain->devices);
Jiang Liuab8dfe22014-07-11 14:19:27 +08001519 if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
Jiang Liu92d03cc2014-02-19 14:07:28 +08001520 domain->id = atomic_inc_return(&vm_domid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001521
1522 return domain;
1523}
1524
Jiang Liufb170fb2014-07-11 14:19:28 +08001525static int __iommu_attach_domain(struct dmar_domain *domain,
1526 struct intel_iommu *iommu)
1527{
1528 int num;
1529 unsigned long ndomains;
1530
1531 ndomains = cap_ndoms(iommu->cap);
1532 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1533 if (num < ndomains) {
1534 set_bit(num, iommu->domain_ids);
1535 iommu->domains[num] = domain;
1536 } else {
1537 num = -ENOSPC;
1538 }
1539
1540 return num;
1541}
1542
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001543static int iommu_attach_domain(struct dmar_domain *domain,
1544 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001545{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001546 int num;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001547 unsigned long flags;
1548
Weidong Han8c11e792008-12-08 15:29:22 +08001549 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001550 num = __iommu_attach_domain(domain, iommu);
Jiang Liu44bde612014-07-11 14:19:29 +08001551 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001552 if (num < 0)
1553 pr_err("IOMMU: no free domain ids\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001554
Jiang Liufb170fb2014-07-11 14:19:28 +08001555 return num;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001556}
1557
Jiang Liu44bde612014-07-11 14:19:29 +08001558static int iommu_attach_vm_domain(struct dmar_domain *domain,
1559 struct intel_iommu *iommu)
1560{
1561 int num;
1562 unsigned long ndomains;
1563
1564 ndomains = cap_ndoms(iommu->cap);
1565 for_each_set_bit(num, iommu->domain_ids, ndomains)
1566 if (iommu->domains[num] == domain)
1567 return num;
1568
1569 return __iommu_attach_domain(domain, iommu);
1570}
1571
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001572static void iommu_detach_domain(struct dmar_domain *domain,
1573 struct intel_iommu *iommu)
1574{
1575 unsigned long flags;
1576 int num, ndomains;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001577
1578 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001579 if (domain_type_is_vm_or_si(domain)) {
1580 ndomains = cap_ndoms(iommu->cap);
1581 for_each_set_bit(num, iommu->domain_ids, ndomains) {
1582 if (iommu->domains[num] == domain) {
1583 clear_bit(num, iommu->domain_ids);
1584 iommu->domains[num] = NULL;
1585 break;
1586 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001587 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001588 } else {
1589 clear_bit(domain->id, iommu->domain_ids);
1590 iommu->domains[domain->id] = NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001591 }
Weidong Han8c11e792008-12-08 15:29:22 +08001592 spin_unlock_irqrestore(&iommu->lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001593}
1594
Jiang Liufb170fb2014-07-11 14:19:28 +08001595static void domain_attach_iommu(struct dmar_domain *domain,
1596 struct intel_iommu *iommu)
1597{
1598 unsigned long flags;
1599
1600 spin_lock_irqsave(&domain->iommu_lock, flags);
1601 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
1602 domain->iommu_count++;
1603 if (domain->iommu_count == 1)
1604 domain->nid = iommu->node;
1605 domain_update_iommu_cap(domain);
1606 }
1607 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1608}
1609
1610static int domain_detach_iommu(struct dmar_domain *domain,
1611 struct intel_iommu *iommu)
1612{
1613 unsigned long flags;
1614 int count = INT_MAX;
1615
1616 spin_lock_irqsave(&domain->iommu_lock, flags);
1617 if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
1618 count = --domain->iommu_count;
1619 domain_update_iommu_cap(domain);
1620 }
1621 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1622
1623 return count;
1624}
1625
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001626static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001627static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001628
Joseph Cihula51a63e62011-03-21 11:04:24 -07001629static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001630{
1631 struct pci_dev *pdev = NULL;
1632 struct iova *iova;
1633 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001634
David Millerf6611972008-02-06 01:36:23 -08001635 init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001636
Mark Gross8a443df2008-03-04 14:59:31 -08001637 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1638 &reserved_rbtree_key);
1639
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001640 /* IOAPIC ranges shouldn't be accessed by DMA */
1641 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1642 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001643 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001644 printk(KERN_ERR "Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001645 return -ENODEV;
1646 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001647
1648 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1649 for_each_pci_dev(pdev) {
1650 struct resource *r;
1651
1652 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1653 r = &pdev->resource[i];
1654 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1655 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001656 iova = reserve_iova(&reserved_iova_list,
1657 IOVA_PFN(r->start),
1658 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001659 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001660 printk(KERN_ERR "Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001661 return -ENODEV;
1662 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001663 }
1664 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001665 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001666}
1667
1668static void domain_reserve_special_ranges(struct dmar_domain *domain)
1669{
1670 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1671}
1672
1673static inline int guestwidth_to_adjustwidth(int gaw)
1674{
1675 int agaw;
1676 int r = (gaw - 12) % 9;
1677
1678 if (r == 0)
1679 agaw = gaw;
1680 else
1681 agaw = gaw + 9 - r;
1682 if (agaw > 64)
1683 agaw = 64;
1684 return agaw;
1685}
1686
1687static int domain_init(struct dmar_domain *domain, int guest_width)
1688{
1689 struct intel_iommu *iommu;
1690 int adjust_width, agaw;
1691 unsigned long sagaw;
1692
David Millerf6611972008-02-06 01:36:23 -08001693 init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001694 domain_reserve_special_ranges(domain);
1695
1696 /* calculate AGAW */
Weidong Han8c11e792008-12-08 15:29:22 +08001697 iommu = domain_get_iommu(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001698 if (guest_width > cap_mgaw(iommu->cap))
1699 guest_width = cap_mgaw(iommu->cap);
1700 domain->gaw = guest_width;
1701 adjust_width = guestwidth_to_adjustwidth(guest_width);
1702 agaw = width_to_agaw(adjust_width);
1703 sagaw = cap_sagaw(iommu->cap);
1704 if (!test_bit(agaw, &sagaw)) {
1705 /* hardware doesn't support it, choose a bigger one */
1706 pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
1707 agaw = find_next_bit(&sagaw, 5, agaw);
1708 if (agaw >= 5)
1709 return -ENODEV;
1710 }
1711 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001712
Weidong Han8e6040972008-12-08 15:49:06 +08001713 if (ecap_coherent(iommu->ecap))
1714 domain->iommu_coherency = 1;
1715 else
1716 domain->iommu_coherency = 0;
1717
Sheng Yang58c610b2009-03-18 15:33:05 +08001718 if (ecap_sc_support(iommu->ecap))
1719 domain->iommu_snooping = 1;
1720 else
1721 domain->iommu_snooping = 0;
1722
David Woodhouse214e39a2014-03-19 10:38:49 +00001723 if (intel_iommu_superpage)
1724 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1725 else
1726 domain->iommu_superpage = 0;
1727
Suresh Siddha4c923d42009-10-02 11:01:24 -07001728 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001729
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001730 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001731 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001732 if (!domain->pgd)
1733 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001734 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001735 return 0;
1736}
1737
1738static void domain_exit(struct dmar_domain *domain)
1739{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001740 struct dmar_drhd_unit *drhd;
1741 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00001742 struct page *freelist = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001743
1744 /* Domain 0 is reserved, so dont process it */
1745 if (!domain)
1746 return;
1747
Alex Williamson7b668352011-05-24 12:02:41 +01001748 /* Flush any lazy unmaps that may reference this domain */
1749 if (!intel_iommu_strict)
1750 flush_unmaps_timeout(0);
1751
Jiang Liu92d03cc2014-02-19 14:07:28 +08001752 /* remove associated devices */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001753 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001754
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001755 /* destroy iovas */
1756 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001757
David Woodhouseea8ea462014-03-05 17:09:32 +00001758 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001759
Jiang Liu92d03cc2014-02-19 14:07:28 +08001760 /* clear attached or cached domains */
Jiang Liu0e242612014-02-19 14:07:34 +08001761 rcu_read_lock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001762 for_each_active_iommu(iommu, drhd)
Jiang Liufb170fb2014-07-11 14:19:28 +08001763 iommu_detach_domain(domain, iommu);
Jiang Liu0e242612014-02-19 14:07:34 +08001764 rcu_read_unlock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001765
David Woodhouseea8ea462014-03-05 17:09:32 +00001766 dma_free_pagelist(freelist);
1767
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001768 free_domain_mem(domain);
1769}
1770
David Woodhouse64ae8922014-03-09 12:52:30 -07001771static int domain_context_mapping_one(struct dmar_domain *domain,
1772 struct intel_iommu *iommu,
1773 u8 bus, u8 devfn, int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001774{
1775 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001776 unsigned long flags;
Weidong Hanea6606b2008-12-08 23:08:15 +08001777 struct dma_pte *pgd;
Weidong Hanea6606b2008-12-08 23:08:15 +08001778 int id;
1779 int agaw;
Yu Zhao93a23a72009-05-18 13:51:37 +08001780 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001781
1782 pr_debug("Set context mapping for %02x:%02x.%d\n",
1783 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001784
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001785 BUG_ON(!domain->pgd);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001786 BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
1787 translation != CONTEXT_TT_MULTI_LEVEL);
Weidong Han5331fe62008-12-08 23:00:00 +08001788
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001789 context = device_to_context_entry(iommu, bus, devfn);
1790 if (!context)
1791 return -ENOMEM;
1792 spin_lock_irqsave(&iommu->lock, flags);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001793 if (context_present(context)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001794 spin_unlock_irqrestore(&iommu->lock, flags);
1795 return 0;
1796 }
1797
Weidong Hanea6606b2008-12-08 23:08:15 +08001798 id = domain->id;
1799 pgd = domain->pgd;
1800
Jiang Liuab8dfe22014-07-11 14:19:27 +08001801 if (domain_type_is_vm_or_si(domain)) {
Jiang Liu44bde612014-07-11 14:19:29 +08001802 if (domain_type_is_vm(domain)) {
1803 id = iommu_attach_vm_domain(domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08001804 if (id < 0) {
Weidong Hanea6606b2008-12-08 23:08:15 +08001805 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001806 pr_err("IOMMU: no free domain ids\n");
Weidong Hanea6606b2008-12-08 23:08:15 +08001807 return -EFAULT;
1808 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001809 }
1810
1811 /* Skip top levels of page tables for
1812 * iommu which has less agaw than default.
Chris Wright1672af12009-12-02 12:06:34 -08001813 * Unnecessary for PT mode.
Weidong Hanea6606b2008-12-08 23:08:15 +08001814 */
Chris Wright1672af12009-12-02 12:06:34 -08001815 if (translation != CONTEXT_TT_PASS_THROUGH) {
1816 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
1817 pgd = phys_to_virt(dma_pte_addr(pgd));
1818 if (!dma_pte_present(pgd)) {
1819 spin_unlock_irqrestore(&iommu->lock, flags);
1820 return -ENOMEM;
1821 }
Weidong Hanea6606b2008-12-08 23:08:15 +08001822 }
1823 }
1824 }
1825
1826 context_set_domain_id(context, id);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001827
Yu Zhao93a23a72009-05-18 13:51:37 +08001828 if (translation != CONTEXT_TT_PASS_THROUGH) {
David Woodhouse64ae8922014-03-09 12:52:30 -07001829 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
Yu Zhao93a23a72009-05-18 13:51:37 +08001830 translation = info ? CONTEXT_TT_DEV_IOTLB :
1831 CONTEXT_TT_MULTI_LEVEL;
1832 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001833 /*
1834 * In pass through mode, AW must be programmed to indicate the largest
1835 * AGAW value supported by hardware. And ASR is ignored by hardware.
1836 */
Yu Zhao93a23a72009-05-18 13:51:37 +08001837 if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001838 context_set_address_width(context, iommu->msagaw);
Yu Zhao93a23a72009-05-18 13:51:37 +08001839 else {
1840 context_set_address_root(context, virt_to_phys(pgd));
1841 context_set_address_width(context, iommu->agaw);
1842 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001843
1844 context_set_translation_type(context, translation);
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00001845 context_set_fault_enable(context);
1846 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08001847 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001848
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001849 /*
1850 * It's a non-present to present mapping. If hardware doesn't cache
1851 * non-present entry we only need to flush the write-buffer. If the
1852 * _does_ cache non-present entries, then it does so in the special
1853 * domain #0, which we have to flush:
1854 */
1855 if (cap_caching_mode(iommu->cap)) {
1856 iommu->flush.flush_context(iommu, 0,
1857 (((u16)bus) << 8) | devfn,
1858 DMA_CCMD_MASK_NOBIT,
1859 DMA_CCMD_DEVICE_INVL);
Jiang Liu18fd7792014-07-11 14:19:26 +08001860 iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001861 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001862 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001863 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001864 iommu_enable_dev_iotlb(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001865 spin_unlock_irqrestore(&iommu->lock, flags);
Weidong Hanc7151a82008-12-08 22:51:37 +08001866
Jiang Liufb170fb2014-07-11 14:19:28 +08001867 domain_attach_iommu(domain, iommu);
1868
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001869 return 0;
1870}
1871
Alex Williamson579305f2014-07-03 09:51:43 -06001872struct domain_context_mapping_data {
1873 struct dmar_domain *domain;
1874 struct intel_iommu *iommu;
1875 int translation;
1876};
1877
1878static int domain_context_mapping_cb(struct pci_dev *pdev,
1879 u16 alias, void *opaque)
1880{
1881 struct domain_context_mapping_data *data = opaque;
1882
1883 return domain_context_mapping_one(data->domain, data->iommu,
1884 PCI_BUS_NUM(alias), alias & 0xff,
1885 data->translation);
1886}
1887
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001888static int
David Woodhousee1f167f2014-03-09 15:24:46 -07001889domain_context_mapping(struct dmar_domain *domain, struct device *dev,
1890 int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001891{
David Woodhouse64ae8922014-03-09 12:52:30 -07001892 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001893 u8 bus, devfn;
Alex Williamson579305f2014-07-03 09:51:43 -06001894 struct domain_context_mapping_data data;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001895
David Woodhousee1f167f2014-03-09 15:24:46 -07001896 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07001897 if (!iommu)
1898 return -ENODEV;
1899
Alex Williamson579305f2014-07-03 09:51:43 -06001900 if (!dev_is_pci(dev))
1901 return domain_context_mapping_one(domain, iommu, bus, devfn,
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001902 translation);
Alex Williamson579305f2014-07-03 09:51:43 -06001903
1904 data.domain = domain;
1905 data.iommu = iommu;
1906 data.translation = translation;
1907
1908 return pci_for_each_dma_alias(to_pci_dev(dev),
1909 &domain_context_mapping_cb, &data);
1910}
1911
1912static int domain_context_mapped_cb(struct pci_dev *pdev,
1913 u16 alias, void *opaque)
1914{
1915 struct intel_iommu *iommu = opaque;
1916
1917 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001918}
1919
David Woodhousee1f167f2014-03-09 15:24:46 -07001920static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001921{
Weidong Han5331fe62008-12-08 23:00:00 +08001922 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07001923 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08001924
David Woodhousee1f167f2014-03-09 15:24:46 -07001925 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08001926 if (!iommu)
1927 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001928
Alex Williamson579305f2014-07-03 09:51:43 -06001929 if (!dev_is_pci(dev))
1930 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07001931
Alex Williamson579305f2014-07-03 09:51:43 -06001932 return !pci_for_each_dma_alias(to_pci_dev(dev),
1933 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001934}
1935
Fenghua Yuf5329592009-08-04 15:09:37 -07001936/* Returns a number of VTD pages, but aligned to MM page size */
1937static inline unsigned long aligned_nrpages(unsigned long host_addr,
1938 size_t size)
1939{
1940 host_addr &= ~PAGE_MASK;
1941 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
1942}
1943
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001944/* Return largest possible superpage level for a given mapping */
1945static inline int hardware_largepage_caps(struct dmar_domain *domain,
1946 unsigned long iov_pfn,
1947 unsigned long phy_pfn,
1948 unsigned long pages)
1949{
1950 int support, level = 1;
1951 unsigned long pfnmerge;
1952
1953 support = domain->iommu_superpage;
1954
1955 /* To use a large page, the virtual *and* physical addresses
1956 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
1957 of them will mean we have to use smaller pages. So just
1958 merge them and check both at once. */
1959 pfnmerge = iov_pfn | phy_pfn;
1960
1961 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
1962 pages >>= VTD_STRIDE_SHIFT;
1963 if (!pages)
1964 break;
1965 pfnmerge >>= VTD_STRIDE_SHIFT;
1966 level++;
1967 support--;
1968 }
1969 return level;
1970}
1971
David Woodhouse9051aa02009-06-29 12:30:54 +01001972static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
1973 struct scatterlist *sg, unsigned long phys_pfn,
1974 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01001975{
1976 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01001977 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08001978 unsigned long sg_res = 0;
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
Jiang Liu162d1b12014-07-11 14:19:35 +08001982 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01001983
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
Jiang Liucc4f14a2014-11-26 09:42:10 +08001989 if (!sg) {
1990 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01001991 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
1992 }
1993
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001994 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01001995 uint64_t tmp;
1996
David Woodhousee1605492009-06-29 11:17:38 +01001997 if (!sg_res) {
Fenghua Yuf5329592009-08-04 15:09:37 -07001998 sg_res = aligned_nrpages(sg->offset, sg->length);
David Woodhousee1605492009-06-29 11:17:38 +01001999 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
2000 sg->dma_length = sg->length;
2001 pteval = page_to_phys(sg_page(sg)) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002002 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002003 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002004
David Woodhousee1605492009-06-29 11:17:38 +01002005 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002006 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2007
David Woodhouse5cf0a762014-03-19 16:07:49 +00002008 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002009 if (!pte)
2010 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002011 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002012 if (largepage_lvl > 1) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002013 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002014 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2015 /*
2016 * Ensure that old small page tables are
2017 * removed to make room for superpage,
2018 * if they exist.
2019 */
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002020 dma_pte_free_pagetable(domain, iov_pfn,
Jiang Liud41a4ad2014-07-11 14:19:34 +08002021 iov_pfn + lvl_pages - 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002022 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002023 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002024 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002025
David Woodhousee1605492009-06-29 11:17:38 +01002026 }
2027 /* We don't need lock here, nobody else
2028 * touches the iova range
2029 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002030 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002031 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002032 static int dumps = 5;
David Woodhousec85994e2009-07-01 19:21:24 +01002033 printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2034 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002035 if (dumps) {
2036 dumps--;
2037 debug_dma_dump_mappings(NULL);
2038 }
2039 WARN_ON(1);
2040 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002041
2042 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2043
2044 BUG_ON(nr_pages < lvl_pages);
2045 BUG_ON(sg_res < lvl_pages);
2046
2047 nr_pages -= lvl_pages;
2048 iov_pfn += lvl_pages;
2049 phys_pfn += lvl_pages;
2050 pteval += lvl_pages * VTD_PAGE_SIZE;
2051 sg_res -= lvl_pages;
2052
2053 /* If the next PTE would be the first in a new page, then we
2054 need to flush the cache on the entries we've just written.
2055 And then we'll need to recalculate 'pte', so clear it and
2056 let it get set again in the if (!pte) block above.
2057
2058 If we're done (!nr_pages) we need to flush the cache too.
2059
2060 Also if we've been setting superpages, we may need to
2061 recalculate 'pte' and switch back to smaller pages for the
2062 end of the mapping, if the trailing size is not enough to
2063 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002064 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002065 if (!nr_pages || first_pte_in_page(pte) ||
2066 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002067 domain_flush_cache(domain, first_pte,
2068 (void *)pte - (void *)first_pte);
2069 pte = NULL;
2070 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002071
2072 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002073 sg = sg_next(sg);
2074 }
2075 return 0;
2076}
2077
David Woodhouse9051aa02009-06-29 12:30:54 +01002078static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2079 struct scatterlist *sg, unsigned long nr_pages,
2080 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002081{
David Woodhouse9051aa02009-06-29 12:30:54 +01002082 return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
2083}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002084
David Woodhouse9051aa02009-06-29 12:30:54 +01002085static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2086 unsigned long phys_pfn, unsigned long nr_pages,
2087 int prot)
2088{
2089 return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002090}
2091
Weidong Hanc7151a82008-12-08 22:51:37 +08002092static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002093{
Weidong Hanc7151a82008-12-08 22:51:37 +08002094 if (!iommu)
2095 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002096
2097 clear_context_table(iommu, bus, devfn);
2098 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002099 DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002100 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002101}
2102
David Woodhouse109b9b02012-05-25 17:43:02 +01002103static inline void unlink_domain_info(struct device_domain_info *info)
2104{
2105 assert_spin_locked(&device_domain_lock);
2106 list_del(&info->link);
2107 list_del(&info->global);
2108 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002109 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002110}
2111
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002112static void domain_remove_dev_info(struct dmar_domain *domain)
2113{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002114 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002115 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002116
2117 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wang3a74ca02014-05-20 20:37:47 +08002118 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhouse109b9b02012-05-25 17:43:02 +01002119 unlink_domain_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002120 spin_unlock_irqrestore(&device_domain_lock, flags);
2121
Yu Zhao93a23a72009-05-18 13:51:37 +08002122 iommu_disable_dev_iotlb(info);
David Woodhouse7c7faa12014-03-09 13:33:06 -07002123 iommu_detach_dev(info->iommu, info->bus, info->devfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002124
Jiang Liuab8dfe22014-07-11 14:19:27 +08002125 if (domain_type_is_vm(domain)) {
David Woodhouse7c7faa12014-03-09 13:33:06 -07002126 iommu_detach_dependent_devices(info->iommu, info->dev);
Jiang Liufb170fb2014-07-11 14:19:28 +08002127 domain_detach_iommu(domain, info->iommu);
Jiang Liu92d03cc2014-02-19 14:07:28 +08002128 }
2129
2130 free_devinfo_mem(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002131 spin_lock_irqsave(&device_domain_lock, flags);
2132 }
2133 spin_unlock_irqrestore(&device_domain_lock, flags);
2134}
2135
2136/*
2137 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002138 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002139 */
David Woodhouse1525a292014-03-06 16:19:30 +00002140static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002141{
2142 struct device_domain_info *info;
2143
2144 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002145 info = dev->archdata.iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002146 if (info)
2147 return info->domain;
2148 return NULL;
2149}
2150
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002151static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002152dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2153{
2154 struct device_domain_info *info;
2155
2156 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002157 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002158 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002159 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002160
2161 return NULL;
2162}
2163
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002164static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
David Woodhouse41e80dca2014-03-09 13:55:54 -07002165 int bus, int devfn,
David Woodhouseb718cd32014-03-09 13:11:33 -07002166 struct device *dev,
2167 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002168{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002169 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002170 struct device_domain_info *info;
2171 unsigned long flags;
2172
2173 info = alloc_devinfo_mem();
2174 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002175 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002176
Jiang Liu745f2582014-02-19 14:07:26 +08002177 info->bus = bus;
2178 info->devfn = devfn;
2179 info->dev = dev;
2180 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002181 info->iommu = iommu;
Jiang Liu745f2582014-02-19 14:07:26 +08002182
2183 spin_lock_irqsave(&device_domain_lock, flags);
2184 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002185 found = find_domain(dev);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002186 else {
2187 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002188 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002189 if (info2)
2190 found = info2->domain;
2191 }
Jiang Liu745f2582014-02-19 14:07:26 +08002192 if (found) {
2193 spin_unlock_irqrestore(&device_domain_lock, flags);
2194 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002195 /* Caller must free the original domain */
2196 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002197 }
2198
David Woodhouseb718cd32014-03-09 13:11:33 -07002199 list_add(&info->link, &domain->devices);
2200 list_add(&info->global, &device_domain_list);
2201 if (dev)
2202 dev->archdata.iommu = info;
2203 spin_unlock_irqrestore(&device_domain_lock, flags);
2204
2205 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002206}
2207
Alex Williamson579305f2014-07-03 09:51:43 -06002208static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2209{
2210 *(u16 *)opaque = alias;
2211 return 0;
2212}
2213
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002214/* domain is initialized */
David Woodhouse146922e2014-03-09 15:44:17 -07002215static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002216{
Alex Williamson579305f2014-07-03 09:51:43 -06002217 struct dmar_domain *domain, *tmp;
2218 struct intel_iommu *iommu;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002219 struct device_domain_info *info;
Alex Williamson579305f2014-07-03 09:51:43 -06002220 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002221 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002222 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002223
David Woodhouse146922e2014-03-09 15:44:17 -07002224 domain = find_domain(dev);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002225 if (domain)
2226 return domain;
2227
David Woodhouse146922e2014-03-09 15:44:17 -07002228 iommu = device_to_iommu(dev, &bus, &devfn);
2229 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002230 return NULL;
2231
2232 if (dev_is_pci(dev)) {
2233 struct pci_dev *pdev = to_pci_dev(dev);
2234
2235 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2236
2237 spin_lock_irqsave(&device_domain_lock, flags);
2238 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2239 PCI_BUS_NUM(dma_alias),
2240 dma_alias & 0xff);
2241 if (info) {
2242 iommu = info->iommu;
2243 domain = info->domain;
2244 }
2245 spin_unlock_irqrestore(&device_domain_lock, flags);
2246
2247 /* DMA alias already has a domain, uses it */
2248 if (info)
2249 goto found_domain;
2250 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002251
David Woodhouse146922e2014-03-09 15:44:17 -07002252 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002253 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002254 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002255 return NULL;
Jiang Liu44bde612014-07-11 14:19:29 +08002256 domain->id = iommu_attach_domain(domain, iommu);
2257 if (domain->id < 0) {
Alex Williamson2fe9723d2011-03-04 14:52:30 -07002258 free_domain_mem(domain);
Alex Williamson579305f2014-07-03 09:51:43 -06002259 return NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002260 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002261 domain_attach_iommu(domain, iommu);
Alex Williamson579305f2014-07-03 09:51:43 -06002262 if (domain_init(domain, gaw)) {
2263 domain_exit(domain);
2264 return NULL;
2265 }
2266
2267 /* register PCI DMA alias device */
2268 if (dev_is_pci(dev)) {
2269 tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2270 dma_alias & 0xff, NULL, domain);
2271
2272 if (!tmp || tmp != domain) {
2273 domain_exit(domain);
2274 domain = tmp;
2275 }
2276
David Woodhouseb718cd32014-03-09 13:11:33 -07002277 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002278 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002279 }
2280
2281found_domain:
Alex Williamson579305f2014-07-03 09:51:43 -06002282 tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
2283
2284 if (!tmp || tmp != domain) {
2285 domain_exit(domain);
2286 domain = tmp;
2287 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002288
2289 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002290}
2291
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002292static int iommu_identity_mapping;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002293#define IDENTMAP_ALL 1
2294#define IDENTMAP_GFX 2
2295#define IDENTMAP_AZALIA 4
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002296
David Woodhouseb2132032009-06-26 18:50:28 +01002297static int iommu_domain_identity_map(struct dmar_domain *domain,
2298 unsigned long long start,
2299 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002300{
David Woodhousec5395d52009-06-28 16:35:56 +01002301 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2302 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002303
David Woodhousec5395d52009-06-28 16:35:56 +01002304 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2305 dma_to_mm_pfn(last_vpfn))) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002306 printk(KERN_ERR "IOMMU: reserve iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002307 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002308 }
2309
David Woodhousec5395d52009-06-28 16:35:56 +01002310 pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
2311 start, end, domain->id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002312 /*
2313 * RMRR range might have overlap with physical memory range,
2314 * clear it first
2315 */
David Woodhousec5395d52009-06-28 16:35:56 +01002316 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002317
David Woodhousec5395d52009-06-28 16:35:56 +01002318 return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
2319 last_vpfn - first_vpfn + 1,
David Woodhouse61df7442009-06-28 11:55:58 +01002320 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002321}
2322
David Woodhouse0b9d9752014-03-09 15:48:15 -07002323static int iommu_prepare_identity_map(struct device *dev,
David Woodhouseb2132032009-06-26 18:50:28 +01002324 unsigned long long start,
2325 unsigned long long end)
2326{
2327 struct dmar_domain *domain;
2328 int ret;
2329
David Woodhouse0b9d9752014-03-09 15:48:15 -07002330 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
David Woodhouseb2132032009-06-26 18:50:28 +01002331 if (!domain)
2332 return -ENOMEM;
2333
David Woodhouse19943b02009-08-04 16:19:20 +01002334 /* For _hardware_ passthrough, don't bother. But for software
2335 passthrough, we do it anyway -- it may indicate a memory
2336 range which is reserved in E820, so which didn't get set
2337 up to start with in si_domain */
2338 if (domain == si_domain && hw_pass_through) {
2339 printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002340 dev_name(dev), start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002341 return 0;
2342 }
2343
2344 printk(KERN_INFO
2345 "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
David Woodhouse0b9d9752014-03-09 15:48:15 -07002346 dev_name(dev), start, end);
David Woodhouse2ff729f2009-08-26 14:25:41 +01002347
David Woodhouse5595b522009-12-02 09:21:55 +00002348 if (end < start) {
2349 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2350 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2351 dmi_get_system_info(DMI_BIOS_VENDOR),
2352 dmi_get_system_info(DMI_BIOS_VERSION),
2353 dmi_get_system_info(DMI_PRODUCT_VERSION));
2354 ret = -EIO;
2355 goto error;
2356 }
2357
David Woodhouse2ff729f2009-08-26 14:25:41 +01002358 if (end >> agaw_to_width(domain->agaw)) {
2359 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2360 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2361 agaw_to_width(domain->agaw),
2362 dmi_get_system_info(DMI_BIOS_VENDOR),
2363 dmi_get_system_info(DMI_BIOS_VERSION),
2364 dmi_get_system_info(DMI_PRODUCT_VERSION));
2365 ret = -EIO;
2366 goto error;
2367 }
David Woodhouse19943b02009-08-04 16:19:20 +01002368
David Woodhouseb2132032009-06-26 18:50:28 +01002369 ret = iommu_domain_identity_map(domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002370 if (ret)
2371 goto error;
2372
2373 /* context entry init */
David Woodhouse0b9d9752014-03-09 15:48:15 -07002374 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
David Woodhouseb2132032009-06-26 18:50:28 +01002375 if (ret)
2376 goto error;
2377
2378 return 0;
2379
2380 error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002381 domain_exit(domain);
2382 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002383}
2384
2385static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002386 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002387{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002388 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002389 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002390 return iommu_prepare_identity_map(dev, rmrr->base_address,
2391 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002392}
2393
Suresh Siddhad3f13812011-08-23 17:05:25 -07002394#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002395static inline void iommu_prepare_isa(void)
2396{
2397 struct pci_dev *pdev;
2398 int ret;
2399
2400 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2401 if (!pdev)
2402 return;
2403
David Woodhousec7ab48d2009-06-26 19:10:36 +01002404 printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002405 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002406
2407 if (ret)
David Woodhousec7ab48d2009-06-26 19:10:36 +01002408 printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
2409 "floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002410
Yijing Wang9b27e822014-05-20 20:37:52 +08002411 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002412}
2413#else
2414static inline void iommu_prepare_isa(void)
2415{
2416 return;
2417}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002418#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002419
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002420static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002421
Matt Kraai071e1372009-08-23 22:30:22 -07002422static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002423{
2424 struct dmar_drhd_unit *drhd;
2425 struct intel_iommu *iommu;
David Woodhousec7ab48d2009-06-26 19:10:36 +01002426 int nid, ret = 0;
Jiang Liu44bde612014-07-11 14:19:29 +08002427 bool first = true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002428
Jiang Liuab8dfe22014-07-11 14:19:27 +08002429 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002430 if (!si_domain)
2431 return -EFAULT;
2432
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002433 for_each_active_iommu(iommu, drhd) {
2434 ret = iommu_attach_domain(si_domain, iommu);
Jiang Liufb170fb2014-07-11 14:19:28 +08002435 if (ret < 0) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002436 domain_exit(si_domain);
2437 return -EFAULT;
Jiang Liu44bde612014-07-11 14:19:29 +08002438 } else if (first) {
2439 si_domain->id = ret;
2440 first = false;
2441 } else if (si_domain->id != ret) {
2442 domain_exit(si_domain);
2443 return -EFAULT;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002444 }
Jiang Liufb170fb2014-07-11 14:19:28 +08002445 domain_attach_iommu(si_domain, iommu);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002446 }
2447
2448 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2449 domain_exit(si_domain);
2450 return -EFAULT;
2451 }
2452
Jiang Liu9544c002014-01-06 14:18:13 +08002453 pr_debug("IOMMU: identity mapping domain is domain %d\n",
2454 si_domain->id);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002455
David Woodhouse19943b02009-08-04 16:19:20 +01002456 if (hw)
2457 return 0;
2458
David Woodhousec7ab48d2009-06-26 19:10:36 +01002459 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002460 unsigned long start_pfn, end_pfn;
2461 int i;
2462
2463 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2464 ret = iommu_domain_identity_map(si_domain,
2465 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2466 if (ret)
2467 return ret;
2468 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002469 }
2470
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002471 return 0;
2472}
2473
David Woodhouse9b226622014-03-09 14:03:28 -07002474static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002475{
2476 struct device_domain_info *info;
2477
2478 if (likely(!iommu_identity_mapping))
2479 return 0;
2480
David Woodhouse9b226622014-03-09 14:03:28 -07002481 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002482 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2483 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002484
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002485 return 0;
2486}
2487
2488static int domain_add_dev_info(struct dmar_domain *domain,
David Woodhouse5913c9b2014-03-09 16:27:31 -07002489 struct device *dev, int translation)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002490{
David Woodhouse0ac72662014-03-09 13:19:22 -07002491 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002492 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002493 u8 bus, devfn;
David Woodhouse5fe60f42009-08-09 10:53:41 +01002494 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002495
David Woodhouse5913c9b2014-03-09 16:27:31 -07002496 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002497 if (!iommu)
2498 return -ENODEV;
2499
David Woodhouse5913c9b2014-03-09 16:27:31 -07002500 ndomain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002501 if (ndomain != domain)
2502 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002503
David Woodhouse5913c9b2014-03-09 16:27:31 -07002504 ret = domain_context_mapping(domain, dev, translation);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002505 if (ret) {
David Woodhouse5913c9b2014-03-09 16:27:31 -07002506 domain_remove_one_dev_info(domain, dev);
David Woodhousee2ad23d2012-05-25 17:42:54 +01002507 return ret;
2508 }
2509
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002510 return 0;
2511}
2512
David Woodhouse0b9d9752014-03-09 15:48:15 -07002513static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002514{
2515 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002516 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002517 int i;
2518
Jiang Liu0e242612014-02-19 14:07:34 +08002519 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002520 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002521 /*
2522 * Return TRUE if this RMRR contains the device that
2523 * is passed in.
2524 */
2525 for_each_active_dev_scope(rmrr->devices,
2526 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002527 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002528 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002529 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002530 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002531 }
Jiang Liu0e242612014-02-19 14:07:34 +08002532 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002533 return false;
2534}
2535
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002536/*
2537 * There are a couple cases where we need to restrict the functionality of
2538 * devices associated with RMRRs. The first is when evaluating a device for
2539 * identity mapping because problems exist when devices are moved in and out
2540 * of domains and their respective RMRR information is lost. This means that
2541 * a device with associated RMRRs will never be in a "passthrough" domain.
2542 * The second is use of the device through the IOMMU API. This interface
2543 * expects to have full control of the IOVA space for the device. We cannot
2544 * satisfy both the requirement that RMRR access is maintained and have an
2545 * unencumbered IOVA space. We also have no ability to quiesce the device's
2546 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2547 * We therefore prevent devices associated with an RMRR from participating in
2548 * the IOMMU API, which eliminates them from device assignment.
2549 *
2550 * In both cases we assume that PCI USB devices with RMRRs have them largely
2551 * for historical reasons and that the RMRR space is not actively used post
2552 * boot. This exclusion may change if vendors begin to abuse it.
2553 */
2554static bool device_is_rmrr_locked(struct device *dev)
2555{
2556 if (!device_has_rmrr(dev))
2557 return false;
2558
2559 if (dev_is_pci(dev)) {
2560 struct pci_dev *pdev = to_pci_dev(dev);
2561
2562 if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
2563 return false;
2564 }
2565
2566 return true;
2567}
2568
David Woodhouse3bdb2592014-03-09 16:03:08 -07002569static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002570{
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002571
David Woodhouse3bdb2592014-03-09 16:03:08 -07002572 if (dev_is_pci(dev)) {
2573 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002574
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002575 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002576 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002577
David Woodhouse3bdb2592014-03-09 16:03:08 -07002578 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2579 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002580
David Woodhouse3bdb2592014-03-09 16:03:08 -07002581 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2582 return 1;
2583
2584 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2585 return 0;
2586
2587 /*
2588 * We want to start off with all devices in the 1:1 domain, and
2589 * take them out later if we find they can't access all of memory.
2590 *
2591 * However, we can't do this for PCI devices behind bridges,
2592 * because all PCI devices behind the same bridge will end up
2593 * with the same source-id on their transactions.
2594 *
2595 * Practically speaking, we can't change things around for these
2596 * devices at run-time, because we can't be sure there'll be no
2597 * DMA transactions in flight for any of their siblings.
2598 *
2599 * So PCI devices (unless they're on the root bus) as well as
2600 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2601 * the 1:1 domain, just in _case_ one of their siblings turns out
2602 * not to be able to map all of memory.
2603 */
2604 if (!pci_is_pcie(pdev)) {
2605 if (!pci_is_root_bus(pdev->bus))
2606 return 0;
2607 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2608 return 0;
2609 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2610 return 0;
2611 } else {
2612 if (device_has_rmrr(dev))
2613 return 0;
2614 }
David Woodhouse6941af22009-07-04 18:24:27 +01002615
David Woodhouse3dfc8132009-07-04 19:11:08 +01002616 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002617 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002618 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002619 * take them out of the 1:1 domain later.
2620 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002621 if (!startup) {
2622 /*
2623 * If the device's dma_mask is less than the system's memory
2624 * size then this is not a candidate for identity mapping.
2625 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002626 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002627
David Woodhouse3bdb2592014-03-09 16:03:08 -07002628 if (dev->coherent_dma_mask &&
2629 dev->coherent_dma_mask < dma_mask)
2630 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002631
David Woodhouse3bdb2592014-03-09 16:03:08 -07002632 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05002633 }
David Woodhouse6941af22009-07-04 18:24:27 +01002634
2635 return 1;
2636}
2637
David Woodhousecf04eee2014-03-21 16:49:04 +00002638static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
2639{
2640 int ret;
2641
2642 if (!iommu_should_identity_map(dev, 1))
2643 return 0;
2644
2645 ret = domain_add_dev_info(si_domain, dev,
2646 hw ? CONTEXT_TT_PASS_THROUGH :
2647 CONTEXT_TT_MULTI_LEVEL);
2648 if (!ret)
2649 pr_info("IOMMU: %s identity mapping for device %s\n",
2650 hw ? "hardware" : "software", dev_name(dev));
2651 else if (ret == -ENODEV)
2652 /* device not associated with an iommu */
2653 ret = 0;
2654
2655 return ret;
2656}
2657
2658
Matt Kraai071e1372009-08-23 22:30:22 -07002659static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002660{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002661 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00002662 struct dmar_drhd_unit *drhd;
2663 struct intel_iommu *iommu;
2664 struct device *dev;
2665 int i;
2666 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002667
David Woodhouse19943b02009-08-04 16:19:20 +01002668 ret = si_domain_init(hw);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002669 if (ret)
2670 return -EFAULT;
2671
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002672 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00002673 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
2674 if (ret)
2675 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002676 }
2677
David Woodhousecf04eee2014-03-21 16:49:04 +00002678 for_each_active_iommu(iommu, drhd)
2679 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
2680 struct acpi_device_physical_node *pn;
2681 struct acpi_device *adev;
2682
2683 if (dev->bus != &acpi_bus_type)
2684 continue;
2685
2686 adev= to_acpi_device(dev);
2687 mutex_lock(&adev->physical_node_lock);
2688 list_for_each_entry(pn, &adev->physical_node_list, node) {
2689 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
2690 if (ret)
2691 break;
2692 }
2693 mutex_unlock(&adev->physical_node_lock);
2694 if (ret)
2695 return ret;
2696 }
2697
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002698 return 0;
2699}
2700
Jiang Liuffebeb42014-11-09 22:48:02 +08002701static void intel_iommu_init_qi(struct intel_iommu *iommu)
2702{
2703 /*
2704 * Start from the sane iommu hardware state.
2705 * If the queued invalidation is already initialized by us
2706 * (for example, while enabling interrupt-remapping) then
2707 * we got the things already rolling from a sane state.
2708 */
2709 if (!iommu->qi) {
2710 /*
2711 * Clear any previous faults.
2712 */
2713 dmar_fault(-1, iommu);
2714 /*
2715 * Disable queued invalidation if supported and already enabled
2716 * before OS handover.
2717 */
2718 dmar_disable_qi(iommu);
2719 }
2720
2721 if (dmar_enable_qi(iommu)) {
2722 /*
2723 * Queued Invalidate not enabled, use Register Based Invalidate
2724 */
2725 iommu->flush.flush_context = __iommu_flush_context;
2726 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
2727 pr_info("IOMMU: %s using Register based invalidation\n",
2728 iommu->name);
2729 } else {
2730 iommu->flush.flush_context = qi_flush_context;
2731 iommu->flush.flush_iotlb = qi_flush_iotlb;
2732 pr_info("IOMMU: %s using Queued invalidation\n", iommu->name);
2733 }
2734}
2735
Joseph Cihulab7792602011-05-03 00:08:37 -07002736static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002737{
2738 struct dmar_drhd_unit *drhd;
2739 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002740 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002741 struct intel_iommu *iommu;
Suresh Siddha9d783ba2009-03-16 17:04:55 -07002742 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002743
2744 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002745 * for each drhd
2746 * allocate root
2747 * initialize and program root entry to not present
2748 * endfor
2749 */
2750 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08002751 /*
2752 * lock not needed as this is only incremented in the single
2753 * threaded kernel __init code path all other access are read
2754 * only
2755 */
Jiang Liu78d8e702014-11-09 22:47:57 +08002756 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08002757 g_num_of_iommus++;
2758 continue;
2759 }
2760 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
Jiang Liu78d8e702014-11-09 22:47:57 +08002761 DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08002762 }
2763
Jiang Liuffebeb42014-11-09 22:48:02 +08002764 /* Preallocate enough resources for IOMMU hot-addition */
2765 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
2766 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
2767
Weidong Hand9630fe2008-12-08 11:06:32 +08002768 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
2769 GFP_KERNEL);
2770 if (!g_iommus) {
2771 printk(KERN_ERR "Allocating global iommu array failed\n");
2772 ret = -ENOMEM;
2773 goto error;
2774 }
2775
mark gross80b20dd2008-04-18 13:53:58 -07002776 deferred_flush = kzalloc(g_num_of_iommus *
2777 sizeof(struct deferred_flush_tables), GFP_KERNEL);
2778 if (!deferred_flush) {
mark gross5e0d2a62008-03-04 15:22:08 -08002779 ret = -ENOMEM;
Jiang Liu989d51f2014-02-19 14:07:21 +08002780 goto free_g_iommus;
mark gross5e0d2a62008-03-04 15:22:08 -08002781 }
2782
Jiang Liu7c919772014-01-06 14:18:18 +08002783 for_each_active_iommu(iommu, drhd) {
Weidong Hand9630fe2008-12-08 11:06:32 +08002784 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002785
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002786 ret = iommu_init_domains(iommu);
2787 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002788 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002789
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002790 /*
2791 * TBD:
2792 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002793 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002794 */
2795 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002796 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002797 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002798 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01002799 hw_pass_through = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002800 }
2801
Jiang Liuffebeb42014-11-09 22:48:02 +08002802 for_each_active_iommu(iommu, drhd)
2803 intel_iommu_init_qi(iommu);
Youquan Songa77b67d2008-10-16 16:31:56 -07002804
David Woodhouse19943b02009-08-04 16:19:20 +01002805 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07002806 iommu_identity_mapping |= IDENTMAP_ALL;
2807
Suresh Siddhad3f13812011-08-23 17:05:25 -07002808#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07002809 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01002810#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07002811
2812 check_tylersburg_isoch();
2813
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002814 /*
2815 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002816 * identity mappings for rmrr, gfx, and isa and may fall back to static
2817 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002818 */
David Woodhouse19943b02009-08-04 16:19:20 +01002819 if (iommu_identity_mapping) {
2820 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
2821 if (ret) {
2822 printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08002823 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002824 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002825 }
David Woodhouse19943b02009-08-04 16:19:20 +01002826 /*
2827 * For each rmrr
2828 * for each dev attached to rmrr
2829 * do
2830 * locate drhd for dev, alloc domain for dev
2831 * allocate free domain
2832 * allocate page table entries for rmrr
2833 * if context not allocated for bus
2834 * allocate and init context
2835 * set present in root table for this bus
2836 * init context with domain, translation etc
2837 * endfor
2838 * endfor
2839 */
2840 printk(KERN_INFO "IOMMU: Setting RMRR:\n");
2841 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002842 /* some BIOS lists non-exist devices in DMAR table. */
2843 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00002844 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07002845 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01002846 if (ret)
2847 printk(KERN_ERR
2848 "IOMMU: mapping reserved region failed\n");
2849 }
2850 }
2851
2852 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002853
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002854 /*
2855 * for each drhd
2856 * enable fault log
2857 * global invalidate context cache
2858 * global invalidate iotlb
2859 * enable translation
2860 */
Jiang Liu7c919772014-01-06 14:18:18 +08002861 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07002862 if (drhd->ignored) {
2863 /*
2864 * we always have to disable PMRs or DMA may fail on
2865 * this device
2866 */
2867 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08002868 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002869 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07002870 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002871
2872 iommu_flush_write_buffer(iommu);
2873
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002874 ret = dmar_set_interrupt(iommu);
2875 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002876 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002877
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002878 iommu_set_root_entry(iommu);
2879
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002880 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002881 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Jiang Liu2a41cce2014-07-11 14:19:33 +08002882 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07002883 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002884 }
2885
2886 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08002887
2888free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08002889 for_each_active_iommu(iommu, drhd) {
2890 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08002891 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002892 }
Jiang Liu9bdc5312014-01-06 14:18:27 +08002893 kfree(deferred_flush);
Jiang Liu989d51f2014-02-19 14:07:21 +08002894free_g_iommus:
Weidong Hand9630fe2008-12-08 11:06:32 +08002895 kfree(g_iommus);
Jiang Liu989d51f2014-02-19 14:07:21 +08002896error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002897 return ret;
2898}
2899
David Woodhouse5a5e02a2009-07-04 09:35:44 +01002900/* This takes a number of _MM_ pages, not VTD pages */
David Woodhouse875764d2009-06-28 21:20:51 +01002901static struct iova *intel_alloc_iova(struct device *dev,
2902 struct dmar_domain *domain,
2903 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002904{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002905 struct iova *iova = NULL;
2906
David Woodhouse875764d2009-06-28 21:20:51 +01002907 /* Restrict dma_mask to the width that the iommu can handle */
2908 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
2909
2910 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002911 /*
2912 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07002913 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08002914 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002915 */
David Woodhouse875764d2009-06-28 21:20:51 +01002916 iova = alloc_iova(&domain->iovad, nrpages,
2917 IOVA_PFN(DMA_BIT_MASK(32)), 1);
2918 if (iova)
2919 return iova;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002920 }
David Woodhouse875764d2009-06-28 21:20:51 +01002921 iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
2922 if (unlikely(!iova)) {
2923 printk(KERN_ERR "Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07002924 nrpages, dev_name(dev));
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002925 return NULL;
2926 }
2927
2928 return iova;
2929}
2930
David Woodhoused4b709f2014-03-09 16:07:40 -07002931static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002932{
2933 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002934 int ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002935
David Woodhoused4b709f2014-03-09 16:07:40 -07002936 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002937 if (!domain) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002938 printk(KERN_ERR "Allocating domain for %s failed",
2939 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002940 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002941 }
2942
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002943 /* make sure context mapping is ok */
David Woodhoused4b709f2014-03-09 16:07:40 -07002944 if (unlikely(!domain_context_mapped(dev))) {
2945 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002946 if (ret) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002947 printk(KERN_ERR "Domain context map for %s failed",
2948 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002949 return NULL;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002950 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002951 }
2952
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002953 return domain;
2954}
2955
David Woodhoused4b709f2014-03-09 16:07:40 -07002956static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
David Woodhouse147202a2009-07-07 19:43:20 +01002957{
2958 struct device_domain_info *info;
2959
2960 /* No lock here, assumes no domain exit in normal case */
David Woodhoused4b709f2014-03-09 16:07:40 -07002961 info = dev->archdata.iommu;
David Woodhouse147202a2009-07-07 19:43:20 +01002962 if (likely(info))
2963 return info->domain;
2964
2965 return __get_valid_domain_for_dev(dev);
2966}
2967
David Woodhouse3d891942014-03-06 15:59:26 +00002968static int iommu_dummy(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002969{
David Woodhouse3d891942014-03-06 15:59:26 +00002970 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002971}
2972
David Woodhouseecb509e2014-03-09 16:29:55 -07002973/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01002974static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002975{
2976 int found;
2977
David Woodhouse3d891942014-03-06 15:59:26 +00002978 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002979 return 1;
2980
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002981 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002982 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002983
David Woodhouse9b226622014-03-09 14:03:28 -07002984 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002985 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07002986 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002987 return 1;
2988 else {
2989 /*
2990 * 32 bit DMA is removed from si_domain and fall back
2991 * to non-identity mapping.
2992 */
David Woodhousebf9c9ed2014-03-09 16:19:13 -07002993 domain_remove_one_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002994 printk(KERN_INFO "32bit %s uses non-identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07002995 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002996 return 0;
2997 }
2998 } else {
2999 /*
3000 * In case of a detached 64 bit DMA device from vm, the device
3001 * is put into si_domain for identity mapping.
3002 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003003 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003004 int ret;
David Woodhouse5913c9b2014-03-09 16:27:31 -07003005 ret = domain_add_dev_info(si_domain, dev,
David Woodhouse5fe60f42009-08-09 10:53:41 +01003006 hw_pass_through ?
3007 CONTEXT_TT_PASS_THROUGH :
3008 CONTEXT_TT_MULTI_LEVEL);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003009 if (!ret) {
3010 printk(KERN_INFO "64bit %s uses identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07003011 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003012 return 1;
3013 }
3014 }
3015 }
3016
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003017 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003018}
3019
David Woodhouse5040a912014-03-09 16:14:00 -07003020static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003021 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003022{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003023 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003024 phys_addr_t start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003025 struct iova *iova;
3026 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003027 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003028 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003029 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003030
3031 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003032
David Woodhouse5040a912014-03-09 16:14:00 -07003033 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003034 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003035
David Woodhouse5040a912014-03-09 16:14:00 -07003036 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003037 if (!domain)
3038 return 0;
3039
Weidong Han8c11e792008-12-08 15:29:22 +08003040 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003041 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003042
David Woodhouse5040a912014-03-09 16:14:00 -07003043 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003044 if (!iova)
3045 goto error;
3046
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003047 /*
3048 * Check if DMAR supports zero-length reads on write only
3049 * mappings..
3050 */
3051 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003052 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003053 prot |= DMA_PTE_READ;
3054 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3055 prot |= DMA_PTE_WRITE;
3056 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003057 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003058 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003059 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003060 * is not a big problem
3061 */
David Woodhouse0ab36de2009-06-28 14:01:43 +01003062 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003063 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003064 if (ret)
3065 goto error;
3066
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003067 /* it's a non-present to present mapping. Only flush if caching mode */
3068 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003069 iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003070 else
Weidong Han8c11e792008-12-08 15:29:22 +08003071 iommu_flush_write_buffer(iommu);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003072
David Woodhouse03d6a242009-06-28 15:33:46 +01003073 start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
3074 start_paddr += paddr & ~PAGE_MASK;
3075 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003076
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003077error:
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003078 if (iova)
3079 __free_iova(&domain->iovad, iova);
David Woodhouse4cf2e752009-02-11 17:23:43 +00003080 printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003081 dev_name(dev), size, (unsigned long long)paddr, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003082 return 0;
3083}
3084
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003085static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3086 unsigned long offset, size_t size,
3087 enum dma_data_direction dir,
3088 struct dma_attrs *attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003089{
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003090 return __intel_map_single(dev, page_to_phys(page) + offset, size,
David Woodhouse46333e32014-03-10 20:01:21 -07003091 dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003092}
3093
mark gross5e0d2a62008-03-04 15:22:08 -08003094static void flush_unmaps(void)
3095{
mark gross80b20dd2008-04-18 13:53:58 -07003096 int i, j;
mark gross5e0d2a62008-03-04 15:22:08 -08003097
mark gross5e0d2a62008-03-04 15:22:08 -08003098 timer_on = 0;
3099
3100 /* just flush them all */
3101 for (i = 0; i < g_num_of_iommus; i++) {
Weidong Hana2bb8452008-12-08 11:24:12 +08003102 struct intel_iommu *iommu = g_iommus[i];
3103 if (!iommu)
3104 continue;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003105
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003106 if (!deferred_flush[i].next)
3107 continue;
3108
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003109 /* In caching mode, global flushes turn emulation expensive */
3110 if (!cap_caching_mode(iommu->cap))
3111 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
Yu Zhao93a23a72009-05-18 13:51:37 +08003112 DMA_TLB_GLOBAL_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003113 for (j = 0; j < deferred_flush[i].next; j++) {
Yu Zhao93a23a72009-05-18 13:51:37 +08003114 unsigned long mask;
3115 struct iova *iova = deferred_flush[i].iova[j];
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003116 struct dmar_domain *domain = deferred_flush[i].domain[j];
Yu Zhao93a23a72009-05-18 13:51:37 +08003117
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003118 /* On real hardware multiple invalidations are expensive */
3119 if (cap_caching_mode(iommu->cap))
3120 iommu_flush_iotlb_psi(iommu, domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08003121 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00003122 !deferred_flush[i].freelist[j], 0);
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003123 else {
Jiang Liua156ef92014-07-11 14:19:36 +08003124 mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003125 iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
3126 (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
3127 }
Yu Zhao93a23a72009-05-18 13:51:37 +08003128 __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003129 if (deferred_flush[i].freelist[j])
3130 dma_free_pagelist(deferred_flush[i].freelist[j]);
mark gross80b20dd2008-04-18 13:53:58 -07003131 }
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003132 deferred_flush[i].next = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003133 }
3134
mark gross5e0d2a62008-03-04 15:22:08 -08003135 list_size = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003136}
3137
3138static void flush_unmaps_timeout(unsigned long data)
3139{
mark gross80b20dd2008-04-18 13:53:58 -07003140 unsigned long flags;
3141
3142 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003143 flush_unmaps();
mark gross80b20dd2008-04-18 13:53:58 -07003144 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003145}
3146
David Woodhouseea8ea462014-03-05 17:09:32 +00003147static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist)
mark gross5e0d2a62008-03-04 15:22:08 -08003148{
3149 unsigned long flags;
mark gross80b20dd2008-04-18 13:53:58 -07003150 int next, iommu_id;
Weidong Han8c11e792008-12-08 15:29:22 +08003151 struct intel_iommu *iommu;
mark gross5e0d2a62008-03-04 15:22:08 -08003152
3153 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross80b20dd2008-04-18 13:53:58 -07003154 if (list_size == HIGH_WATER_MARK)
3155 flush_unmaps();
3156
Weidong Han8c11e792008-12-08 15:29:22 +08003157 iommu = domain_get_iommu(dom);
3158 iommu_id = iommu->seq_id;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003159
mark gross80b20dd2008-04-18 13:53:58 -07003160 next = deferred_flush[iommu_id].next;
3161 deferred_flush[iommu_id].domain[next] = dom;
3162 deferred_flush[iommu_id].iova[next] = iova;
David Woodhouseea8ea462014-03-05 17:09:32 +00003163 deferred_flush[iommu_id].freelist[next] = freelist;
mark gross80b20dd2008-04-18 13:53:58 -07003164 deferred_flush[iommu_id].next++;
mark gross5e0d2a62008-03-04 15:22:08 -08003165
3166 if (!timer_on) {
3167 mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
3168 timer_on = 1;
3169 }
3170 list_size++;
3171 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
3172}
3173
Jiang Liud41a4ad2014-07-11 14:19:34 +08003174static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003175{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003176 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003177 unsigned long start_pfn, last_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003178 struct iova *iova;
Weidong Han8c11e792008-12-08 15:29:22 +08003179 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003180 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003181
David Woodhouse73676832009-07-04 14:08:36 +01003182 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003183 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003184
David Woodhouse1525a292014-03-06 16:19:30 +00003185 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003186 BUG_ON(!domain);
3187
Weidong Han8c11e792008-12-08 15:29:22 +08003188 iommu = domain_get_iommu(domain);
3189
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003190 iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
David Woodhouse85b98272009-07-01 19:27:53 +01003191 if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
3192 (unsigned long long)dev_addr))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003193 return;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003194
David Woodhoused794dc92009-06-28 00:27:49 +01003195 start_pfn = mm_to_dma_pfn(iova->pfn_lo);
3196 last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003197
David Woodhoused794dc92009-06-28 00:27:49 +01003198 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003199 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003200
David Woodhouseea8ea462014-03-05 17:09:32 +00003201 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003202
mark gross5e0d2a62008-03-04 15:22:08 -08003203 if (intel_iommu_strict) {
David Woodhouse03d6a242009-06-28 15:33:46 +01003204 iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
David Woodhouseea8ea462014-03-05 17:09:32 +00003205 last_pfn - start_pfn + 1, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003206 /* free iova */
3207 __free_iova(&domain->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003208 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003209 } else {
David Woodhouseea8ea462014-03-05 17:09:32 +00003210 add_unmap(domain, iova, freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003211 /*
3212 * queue up the release of the unmap to save the 1/6th of the
3213 * cpu used up by the iotlb flush operation...
3214 */
mark gross5e0d2a62008-03-04 15:22:08 -08003215 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003216}
3217
Jiang Liud41a4ad2014-07-11 14:19:34 +08003218static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3219 size_t size, enum dma_data_direction dir,
3220 struct dma_attrs *attrs)
3221{
3222 intel_unmap(dev, dev_addr);
3223}
3224
David Woodhouse5040a912014-03-09 16:14:00 -07003225static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003226 dma_addr_t *dma_handle, gfp_t flags,
3227 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003228{
Akinobu Mita36746432014-06-04 16:06:51 -07003229 struct page *page = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003230 int order;
3231
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003232 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003233 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003234
David Woodhouse5040a912014-03-09 16:14:00 -07003235 if (!iommu_no_mapping(dev))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003236 flags &= ~(GFP_DMA | GFP_DMA32);
David Woodhouse5040a912014-03-09 16:14:00 -07003237 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3238 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003239 flags |= GFP_DMA;
3240 else
3241 flags |= GFP_DMA32;
3242 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003243
Akinobu Mita36746432014-06-04 16:06:51 -07003244 if (flags & __GFP_WAIT) {
3245 unsigned int count = size >> PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003246
Akinobu Mita36746432014-06-04 16:06:51 -07003247 page = dma_alloc_from_contiguous(dev, count, order);
3248 if (page && iommu_no_mapping(dev) &&
3249 page_to_phys(page) + size > dev->coherent_dma_mask) {
3250 dma_release_from_contiguous(dev, page, count);
3251 page = NULL;
3252 }
3253 }
3254
3255 if (!page)
3256 page = alloc_pages(flags, order);
3257 if (!page)
3258 return NULL;
3259 memset(page_address(page), 0, size);
3260
3261 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003262 DMA_BIDIRECTIONAL,
David Woodhouse5040a912014-03-09 16:14:00 -07003263 dev->coherent_dma_mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003264 if (*dma_handle)
Akinobu Mita36746432014-06-04 16:06:51 -07003265 return page_address(page);
3266 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3267 __free_pages(page, order);
3268
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003269 return NULL;
3270}
3271
David Woodhouse5040a912014-03-09 16:14:00 -07003272static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003273 dma_addr_t dma_handle, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003274{
3275 int order;
Akinobu Mita36746432014-06-04 16:06:51 -07003276 struct page *page = virt_to_page(vaddr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003277
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003278 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003279 order = get_order(size);
3280
Jiang Liud41a4ad2014-07-11 14:19:34 +08003281 intel_unmap(dev, dma_handle);
Akinobu Mita36746432014-06-04 16:06:51 -07003282 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3283 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003284}
3285
David Woodhouse5040a912014-03-09 16:14:00 -07003286static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003287 int nelems, enum dma_data_direction dir,
3288 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003289{
Jiang Liud41a4ad2014-07-11 14:19:34 +08003290 intel_unmap(dev, sglist[0].dma_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003291}
3292
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003293static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003294 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003295{
3296 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003297 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003298
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003299 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003300 BUG_ON(!sg_page(sg));
David Woodhouse4cf2e752009-02-11 17:23:43 +00003301 sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003302 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003303 }
3304 return nelems;
3305}
3306
David Woodhouse5040a912014-03-09 16:14:00 -07003307static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003308 enum dma_data_direction dir, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003309{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003310 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003311 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003312 size_t size = 0;
3313 int prot = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003314 struct iova *iova = NULL;
3315 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003316 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003317 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003318 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003319
3320 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003321 if (iommu_no_mapping(dev))
3322 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003323
David Woodhouse5040a912014-03-09 16:14:00 -07003324 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003325 if (!domain)
3326 return 0;
3327
Weidong Han8c11e792008-12-08 15:29:22 +08003328 iommu = domain_get_iommu(domain);
3329
David Woodhouseb536d242009-06-28 14:49:31 +01003330 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003331 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003332
David Woodhouse5040a912014-03-09 16:14:00 -07003333 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
3334 *dev->dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003335 if (!iova) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003336 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003337 return 0;
3338 }
3339
3340 /*
3341 * Check if DMAR supports zero-length reads on write only
3342 * mappings..
3343 */
3344 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003345 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003346 prot |= DMA_PTE_READ;
3347 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3348 prot |= DMA_PTE_WRITE;
3349
David Woodhouseb536d242009-06-28 14:49:31 +01003350 start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
David Woodhousee1605492009-06-29 11:17:38 +01003351
Fenghua Yuf5329592009-08-04 15:09:37 -07003352 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003353 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003354 dma_pte_free_pagetable(domain, start_vpfn,
3355 start_vpfn + size - 1);
David Woodhousee1605492009-06-29 11:17:38 +01003356 __free_iova(&domain->iovad, iova);
3357 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003358 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003359
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003360 /* it's a non-present to present mapping. Only flush if caching mode */
3361 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003362 iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003363 else
Weidong Han8c11e792008-12-08 15:29:22 +08003364 iommu_flush_write_buffer(iommu);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003365
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003366 return nelems;
3367}
3368
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003369static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
3370{
3371 return !dma_addr;
3372}
3373
FUJITA Tomonori160c1d82009-01-05 23:59:02 +09003374struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003375 .alloc = intel_alloc_coherent,
3376 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003377 .map_sg = intel_map_sg,
3378 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003379 .map_page = intel_map_page,
3380 .unmap_page = intel_unmap_page,
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003381 .mapping_error = intel_mapping_error,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003382};
3383
3384static inline int iommu_domain_cache_init(void)
3385{
3386 int ret = 0;
3387
3388 iommu_domain_cache = kmem_cache_create("iommu_domain",
3389 sizeof(struct dmar_domain),
3390 0,
3391 SLAB_HWCACHE_ALIGN,
3392
3393 NULL);
3394 if (!iommu_domain_cache) {
3395 printk(KERN_ERR "Couldn't create iommu_domain cache\n");
3396 ret = -ENOMEM;
3397 }
3398
3399 return ret;
3400}
3401
3402static inline int iommu_devinfo_cache_init(void)
3403{
3404 int ret = 0;
3405
3406 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3407 sizeof(struct device_domain_info),
3408 0,
3409 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003410 NULL);
3411 if (!iommu_devinfo_cache) {
3412 printk(KERN_ERR "Couldn't create devinfo cache\n");
3413 ret = -ENOMEM;
3414 }
3415
3416 return ret;
3417}
3418
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003419static int __init iommu_init_mempool(void)
3420{
3421 int ret;
3422 ret = iommu_iova_cache_init();
3423 if (ret)
3424 return ret;
3425
3426 ret = iommu_domain_cache_init();
3427 if (ret)
3428 goto domain_error;
3429
3430 ret = iommu_devinfo_cache_init();
3431 if (!ret)
3432 return ret;
3433
3434 kmem_cache_destroy(iommu_domain_cache);
3435domain_error:
Robin Murphy85b45452015-01-12 17:51:14 +00003436 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003437
3438 return -ENOMEM;
3439}
3440
3441static void __init iommu_exit_mempool(void)
3442{
3443 kmem_cache_destroy(iommu_devinfo_cache);
3444 kmem_cache_destroy(iommu_domain_cache);
Robin Murphy85b45452015-01-12 17:51:14 +00003445 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003446}
3447
Dan Williams556ab452010-07-23 15:47:56 -07003448static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3449{
3450 struct dmar_drhd_unit *drhd;
3451 u32 vtbar;
3452 int rc;
3453
3454 /* We know that this device on this chipset has its own IOMMU.
3455 * If we find it under a different IOMMU, then the BIOS is lying
3456 * to us. Hope that the IOMMU for this device is actually
3457 * disabled, and it needs no translation...
3458 */
3459 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3460 if (rc) {
3461 /* "can't" happen */
3462 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3463 return;
3464 }
3465 vtbar &= 0xffff0000;
3466
3467 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3468 drhd = dmar_find_matched_drhd_unit(pdev);
3469 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3470 TAINT_FIRMWARE_WORKAROUND,
3471 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3472 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3473}
3474DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3475
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003476static void __init init_no_remapping_devices(void)
3477{
3478 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003479 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003480 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003481
3482 for_each_drhd_unit(drhd) {
3483 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003484 for_each_active_dev_scope(drhd->devices,
3485 drhd->devices_cnt, i, dev)
3486 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003487 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003488 if (i == drhd->devices_cnt)
3489 drhd->ignored = 1;
3490 }
3491 }
3492
Jiang Liu7c919772014-01-06 14:18:18 +08003493 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003494 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003495 continue;
3496
Jiang Liub683b232014-02-19 14:07:32 +08003497 for_each_active_dev_scope(drhd->devices,
3498 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003499 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003500 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003501 if (i < drhd->devices_cnt)
3502 continue;
3503
David Woodhousec0771df2011-10-14 20:59:46 +01003504 /* This IOMMU has *only* gfx devices. Either bypass it or
3505 set the gfx_mapped flag, as appropriate */
3506 if (dmar_map_gfx) {
3507 intel_iommu_gfx_mapped = 1;
3508 } else {
3509 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003510 for_each_active_dev_scope(drhd->devices,
3511 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003512 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003513 }
3514 }
3515}
3516
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003517#ifdef CONFIG_SUSPEND
3518static int init_iommu_hw(void)
3519{
3520 struct dmar_drhd_unit *drhd;
3521 struct intel_iommu *iommu = NULL;
3522
3523 for_each_active_iommu(iommu, drhd)
3524 if (iommu->qi)
3525 dmar_reenable_qi(iommu);
3526
Joseph Cihulab7792602011-05-03 00:08:37 -07003527 for_each_iommu(iommu, drhd) {
3528 if (drhd->ignored) {
3529 /*
3530 * we always have to disable PMRs or DMA may fail on
3531 * this device
3532 */
3533 if (force_on)
3534 iommu_disable_protect_mem_regions(iommu);
3535 continue;
3536 }
3537
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003538 iommu_flush_write_buffer(iommu);
3539
3540 iommu_set_root_entry(iommu);
3541
3542 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003543 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003544 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3545 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003546 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003547 }
3548
3549 return 0;
3550}
3551
3552static void iommu_flush_all(void)
3553{
3554 struct dmar_drhd_unit *drhd;
3555 struct intel_iommu *iommu;
3556
3557 for_each_active_iommu(iommu, drhd) {
3558 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003559 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003560 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003561 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003562 }
3563}
3564
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003565static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003566{
3567 struct dmar_drhd_unit *drhd;
3568 struct intel_iommu *iommu = NULL;
3569 unsigned long flag;
3570
3571 for_each_active_iommu(iommu, drhd) {
3572 iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
3573 GFP_ATOMIC);
3574 if (!iommu->iommu_state)
3575 goto nomem;
3576 }
3577
3578 iommu_flush_all();
3579
3580 for_each_active_iommu(iommu, drhd) {
3581 iommu_disable_translation(iommu);
3582
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003583 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003584
3585 iommu->iommu_state[SR_DMAR_FECTL_REG] =
3586 readl(iommu->reg + DMAR_FECTL_REG);
3587 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
3588 readl(iommu->reg + DMAR_FEDATA_REG);
3589 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
3590 readl(iommu->reg + DMAR_FEADDR_REG);
3591 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
3592 readl(iommu->reg + DMAR_FEUADDR_REG);
3593
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003594 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003595 }
3596 return 0;
3597
3598nomem:
3599 for_each_active_iommu(iommu, drhd)
3600 kfree(iommu->iommu_state);
3601
3602 return -ENOMEM;
3603}
3604
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003605static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003606{
3607 struct dmar_drhd_unit *drhd;
3608 struct intel_iommu *iommu = NULL;
3609 unsigned long flag;
3610
3611 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07003612 if (force_on)
3613 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
3614 else
3615 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003616 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003617 }
3618
3619 for_each_active_iommu(iommu, drhd) {
3620
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003621 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003622
3623 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
3624 iommu->reg + DMAR_FECTL_REG);
3625 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
3626 iommu->reg + DMAR_FEDATA_REG);
3627 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
3628 iommu->reg + DMAR_FEADDR_REG);
3629 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
3630 iommu->reg + DMAR_FEUADDR_REG);
3631
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003632 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003633 }
3634
3635 for_each_active_iommu(iommu, drhd)
3636 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003637}
3638
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003639static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003640 .resume = iommu_resume,
3641 .suspend = iommu_suspend,
3642};
3643
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003644static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003645{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003646 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003647}
3648
3649#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02003650static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003651#endif /* CONFIG_PM */
3652
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003653
Jiang Liuc2a0b532014-11-09 22:47:56 +08003654int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003655{
3656 struct acpi_dmar_reserved_memory *rmrr;
3657 struct dmar_rmrr_unit *rmrru;
3658
3659 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
3660 if (!rmrru)
3661 return -ENOMEM;
3662
3663 rmrru->hdr = header;
3664 rmrr = (struct acpi_dmar_reserved_memory *)header;
3665 rmrru->base_address = rmrr->base_address;
3666 rmrru->end_address = rmrr->end_address;
Jiang Liu2e455282014-02-19 14:07:36 +08003667 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
3668 ((void *)rmrr) + rmrr->header.length,
3669 &rmrru->devices_cnt);
3670 if (rmrru->devices_cnt && rmrru->devices == NULL) {
3671 kfree(rmrru);
3672 return -ENOMEM;
3673 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003674
Jiang Liu2e455282014-02-19 14:07:36 +08003675 list_add(&rmrru->list, &dmar_rmrr_units);
3676
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003677 return 0;
3678}
3679
Jiang Liu6b197242014-11-09 22:47:58 +08003680static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
3681{
3682 struct dmar_atsr_unit *atsru;
3683 struct acpi_dmar_atsr *tmp;
3684
3685 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3686 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
3687 if (atsr->segment != tmp->segment)
3688 continue;
3689 if (atsr->header.length != tmp->header.length)
3690 continue;
3691 if (memcmp(atsr, tmp, atsr->header.length) == 0)
3692 return atsru;
3693 }
3694
3695 return NULL;
3696}
3697
3698int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003699{
3700 struct acpi_dmar_atsr *atsr;
3701 struct dmar_atsr_unit *atsru;
3702
Jiang Liu6b197242014-11-09 22:47:58 +08003703 if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
3704 return 0;
3705
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003706 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08003707 atsru = dmar_find_atsr(atsr);
3708 if (atsru)
3709 return 0;
3710
3711 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003712 if (!atsru)
3713 return -ENOMEM;
3714
Jiang Liu6b197242014-11-09 22:47:58 +08003715 /*
3716 * If memory is allocated from slab by ACPI _DSM method, we need to
3717 * copy the memory content because the memory buffer will be freed
3718 * on return.
3719 */
3720 atsru->hdr = (void *)(atsru + 1);
3721 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003722 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08003723 if (!atsru->include_all) {
3724 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
3725 (void *)atsr + atsr->header.length,
3726 &atsru->devices_cnt);
3727 if (atsru->devices_cnt && atsru->devices == NULL) {
3728 kfree(atsru);
3729 return -ENOMEM;
3730 }
3731 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003732
Jiang Liu0e242612014-02-19 14:07:34 +08003733 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003734
3735 return 0;
3736}
3737
Jiang Liu9bdc5312014-01-06 14:18:27 +08003738static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3739{
3740 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
3741 kfree(atsru);
3742}
3743
Jiang Liu6b197242014-11-09 22:47:58 +08003744int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3745{
3746 struct acpi_dmar_atsr *atsr;
3747 struct dmar_atsr_unit *atsru;
3748
3749 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3750 atsru = dmar_find_atsr(atsr);
3751 if (atsru) {
3752 list_del_rcu(&atsru->list);
3753 synchronize_rcu();
3754 intel_iommu_free_atsr(atsru);
3755 }
3756
3757 return 0;
3758}
3759
3760int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3761{
3762 int i;
3763 struct device *dev;
3764 struct acpi_dmar_atsr *atsr;
3765 struct dmar_atsr_unit *atsru;
3766
3767 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3768 atsru = dmar_find_atsr(atsr);
3769 if (!atsru)
3770 return 0;
3771
3772 if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
3773 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
3774 i, dev)
3775 return -EBUSY;
3776
3777 return 0;
3778}
3779
Jiang Liuffebeb42014-11-09 22:48:02 +08003780static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
3781{
3782 int sp, ret = 0;
3783 struct intel_iommu *iommu = dmaru->iommu;
3784
3785 if (g_iommus[iommu->seq_id])
3786 return 0;
3787
3788 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
3789 pr_warn("IOMMU: %s doesn't support hardware pass through.\n",
3790 iommu->name);
3791 return -ENXIO;
3792 }
3793 if (!ecap_sc_support(iommu->ecap) &&
3794 domain_update_iommu_snooping(iommu)) {
3795 pr_warn("IOMMU: %s doesn't support snooping.\n",
3796 iommu->name);
3797 return -ENXIO;
3798 }
3799 sp = domain_update_iommu_superpage(iommu) - 1;
3800 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
3801 pr_warn("IOMMU: %s doesn't support large page.\n",
3802 iommu->name);
3803 return -ENXIO;
3804 }
3805
3806 /*
3807 * Disable translation if already enabled prior to OS handover.
3808 */
3809 if (iommu->gcmd & DMA_GCMD_TE)
3810 iommu_disable_translation(iommu);
3811
3812 g_iommus[iommu->seq_id] = iommu;
3813 ret = iommu_init_domains(iommu);
3814 if (ret == 0)
3815 ret = iommu_alloc_root_entry(iommu);
3816 if (ret)
3817 goto out;
3818
3819 if (dmaru->ignored) {
3820 /*
3821 * we always have to disable PMRs or DMA may fail on this device
3822 */
3823 if (force_on)
3824 iommu_disable_protect_mem_regions(iommu);
3825 return 0;
3826 }
3827
3828 intel_iommu_init_qi(iommu);
3829 iommu_flush_write_buffer(iommu);
3830 ret = dmar_set_interrupt(iommu);
3831 if (ret)
3832 goto disable_iommu;
3833
3834 iommu_set_root_entry(iommu);
3835 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3836 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3837 iommu_enable_translation(iommu);
3838
3839 if (si_domain) {
3840 ret = iommu_attach_domain(si_domain, iommu);
3841 if (ret < 0 || si_domain->id != ret)
3842 goto disable_iommu;
3843 domain_attach_iommu(si_domain, iommu);
3844 }
3845
3846 iommu_disable_protect_mem_regions(iommu);
3847 return 0;
3848
3849disable_iommu:
3850 disable_dmar_iommu(iommu);
3851out:
3852 free_dmar_iommu(iommu);
3853 return ret;
3854}
3855
Jiang Liu6b197242014-11-09 22:47:58 +08003856int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
3857{
Jiang Liuffebeb42014-11-09 22:48:02 +08003858 int ret = 0;
3859 struct intel_iommu *iommu = dmaru->iommu;
3860
3861 if (!intel_iommu_enabled)
3862 return 0;
3863 if (iommu == NULL)
3864 return -EINVAL;
3865
3866 if (insert) {
3867 ret = intel_iommu_add(dmaru);
3868 } else {
3869 disable_dmar_iommu(iommu);
3870 free_dmar_iommu(iommu);
3871 }
3872
3873 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08003874}
3875
Jiang Liu9bdc5312014-01-06 14:18:27 +08003876static void intel_iommu_free_dmars(void)
3877{
3878 struct dmar_rmrr_unit *rmrru, *rmrr_n;
3879 struct dmar_atsr_unit *atsru, *atsr_n;
3880
3881 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
3882 list_del(&rmrru->list);
3883 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
3884 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003885 }
3886
Jiang Liu9bdc5312014-01-06 14:18:27 +08003887 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
3888 list_del(&atsru->list);
3889 intel_iommu_free_atsr(atsru);
3890 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003891}
3892
3893int dmar_find_matched_atsr_unit(struct pci_dev *dev)
3894{
Jiang Liub683b232014-02-19 14:07:32 +08003895 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003896 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00003897 struct pci_dev *bridge = NULL;
3898 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003899 struct acpi_dmar_atsr *atsr;
3900 struct dmar_atsr_unit *atsru;
3901
3902 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003903 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08003904 bridge = bus->self;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003905 if (!bridge || !pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08003906 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003907 return 0;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003908 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003909 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003910 }
Jiang Liub5f82dd2014-02-19 14:07:31 +08003911 if (!bridge)
3912 return 0;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003913
Jiang Liu0e242612014-02-19 14:07:34 +08003914 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08003915 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3916 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3917 if (atsr->segment != pci_domain_nr(dev->bus))
3918 continue;
3919
Jiang Liub683b232014-02-19 14:07:32 +08003920 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00003921 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08003922 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003923
3924 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08003925 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003926 }
Jiang Liub683b232014-02-19 14:07:32 +08003927 ret = 0;
3928out:
Jiang Liu0e242612014-02-19 14:07:34 +08003929 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003930
Jiang Liub683b232014-02-19 14:07:32 +08003931 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003932}
3933
Jiang Liu59ce0512014-02-19 14:07:35 +08003934int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3935{
3936 int ret = 0;
3937 struct dmar_rmrr_unit *rmrru;
3938 struct dmar_atsr_unit *atsru;
3939 struct acpi_dmar_atsr *atsr;
3940 struct acpi_dmar_reserved_memory *rmrr;
3941
3942 if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
3943 return 0;
3944
3945 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
3946 rmrr = container_of(rmrru->hdr,
3947 struct acpi_dmar_reserved_memory, header);
3948 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3949 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
3950 ((void *)rmrr) + rmrr->header.length,
3951 rmrr->segment, rmrru->devices,
3952 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08003953 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08003954 return ret;
3955 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08003956 dmar_remove_dev_scope(info, rmrr->segment,
3957 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08003958 }
3959 }
3960
3961 list_for_each_entry(atsru, &dmar_atsr_units, list) {
3962 if (atsru->include_all)
3963 continue;
3964
3965 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3966 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3967 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
3968 (void *)atsr + atsr->header.length,
3969 atsr->segment, atsru->devices,
3970 atsru->devices_cnt);
3971 if (ret > 0)
3972 break;
3973 else if(ret < 0)
3974 return ret;
3975 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
3976 if (dmar_remove_dev_scope(info, atsr->segment,
3977 atsru->devices, atsru->devices_cnt))
3978 break;
3979 }
3980 }
3981
3982 return 0;
3983}
3984
Fenghua Yu99dcade2009-11-11 07:23:06 -08003985/*
3986 * Here we only respond to action of unbound device from driver.
3987 *
3988 * Added device is not attached to its DMAR domain here yet. That will happen
3989 * when mapping the device to iova.
3990 */
3991static int device_notifier(struct notifier_block *nb,
3992 unsigned long action, void *data)
3993{
3994 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08003995 struct dmar_domain *domain;
3996
David Woodhouse3d891942014-03-06 15:59:26 +00003997 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00003998 return 0;
3999
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004000 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004001 return 0;
4002
David Woodhouse1525a292014-03-06 16:19:30 +00004003 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004004 if (!domain)
4005 return 0;
4006
Jiang Liu3a5670e2014-02-19 14:07:33 +08004007 down_read(&dmar_global_lock);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004008 domain_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004009 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004010 domain_exit(domain);
Jiang Liu3a5670e2014-02-19 14:07:33 +08004011 up_read(&dmar_global_lock);
Alex Williamsona97590e2011-03-04 14:52:16 -07004012
Fenghua Yu99dcade2009-11-11 07:23:06 -08004013 return 0;
4014}
4015
4016static struct notifier_block device_nb = {
4017 .notifier_call = device_notifier,
4018};
4019
Jiang Liu75f05562014-02-19 14:07:37 +08004020static int intel_iommu_memory_notifier(struct notifier_block *nb,
4021 unsigned long val, void *v)
4022{
4023 struct memory_notify *mhp = v;
4024 unsigned long long start, end;
4025 unsigned long start_vpfn, last_vpfn;
4026
4027 switch (val) {
4028 case MEM_GOING_ONLINE:
4029 start = mhp->start_pfn << PAGE_SHIFT;
4030 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4031 if (iommu_domain_identity_map(si_domain, start, end)) {
4032 pr_warn("dmar: failed to build identity map for [%llx-%llx]\n",
4033 start, end);
4034 return NOTIFY_BAD;
4035 }
4036 break;
4037
4038 case MEM_OFFLINE:
4039 case MEM_CANCEL_ONLINE:
4040 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4041 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4042 while (start_vpfn <= last_vpfn) {
4043 struct iova *iova;
4044 struct dmar_drhd_unit *drhd;
4045 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004046 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004047
4048 iova = find_iova(&si_domain->iovad, start_vpfn);
4049 if (iova == NULL) {
4050 pr_debug("dmar: failed get IOVA for PFN %lx\n",
4051 start_vpfn);
4052 break;
4053 }
4054
4055 iova = split_and_remove_iova(&si_domain->iovad, iova,
4056 start_vpfn, last_vpfn);
4057 if (iova == NULL) {
4058 pr_warn("dmar: failed to split IOVA PFN [%lx-%lx]\n",
4059 start_vpfn, last_vpfn);
4060 return NOTIFY_BAD;
4061 }
4062
David Woodhouseea8ea462014-03-05 17:09:32 +00004063 freelist = domain_unmap(si_domain, iova->pfn_lo,
4064 iova->pfn_hi);
4065
Jiang Liu75f05562014-02-19 14:07:37 +08004066 rcu_read_lock();
4067 for_each_active_iommu(iommu, drhd)
4068 iommu_flush_iotlb_psi(iommu, si_domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08004069 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004070 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004071 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004072 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004073
4074 start_vpfn = iova->pfn_hi + 1;
4075 free_iova_mem(iova);
4076 }
4077 break;
4078 }
4079
4080 return NOTIFY_OK;
4081}
4082
4083static struct notifier_block intel_iommu_memory_nb = {
4084 .notifier_call = intel_iommu_memory_notifier,
4085 .priority = 0
4086};
4087
Alex Williamsona5459cf2014-06-12 16:12:31 -06004088
4089static ssize_t intel_iommu_show_version(struct device *dev,
4090 struct device_attribute *attr,
4091 char *buf)
4092{
4093 struct intel_iommu *iommu = dev_get_drvdata(dev);
4094 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4095 return sprintf(buf, "%d:%d\n",
4096 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4097}
4098static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4099
4100static ssize_t intel_iommu_show_address(struct device *dev,
4101 struct device_attribute *attr,
4102 char *buf)
4103{
4104 struct intel_iommu *iommu = dev_get_drvdata(dev);
4105 return sprintf(buf, "%llx\n", iommu->reg_phys);
4106}
4107static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4108
4109static ssize_t intel_iommu_show_cap(struct device *dev,
4110 struct device_attribute *attr,
4111 char *buf)
4112{
4113 struct intel_iommu *iommu = dev_get_drvdata(dev);
4114 return sprintf(buf, "%llx\n", iommu->cap);
4115}
4116static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4117
4118static ssize_t intel_iommu_show_ecap(struct device *dev,
4119 struct device_attribute *attr,
4120 char *buf)
4121{
4122 struct intel_iommu *iommu = dev_get_drvdata(dev);
4123 return sprintf(buf, "%llx\n", iommu->ecap);
4124}
4125static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4126
4127static struct attribute *intel_iommu_attrs[] = {
4128 &dev_attr_version.attr,
4129 &dev_attr_address.attr,
4130 &dev_attr_cap.attr,
4131 &dev_attr_ecap.attr,
4132 NULL,
4133};
4134
4135static struct attribute_group intel_iommu_group = {
4136 .name = "intel-iommu",
4137 .attrs = intel_iommu_attrs,
4138};
4139
4140const struct attribute_group *intel_iommu_groups[] = {
4141 &intel_iommu_group,
4142 NULL,
4143};
4144
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004145int __init intel_iommu_init(void)
4146{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004147 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004148 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004149 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004150
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004151 /* VT-d is required for a TXT/tboot launch, so enforce that */
4152 force_on = tboot_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004153
Jiang Liu3a5670e2014-02-19 14:07:33 +08004154 if (iommu_init_mempool()) {
4155 if (force_on)
4156 panic("tboot: Failed to initialize iommu memory\n");
4157 return -ENOMEM;
4158 }
4159
4160 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004161 if (dmar_table_init()) {
4162 if (force_on)
4163 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004164 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004165 }
4166
Takao Indoh3a93c842013-04-23 17:35:03 +09004167 /*
4168 * Disable translation if already enabled prior to OS handover.
4169 */
Jiang Liu7c919772014-01-06 14:18:18 +08004170 for_each_active_iommu(iommu, drhd)
Takao Indoh3a93c842013-04-23 17:35:03 +09004171 if (iommu->gcmd & DMA_GCMD_TE)
4172 iommu_disable_translation(iommu);
Takao Indoh3a93c842013-04-23 17:35:03 +09004173
Suresh Siddhac2c72862011-08-23 17:05:19 -07004174 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004175 if (force_on)
4176 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004177 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004178 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004179
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004180 if (no_iommu || dmar_disabled)
Jiang Liu9bdc5312014-01-06 14:18:27 +08004181 goto out_free_dmar;
Suresh Siddha2ae21012008-07-10 11:16:43 -07004182
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004183 if (list_empty(&dmar_rmrr_units))
4184 printk(KERN_INFO "DMAR: No RMRR found\n");
4185
4186 if (list_empty(&dmar_atsr_units))
4187 printk(KERN_INFO "DMAR: No ATSR found\n");
4188
Joseph Cihula51a63e62011-03-21 11:04:24 -07004189 if (dmar_init_reserved_ranges()) {
4190 if (force_on)
4191 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004192 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004193 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004194
4195 init_no_remapping_devices();
4196
Joseph Cihulab7792602011-05-03 00:08:37 -07004197 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004198 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004199 if (force_on)
4200 panic("tboot: Failed to initialize DMARs\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004201 printk(KERN_ERR "IOMMU: dmar init failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004202 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004203 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004204 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004205 printk(KERN_INFO
4206 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
4207
mark gross5e0d2a62008-03-04 15:22:08 -08004208 init_timer(&unmap_timer);
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004209#ifdef CONFIG_SWIOTLB
4210 swiotlb = 0;
4211#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004212 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004213
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004214 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004215
Alex Williamsona5459cf2014-06-12 16:12:31 -06004216 for_each_active_iommu(iommu, drhd)
4217 iommu->iommu_dev = iommu_device_create(NULL, iommu,
4218 intel_iommu_groups,
4219 iommu->name);
4220
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004221 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004222 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004223 if (si_domain && !hw_pass_through)
4224 register_memory_notifier(&intel_iommu_memory_nb);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004225
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004226 intel_iommu_enabled = 1;
4227
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004228 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004229
4230out_free_reserved_range:
4231 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004232out_free_dmar:
4233 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004234 up_write(&dmar_global_lock);
4235 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004236 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004237}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004238
Alex Williamson579305f2014-07-03 09:51:43 -06004239static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
4240{
4241 struct intel_iommu *iommu = opaque;
4242
4243 iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4244 return 0;
4245}
4246
4247/*
4248 * NB - intel-iommu lacks any sort of reference counting for the users of
4249 * dependent devices. If multiple endpoints have intersecting dependent
4250 * devices, unbinding the driver from any one of them will possibly leave
4251 * the others unable to operate.
4252 */
Han, Weidong3199aa62009-02-26 17:31:12 +08004253static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004254 struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004255{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004256 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004257 return;
4258
Alex Williamson579305f2014-07-03 09:51:43 -06004259 pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004260}
4261
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004262static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004263 struct device *dev)
Weidong Hanc7151a82008-12-08 22:51:37 +08004264{
Yijing Wangbca2b912013-10-31 17:26:04 +08004265 struct device_domain_info *info, *tmp;
Weidong Hanc7151a82008-12-08 22:51:37 +08004266 struct intel_iommu *iommu;
4267 unsigned long flags;
4268 int found = 0;
David Woodhouse156baca2014-03-09 14:00:57 -07004269 u8 bus, devfn;
Weidong Hanc7151a82008-12-08 22:51:37 +08004270
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004271 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanc7151a82008-12-08 22:51:37 +08004272 if (!iommu)
4273 return;
4274
4275 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wangbca2b912013-10-31 17:26:04 +08004276 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004277 if (info->iommu == iommu && info->bus == bus &&
4278 info->devfn == devfn) {
David Woodhouse109b9b02012-05-25 17:43:02 +01004279 unlink_domain_info(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004280 spin_unlock_irqrestore(&device_domain_lock, flags);
4281
Yu Zhao93a23a72009-05-18 13:51:37 +08004282 iommu_disable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004283 iommu_detach_dev(iommu, info->bus, info->devfn);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004284 iommu_detach_dependent_devices(iommu, dev);
Weidong Hanc7151a82008-12-08 22:51:37 +08004285 free_devinfo_mem(info);
4286
4287 spin_lock_irqsave(&device_domain_lock, flags);
4288
4289 if (found)
4290 break;
4291 else
4292 continue;
4293 }
4294
4295 /* if there is no other devices under the same iommu
4296 * owned by this domain, clear this iommu in iommu_bmp
4297 * update iommu count and coherency
4298 */
David Woodhouse8bbc4412014-03-09 13:52:37 -07004299 if (info->iommu == iommu)
Weidong Hanc7151a82008-12-08 22:51:37 +08004300 found = 1;
4301 }
4302
Roland Dreier3e7abe22011-07-20 06:22:21 -07004303 spin_unlock_irqrestore(&device_domain_lock, flags);
4304
Weidong Hanc7151a82008-12-08 22:51:37 +08004305 if (found == 0) {
Jiang Liufb170fb2014-07-11 14:19:28 +08004306 domain_detach_iommu(domain, iommu);
4307 if (!domain_type_is_vm_or_si(domain))
4308 iommu_detach_domain(domain, iommu);
Weidong Hanc7151a82008-12-08 22:51:37 +08004309 }
Weidong Hanc7151a82008-12-08 22:51:37 +08004310}
4311
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004312static int md_domain_init(struct dmar_domain *domain, int guest_width)
Weidong Han5e98c4b2008-12-08 23:03:27 +08004313{
4314 int adjust_width;
4315
4316 init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004317 domain_reserve_special_ranges(domain);
4318
4319 /* calculate AGAW */
4320 domain->gaw = guest_width;
4321 adjust_width = guestwidth_to_adjustwidth(guest_width);
4322 domain->agaw = width_to_agaw(adjust_width);
4323
Weidong Han5e98c4b2008-12-08 23:03:27 +08004324 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004325 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004326 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004327 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004328
4329 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004330 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004331 if (!domain->pgd)
4332 return -ENOMEM;
4333 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4334 return 0;
4335}
4336
Joerg Roedel5d450802008-12-03 14:52:32 +01004337static int intel_iommu_domain_init(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004338{
Joerg Roedel5d450802008-12-03 14:52:32 +01004339 struct dmar_domain *dmar_domain;
Kay, Allen M38717942008-09-09 18:37:29 +03004340
Jiang Liuab8dfe22014-07-11 14:19:27 +08004341 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01004342 if (!dmar_domain) {
Kay, Allen M38717942008-09-09 18:37:29 +03004343 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004344 "intel_iommu_domain_init: dmar_domain == NULL\n");
4345 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004346 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004347 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Kay, Allen M38717942008-09-09 18:37:29 +03004348 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004349 "intel_iommu_domain_init() failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08004350 domain_exit(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004351 return -ENOMEM;
Kay, Allen M38717942008-09-09 18:37:29 +03004352 }
Allen Kay8140a952011-10-14 12:32:17 -07004353 domain_update_iommu_cap(dmar_domain);
Joerg Roedel5d450802008-12-03 14:52:32 +01004354 domain->priv = dmar_domain;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004355
Joerg Roedel8a0e7152012-01-26 19:40:54 +01004356 domain->geometry.aperture_start = 0;
4357 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4358 domain->geometry.force_aperture = true;
4359
Joerg Roedel5d450802008-12-03 14:52:32 +01004360 return 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004361}
Kay, Allen M38717942008-09-09 18:37:29 +03004362
Joerg Roedel5d450802008-12-03 14:52:32 +01004363static void intel_iommu_domain_destroy(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004364{
Joerg Roedel5d450802008-12-03 14:52:32 +01004365 struct dmar_domain *dmar_domain = domain->priv;
4366
4367 domain->priv = NULL;
Jiang Liu92d03cc2014-02-19 14:07:28 +08004368 domain_exit(dmar_domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004369}
Kay, Allen M38717942008-09-09 18:37:29 +03004370
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004371static int intel_iommu_attach_device(struct iommu_domain *domain,
4372 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004373{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004374 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004375 struct intel_iommu *iommu;
4376 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07004377 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03004378
Alex Williamsonc875d2c2014-07-03 09:57:02 -06004379 if (device_is_rmrr_locked(dev)) {
4380 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
4381 return -EPERM;
4382 }
4383
David Woodhouse7207d8f2014-03-09 16:31:06 -07004384 /* normally dev is not mapped */
4385 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004386 struct dmar_domain *old_domain;
4387
David Woodhouse1525a292014-03-06 16:19:30 +00004388 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004389 if (old_domain) {
Jiang Liuab8dfe22014-07-11 14:19:27 +08004390 if (domain_type_is_vm_or_si(dmar_domain))
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004391 domain_remove_one_dev_info(old_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004392 else
4393 domain_remove_dev_info(old_domain);
Joerg Roedel62c22162014-12-09 12:56:45 +01004394
4395 if (!domain_type_is_vm_or_si(old_domain) &&
4396 list_empty(&old_domain->devices))
4397 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004398 }
4399 }
4400
David Woodhouse156baca2014-03-09 14:00:57 -07004401 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004402 if (!iommu)
4403 return -ENODEV;
4404
4405 /* check if this iommu agaw is sufficient for max mapped address */
4406 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01004407 if (addr_width > cap_mgaw(iommu->cap))
4408 addr_width = cap_mgaw(iommu->cap);
4409
4410 if (dmar_domain->max_addr > (1LL << addr_width)) {
4411 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004412 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01004413 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004414 return -EFAULT;
4415 }
Tom Lyona99c47a2010-05-17 08:20:45 +01004416 dmar_domain->gaw = addr_width;
4417
4418 /*
4419 * Knock out extra levels of page tables if necessary
4420 */
4421 while (iommu->agaw < dmar_domain->agaw) {
4422 struct dma_pte *pte;
4423
4424 pte = dmar_domain->pgd;
4425 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08004426 dmar_domain->pgd = (struct dma_pte *)
4427 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01004428 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01004429 }
4430 dmar_domain->agaw--;
4431 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004432
David Woodhouse5913c9b2014-03-09 16:27:31 -07004433 return domain_add_dev_info(dmar_domain, dev, CONTEXT_TT_MULTI_LEVEL);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004434}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004435
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004436static void intel_iommu_detach_device(struct iommu_domain *domain,
4437 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004438{
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004439 struct dmar_domain *dmar_domain = domain->priv;
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004440
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004441 domain_remove_one_dev_info(dmar_domain, dev);
Kay, Allen M38717942008-09-09 18:37:29 +03004442}
Kay, Allen M38717942008-09-09 18:37:29 +03004443
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004444static int intel_iommu_map(struct iommu_domain *domain,
4445 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004446 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03004447{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004448 struct dmar_domain *dmar_domain = domain->priv;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004449 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004450 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004451 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004452
Joerg Roedeldde57a22008-12-03 15:04:09 +01004453 if (iommu_prot & IOMMU_READ)
4454 prot |= DMA_PTE_READ;
4455 if (iommu_prot & IOMMU_WRITE)
4456 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08004457 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
4458 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004459
David Woodhouse163cc522009-06-28 00:51:17 +01004460 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004461 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004462 u64 end;
4463
4464 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01004465 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004466 if (end < max_addr) {
Tom Lyon8954da12010-05-17 08:19:52 +01004467 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004468 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01004469 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004470 return -EFAULT;
4471 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01004472 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004473 }
David Woodhousead051222009-06-28 14:22:28 +01004474 /* Round up size to next multiple of PAGE_SIZE, if it and
4475 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01004476 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01004477 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
4478 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004479 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03004480}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004481
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004482static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00004483 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004484{
Joerg Roedeldde57a22008-12-03 15:04:09 +01004485 struct dmar_domain *dmar_domain = domain->priv;
David Woodhouseea8ea462014-03-05 17:09:32 +00004486 struct page *freelist = NULL;
4487 struct intel_iommu *iommu;
4488 unsigned long start_pfn, last_pfn;
4489 unsigned int npages;
4490 int iommu_id, num, ndomains, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01004491
David Woodhouse5cf0a762014-03-19 16:07:49 +00004492 /* Cope with horrid API which requires us to unmap more than the
4493 size argument if it happens to be a large-page mapping. */
4494 if (!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level))
4495 BUG();
4496
4497 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
4498 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
4499
David Woodhouseea8ea462014-03-05 17:09:32 +00004500 start_pfn = iova >> VTD_PAGE_SHIFT;
4501 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
4502
4503 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
4504
4505 npages = last_pfn - start_pfn + 1;
4506
4507 for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) {
4508 iommu = g_iommus[iommu_id];
4509
4510 /*
4511 * find bit position of dmar_domain
4512 */
4513 ndomains = cap_ndoms(iommu->cap);
4514 for_each_set_bit(num, iommu->domain_ids, ndomains) {
4515 if (iommu->domains[num] == dmar_domain)
4516 iommu_flush_iotlb_psi(iommu, num, start_pfn,
4517 npages, !freelist, 0);
4518 }
4519
4520 }
4521
4522 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004523
David Woodhouse163cc522009-06-28 00:51:17 +01004524 if (dmar_domain->max_addr == iova + size)
4525 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004526
David Woodhouse5cf0a762014-03-19 16:07:49 +00004527 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004528}
Kay, Allen M38717942008-09-09 18:37:29 +03004529
Joerg Roedeld14d6572008-12-03 15:06:57 +01004530static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05304531 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03004532{
Joerg Roedeld14d6572008-12-03 15:06:57 +01004533 struct dmar_domain *dmar_domain = domain->priv;
Kay, Allen M38717942008-09-09 18:37:29 +03004534 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00004535 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004536 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004537
David Woodhouse5cf0a762014-03-19 16:07:49 +00004538 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03004539 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004540 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03004541
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004542 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03004543}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004544
Joerg Roedel5d587b82014-09-05 10:50:45 +02004545static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004546{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004547 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004548 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04004549 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004550 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004551
Joerg Roedel5d587b82014-09-05 10:50:45 +02004552 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004553}
4554
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004555static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004556{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004557 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004558 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07004559 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04004560
Alex Williamsona5459cf2014-06-12 16:12:31 -06004561 iommu = device_to_iommu(dev, &bus, &devfn);
4562 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004563 return -ENODEV;
4564
Alex Williamsona5459cf2014-06-12 16:12:31 -06004565 iommu_device_link(iommu->iommu_dev, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004566
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004567 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06004568
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004569 if (IS_ERR(group))
4570 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004571
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004572 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004573 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004574}
4575
4576static void intel_iommu_remove_device(struct device *dev)
4577{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004578 struct intel_iommu *iommu;
4579 u8 bus, devfn;
4580
4581 iommu = device_to_iommu(dev, &bus, &devfn);
4582 if (!iommu)
4583 return;
4584
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004585 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004586
4587 iommu_device_unlink(iommu->iommu_dev, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004588}
4589
Thierry Redingb22f6432014-06-27 09:03:12 +02004590static const struct iommu_ops intel_iommu_ops = {
Joerg Roedel5d587b82014-09-05 10:50:45 +02004591 .capable = intel_iommu_capable,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004592 .domain_init = intel_iommu_domain_init,
4593 .domain_destroy = intel_iommu_domain_destroy,
4594 .attach_dev = intel_iommu_attach_device,
4595 .detach_dev = intel_iommu_detach_device,
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004596 .map = intel_iommu_map,
4597 .unmap = intel_iommu_unmap,
Olav Haugan315786e2014-10-25 09:55:16 -07004598 .map_sg = default_iommu_map_sg,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004599 .iova_to_phys = intel_iommu_iova_to_phys,
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004600 .add_device = intel_iommu_add_device,
4601 .remove_device = intel_iommu_remove_device,
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +02004602 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004603};
David Woodhouse9af88142009-02-13 23:18:03 +00004604
Daniel Vetter94526182013-01-20 23:50:13 +01004605static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
4606{
4607 /* G4x/GM45 integrated gfx dmar support is totally busted. */
4608 printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
4609 dmar_map_gfx = 0;
4610}
4611
4612DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
4613DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
4614DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
4615DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
4616DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
4617DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
4618DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
4619
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004620static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00004621{
4622 /*
4623 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01004624 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00004625 */
4626 printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
4627 rwbf_quirk = 1;
4628}
4629
4630DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01004631DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
4632DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
4633DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
4634DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
4635DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
4636DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07004637
Adam Jacksoneecfd572010-08-25 21:17:34 +01004638#define GGC 0x52
4639#define GGC_MEMORY_SIZE_MASK (0xf << 8)
4640#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
4641#define GGC_MEMORY_SIZE_1M (0x1 << 8)
4642#define GGC_MEMORY_SIZE_2M (0x3 << 8)
4643#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
4644#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
4645#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
4646#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
4647
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004648static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01004649{
4650 unsigned short ggc;
4651
Adam Jacksoneecfd572010-08-25 21:17:34 +01004652 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01004653 return;
4654
Adam Jacksoneecfd572010-08-25 21:17:34 +01004655 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
David Woodhouse9eecabc2010-09-21 22:28:23 +01004656 printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
4657 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004658 } else if (dmar_map_gfx) {
4659 /* we have to ensure the gfx device is idle before we flush */
4660 printk(KERN_INFO "DMAR: Disabling batched IOTLB flush on Ironlake\n");
4661 intel_iommu_strict = 1;
4662 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01004663}
4664DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4665DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
4666DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
4667DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
4668
David Woodhousee0fc7e02009-09-30 09:12:17 -07004669/* On Tylersburg chipsets, some BIOSes have been known to enable the
4670 ISOCH DMAR unit for the Azalia sound device, but not give it any
4671 TLB entries, which causes it to deadlock. Check for that. We do
4672 this in a function called from init_dmars(), instead of in a PCI
4673 quirk, because we don't want to print the obnoxious "BIOS broken"
4674 message if VT-d is actually disabled.
4675*/
4676static void __init check_tylersburg_isoch(void)
4677{
4678 struct pci_dev *pdev;
4679 uint32_t vtisochctrl;
4680
4681 /* If there's no Azalia in the system anyway, forget it. */
4682 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
4683 if (!pdev)
4684 return;
4685 pci_dev_put(pdev);
4686
4687 /* System Management Registers. Might be hidden, in which case
4688 we can't do the sanity check. But that's OK, because the
4689 known-broken BIOSes _don't_ actually hide it, so far. */
4690 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
4691 if (!pdev)
4692 return;
4693
4694 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
4695 pci_dev_put(pdev);
4696 return;
4697 }
4698
4699 pci_dev_put(pdev);
4700
4701 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
4702 if (vtisochctrl & 1)
4703 return;
4704
4705 /* Drop all bits other than the number of TLB entries */
4706 vtisochctrl &= 0x1c;
4707
4708 /* If we have the recommended number of TLB entries (16), fine. */
4709 if (vtisochctrl == 0x10)
4710 return;
4711
4712 /* Zero TLB entries? You get to ride the short bus to school. */
4713 if (!vtisochctrl) {
4714 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
4715 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4716 dmi_get_system_info(DMI_BIOS_VENDOR),
4717 dmi_get_system_info(DMI_BIOS_VERSION),
4718 dmi_get_system_info(DMI_PRODUCT_VERSION));
4719 iommu_identity_mapping |= IDENTMAP_AZALIA;
4720 return;
4721 }
4722
4723 printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
4724 vtisochctrl);
4725}