blob: 68d43beccb7e560f845ad49b8ae7d9e38872fcf7 [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)
David Woodhouse18436af2015-03-25 15:05:47 +000053#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070054#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070055#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070056
57#define IOAPIC_RANGE_START (0xfee00000)
58#define IOAPIC_RANGE_END (0xfeefffff)
59#define IOVA_START_ADDR (0x1000)
60
61#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
62
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070063#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080064#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070065
David Woodhouse2ebe3152009-09-19 07:34:04 -070066#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
67#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
68
69/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
70 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
71#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
72 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
73#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070074
Robin Murphy1b722502015-01-12 17:51:15 +000075/* IO virtual address start page frame number */
76#define IOVA_START_PFN (1)
77
Mark McLoughlinf27be032008-11-20 15:49:43 +000078#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
Yang Hongyang284901a2009-04-06 19:01:15 -070079#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
Yang Hongyang6a355282009-04-06 19:01:13 -070080#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
mark gross5e0d2a62008-03-04 15:22:08 -080081
Andrew Mortondf08cdc2010-09-22 13:05:11 -070082/* page table handling */
83#define LEVEL_STRIDE (9)
84#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
85
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020086/*
87 * This bitmap is used to advertise the page sizes our hardware support
88 * to the IOMMU core, which will then use this information to split
89 * physically contiguous memory regions it is mapping into page sizes
90 * that we support.
91 *
92 * Traditionally the IOMMU core just handed us the mappings directly,
93 * after making sure the size is an order of a 4KiB page and that the
94 * mapping has natural alignment.
95 *
96 * To retain this behavior, we currently advertise that we support
97 * all page sizes that are an order of 4KiB.
98 *
99 * If at some point we'd like to utilize the IOMMU core's new behavior,
100 * we could change this to advertise the real page sizes we support.
101 */
102#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
103
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700104static inline int agaw_to_level(int agaw)
105{
106 return agaw + 2;
107}
108
109static inline int agaw_to_width(int agaw)
110{
Jiang Liu5c645b32014-01-06 14:18:12 +0800111 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700112}
113
114static inline int width_to_agaw(int width)
115{
Jiang Liu5c645b32014-01-06 14:18:12 +0800116 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700117}
118
119static inline unsigned int level_to_offset_bits(int level)
120{
121 return (level - 1) * LEVEL_STRIDE;
122}
123
124static inline int pfn_level_offset(unsigned long pfn, int level)
125{
126 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
127}
128
129static inline unsigned long level_mask(int level)
130{
131 return -1UL << level_to_offset_bits(level);
132}
133
134static inline unsigned long level_size(int level)
135{
136 return 1UL << level_to_offset_bits(level);
137}
138
139static inline unsigned long align_to_level(unsigned long pfn, int level)
140{
141 return (pfn + level_size(level) - 1) & level_mask(level);
142}
David Woodhousefd18de52009-05-10 23:57:41 +0100143
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100144static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
145{
Jiang Liu5c645b32014-01-06 14:18:12 +0800146 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100147}
148
David Woodhousedd4e8312009-06-27 16:21:20 +0100149/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
150 are never going to work. */
151static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
152{
153 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
154}
155
156static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
157{
158 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
159}
160static inline unsigned long page_to_dma_pfn(struct page *pg)
161{
162 return mm_to_dma_pfn(page_to_pfn(pg));
163}
164static inline unsigned long virt_to_dma_pfn(void *p)
165{
166 return page_to_dma_pfn(virt_to_page(p));
167}
168
Weidong Hand9630fe2008-12-08 11:06:32 +0800169/* global iommu list, set NULL for ignored DMAR units */
170static struct intel_iommu **g_iommus;
171
David Woodhousee0fc7e02009-09-30 09:12:17 -0700172static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000173static int rwbf_quirk;
174
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000175/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700176 * set to 1 to panic kernel if can't successfully enable VT-d
177 * (used when kernel is launched w/ TXT)
178 */
179static int force_on = 0;
180
181/*
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000182 * 0: Present
183 * 1-11: Reserved
184 * 12-63: Context Ptr (12 - (haw-1))
185 * 64-127: Reserved
186 */
187struct root_entry {
David Woodhouse03ecc322015-02-13 14:35:21 +0000188 u64 lo;
189 u64 hi;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000190};
191#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000192
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000193
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000194/*
195 * low 64 bits:
196 * 0: present
197 * 1: fault processing disable
198 * 2-3: translation type
199 * 12-63: address space root
200 * high 64 bits:
201 * 0-2: address width
202 * 3-6: aval
203 * 8-23: domain id
204 */
205struct context_entry {
206 u64 lo;
207 u64 hi;
208};
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000209
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000210static inline bool context_present(struct context_entry *context)
211{
212 return (context->lo & 1);
213}
214static inline void context_set_present(struct context_entry *context)
215{
216 context->lo |= 1;
217}
218
219static inline void context_set_fault_enable(struct context_entry *context)
220{
221 context->lo &= (((u64)-1) << 2) | 1;
222}
223
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000224static inline void context_set_translation_type(struct context_entry *context,
225 unsigned long value)
226{
227 context->lo &= (((u64)-1) << 4) | 3;
228 context->lo |= (value & 3) << 2;
229}
230
231static inline void context_set_address_root(struct context_entry *context,
232 unsigned long value)
233{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800234 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000235 context->lo |= value & VTD_PAGE_MASK;
236}
237
238static inline void context_set_address_width(struct context_entry *context,
239 unsigned long value)
240{
241 context->hi |= value & 7;
242}
243
244static inline void context_set_domain_id(struct context_entry *context,
245 unsigned long value)
246{
247 context->hi |= (value & ((1 << 16) - 1)) << 8;
248}
249
250static inline void context_clear_entry(struct context_entry *context)
251{
252 context->lo = 0;
253 context->hi = 0;
254}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000255
Mark McLoughlin622ba122008-11-20 15:49:46 +0000256/*
257 * 0: readable
258 * 1: writable
259 * 2-6: reserved
260 * 7: super page
Sheng Yang9cf066972009-03-18 15:33:07 +0800261 * 8-10: available
262 * 11: snoop behavior
Mark McLoughlin622ba122008-11-20 15:49:46 +0000263 * 12-63: Host physcial address
264 */
265struct dma_pte {
266 u64 val;
267};
Mark McLoughlin622ba122008-11-20 15:49:46 +0000268
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000269static inline void dma_clear_pte(struct dma_pte *pte)
270{
271 pte->val = 0;
272}
273
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000274static inline u64 dma_pte_addr(struct dma_pte *pte)
275{
David Woodhousec85994e2009-07-01 19:21:24 +0100276#ifdef CONFIG_64BIT
277 return pte->val & VTD_PAGE_MASK;
278#else
279 /* Must have a full atomic 64-bit read */
David Woodhouse1a8bd482010-08-10 01:38:53 +0100280 return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
David Woodhousec85994e2009-07-01 19:21:24 +0100281#endif
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000282}
283
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000284static inline bool dma_pte_present(struct dma_pte *pte)
285{
286 return (pte->val & 3) != 0;
287}
Mark McLoughlin622ba122008-11-20 15:49:46 +0000288
Allen Kay4399c8b2011-10-14 12:32:46 -0700289static inline bool dma_pte_superpage(struct dma_pte *pte)
290{
Joerg Roedelc3c75eb2014-07-04 11:19:10 +0200291 return (pte->val & DMA_PTE_LARGE_PAGE);
Allen Kay4399c8b2011-10-14 12:32:46 -0700292}
293
David Woodhouse75e6bf92009-07-02 11:21:16 +0100294static inline int first_pte_in_page(struct dma_pte *pte)
295{
296 return !((unsigned long)pte & ~VTD_PAGE_MASK);
297}
298
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700299/*
300 * This domain is a statically identity mapping domain.
301 * 1. This domain creats a static 1:1 mapping to all usable memory.
302 * 2. It maps to each iommu if successful.
303 * 3. Each iommu mapps to this domain if successful.
304 */
David Woodhouse19943b02009-08-04 16:19:20 +0100305static struct dmar_domain *si_domain;
306static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700307
Weidong Han1ce28fe2008-12-08 16:35:39 +0800308/* domain represents a virtual machine, more than one devices
309 * across iommus may be owned in one domain, e.g. kvm guest.
310 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800311#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800312
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700313/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800314#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700315
Mark McLoughlin99126f72008-11-20 15:49:47 +0000316struct dmar_domain {
317 int id; /* domain id */
Suresh Siddha4c923d42009-10-02 11:01:24 -0700318 int nid; /* node id */
Jiang Liu78d8e702014-11-09 22:47:57 +0800319 DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
Mike Travis1b198bb2012-03-05 15:05:16 -0800320 /* bitmap of iommus this domain uses*/
Mark McLoughlin99126f72008-11-20 15:49:47 +0000321
Joerg Roedel00a77de2015-03-26 13:43:08 +0100322 struct list_head devices; /* all devices' list */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000323 struct iova_domain iovad; /* iova's that belong to this domain */
324
325 struct dma_pte *pgd; /* virtual address */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000326 int gaw; /* max guest address width */
327
328 /* adjusted guest address width, 0 is level 2 30-bit */
329 int agaw;
330
Weidong Han3b5410e2008-12-08 09:17:15 +0800331 int flags; /* flags to find out type of domain */
Weidong Han8e6040972008-12-08 15:49:06 +0800332
333 int iommu_coherency;/* indicate coherency of iommu access */
Sheng Yang58c610b2009-03-18 15:33:05 +0800334 int iommu_snooping; /* indicate snooping control feature*/
Weidong Hanc7151a82008-12-08 22:51:37 +0800335 int iommu_count; /* reference count of iommu */
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100336 int iommu_superpage;/* Level of superpages supported:
337 0 == 4KiB (no superpages), 1 == 2MiB,
338 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
Weidong Hanc7151a82008-12-08 22:51:37 +0800339 spinlock_t iommu_lock; /* protect iommu set in domain */
Weidong Hanfe40f1e2008-12-08 23:10:23 +0800340 u64 max_addr; /* maximum mapped address */
Joerg Roedel00a77de2015-03-26 13:43:08 +0100341
342 struct iommu_domain domain; /* generic domain data structure for
343 iommu core */
Mark McLoughlin99126f72008-11-20 15:49:47 +0000344};
345
Mark McLoughlina647dac2008-11-20 15:49:48 +0000346/* PCI domain-device relationship */
347struct device_domain_info {
348 struct list_head link; /* link to domain siblings */
349 struct list_head global; /* link to global list */
David Woodhouse276dbf992009-04-04 01:45:37 +0100350 u8 bus; /* PCI bus number */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000351 u8 devfn; /* PCI devfn number */
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000352 struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
Yu Zhao93a23a72009-05-18 13:51:37 +0800353 struct intel_iommu *iommu; /* IOMMU used by this device */
Mark McLoughlina647dac2008-11-20 15:49:48 +0000354 struct dmar_domain *domain; /* pointer to domain */
355};
356
Jiang Liub94e4112014-02-19 14:07:25 +0800357struct dmar_rmrr_unit {
358 struct list_head list; /* list of rmrr units */
359 struct acpi_dmar_header *hdr; /* ACPI header */
360 u64 base_address; /* reserved base address*/
361 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000362 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800363 int devices_cnt; /* target device count */
364};
365
366struct dmar_atsr_unit {
367 struct list_head list; /* list of ATSR units */
368 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000369 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800370 int devices_cnt; /* target device count */
371 u8 include_all:1; /* include all ports */
372};
373
374static LIST_HEAD(dmar_atsr_units);
375static LIST_HEAD(dmar_rmrr_units);
376
377#define for_each_rmrr_units(rmrr) \
378 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
379
mark gross5e0d2a62008-03-04 15:22:08 -0800380static void flush_unmaps_timeout(unsigned long data);
381
Jiang Liub707cb02014-01-06 14:18:26 +0800382static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
mark gross5e0d2a62008-03-04 15:22:08 -0800383
mark gross80b20dd2008-04-18 13:53:58 -0700384#define HIGH_WATER_MARK 250
385struct deferred_flush_tables {
386 int next;
387 struct iova *iova[HIGH_WATER_MARK];
388 struct dmar_domain *domain[HIGH_WATER_MARK];
David Woodhouseea8ea462014-03-05 17:09:32 +0000389 struct page *freelist[HIGH_WATER_MARK];
mark gross80b20dd2008-04-18 13:53:58 -0700390};
391
392static struct deferred_flush_tables *deferred_flush;
393
mark gross5e0d2a62008-03-04 15:22:08 -0800394/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800395static int g_num_of_iommus;
396
397static DEFINE_SPINLOCK(async_umap_flush_lock);
398static LIST_HEAD(unmaps_to_do);
399
400static int timer_on;
401static long list_size;
mark gross5e0d2a62008-03-04 15:22:08 -0800402
Jiang Liu92d03cc2014-02-19 14:07:28 +0800403static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700404static void domain_remove_dev_info(struct dmar_domain *domain);
Jiang Liub94e4112014-02-19 14:07:25 +0800405static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -0700406 struct device *dev);
Jiang Liu92d03cc2014-02-19 14:07:28 +0800407static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +0000408 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800409static int domain_detach_iommu(struct dmar_domain *domain,
410 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700411
Suresh Siddhad3f13812011-08-23 17:05:25 -0700412#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800413int dmar_disabled = 0;
414#else
415int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700416#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800417
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200418int intel_iommu_enabled = 0;
419EXPORT_SYMBOL_GPL(intel_iommu_enabled);
420
David Woodhouse2d9e6672010-06-15 10:57:57 +0100421static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700422static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800423static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100424static int intel_iommu_superpage = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700425
David Woodhousec0771df2011-10-14 20:59:46 +0100426int intel_iommu_gfx_mapped;
427EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
428
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700429#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
430static DEFINE_SPINLOCK(device_domain_lock);
431static LIST_HEAD(device_domain_list);
432
Thierry Redingb22f6432014-06-27 09:03:12 +0200433static const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100434
Joerg Roedel00a77de2015-03-26 13:43:08 +0100435/* Convert generic 'struct iommu_domain to private struct dmar_domain */
436static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
437{
438 return container_of(dom, struct dmar_domain, domain);
439}
440
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700441static int __init intel_iommu_setup(char *str)
442{
443 if (!str)
444 return -EINVAL;
445 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800446 if (!strncmp(str, "on", 2)) {
447 dmar_disabled = 0;
448 printk(KERN_INFO "Intel-IOMMU: enabled\n");
449 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700450 dmar_disabled = 1;
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800451 printk(KERN_INFO "Intel-IOMMU: disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700452 } else if (!strncmp(str, "igfx_off", 8)) {
453 dmar_map_gfx = 0;
454 printk(KERN_INFO
455 "Intel-IOMMU: disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700456 } else if (!strncmp(str, "forcedac", 8)) {
mark gross5e0d2a62008-03-04 15:22:08 -0800457 printk(KERN_INFO
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700458 "Intel-IOMMU: Forcing DAC for PCI devices\n");
459 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800460 } else if (!strncmp(str, "strict", 6)) {
461 printk(KERN_INFO
462 "Intel-IOMMU: disable batched IOTLB flush\n");
463 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100464 } else if (!strncmp(str, "sp_off", 6)) {
465 printk(KERN_INFO
466 "Intel-IOMMU: disable supported super page\n");
467 intel_iommu_superpage = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700468 }
469
470 str += strcspn(str, ",");
471 while (*str == ',')
472 str++;
473 }
474 return 0;
475}
476__setup("intel_iommu=", intel_iommu_setup);
477
478static struct kmem_cache *iommu_domain_cache;
479static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700480
Suresh Siddha4c923d42009-10-02 11:01:24 -0700481static inline void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700482{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700483 struct page *page;
484 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700485
Suresh Siddha4c923d42009-10-02 11:01:24 -0700486 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
487 if (page)
488 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700489 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700490}
491
492static inline void free_pgtable_page(void *vaddr)
493{
494 free_page((unsigned long)vaddr);
495}
496
497static inline void *alloc_domain_mem(void)
498{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900499 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700500}
501
Kay, Allen M38717942008-09-09 18:37:29 +0300502static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700503{
504 kmem_cache_free(iommu_domain_cache, vaddr);
505}
506
507static inline void * alloc_devinfo_mem(void)
508{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900509 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700510}
511
512static inline void free_devinfo_mem(void *vaddr)
513{
514 kmem_cache_free(iommu_devinfo_cache, vaddr);
515}
516
Jiang Liuab8dfe22014-07-11 14:19:27 +0800517static inline int domain_type_is_vm(struct dmar_domain *domain)
518{
519 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
520}
521
522static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
523{
524 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
525 DOMAIN_FLAG_STATIC_IDENTITY);
526}
Weidong Han1b573682008-12-08 15:34:06 +0800527
Jiang Liu162d1b12014-07-11 14:19:35 +0800528static inline int domain_pfn_supported(struct dmar_domain *domain,
529 unsigned long pfn)
530{
531 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
532
533 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
534}
535
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700536static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800537{
538 unsigned long sagaw;
539 int agaw = -1;
540
541 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700542 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800543 agaw >= 0; agaw--) {
544 if (test_bit(agaw, &sagaw))
545 break;
546 }
547
548 return agaw;
549}
550
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700551/*
552 * Calculate max SAGAW for each iommu.
553 */
554int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
555{
556 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
557}
558
559/*
560 * calculate agaw for each iommu.
561 * "SAGAW" may be different across iommus, use a default agaw, and
562 * get a supported less agaw for iommus that don't support the default agaw.
563 */
564int iommu_calculate_agaw(struct intel_iommu *iommu)
565{
566 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
567}
568
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700569/* This functionin only returns single iommu in a domain */
Weidong Han8c11e792008-12-08 15:29:22 +0800570static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
571{
572 int iommu_id;
573
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700574 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800575 BUG_ON(domain_type_is_vm_or_si(domain));
Mike Travis1b198bb2012-03-05 15:05:16 -0800576 iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
Weidong Han8c11e792008-12-08 15:29:22 +0800577 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
578 return NULL;
579
580 return g_iommus[iommu_id];
581}
582
Weidong Han8e6040972008-12-08 15:49:06 +0800583static void domain_update_iommu_coherency(struct dmar_domain *domain)
584{
David Woodhoused0501962014-03-11 17:10:29 -0700585 struct dmar_drhd_unit *drhd;
586 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100587 bool found = false;
588 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800589
David Woodhoused0501962014-03-11 17:10:29 -0700590 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800591
Mike Travis1b198bb2012-03-05 15:05:16 -0800592 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100593 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800594 if (!ecap_coherent(g_iommus[i]->ecap)) {
595 domain->iommu_coherency = 0;
596 break;
597 }
Weidong Han8e6040972008-12-08 15:49:06 +0800598 }
David Woodhoused0501962014-03-11 17:10:29 -0700599 if (found)
600 return;
601
602 /* No hardware attached; use lowest common denominator */
603 rcu_read_lock();
604 for_each_active_iommu(iommu, drhd) {
605 if (!ecap_coherent(iommu->ecap)) {
606 domain->iommu_coherency = 0;
607 break;
608 }
609 }
610 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800611}
612
Jiang Liu161f6932014-07-11 14:19:37 +0800613static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100614{
Allen Kay8140a952011-10-14 12:32:17 -0700615 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800616 struct intel_iommu *iommu;
617 int ret = 1;
618
619 rcu_read_lock();
620 for_each_active_iommu(iommu, drhd) {
621 if (iommu != skip) {
622 if (!ecap_sc_support(iommu->ecap)) {
623 ret = 0;
624 break;
625 }
626 }
627 }
628 rcu_read_unlock();
629
630 return ret;
631}
632
633static int domain_update_iommu_superpage(struct intel_iommu *skip)
634{
635 struct dmar_drhd_unit *drhd;
636 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700637 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100638
639 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800640 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100641 }
642
Allen Kay8140a952011-10-14 12:32:17 -0700643 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800644 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700645 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800646 if (iommu != skip) {
647 mask &= cap_super_page_val(iommu->cap);
648 if (!mask)
649 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100650 }
651 }
Jiang Liu0e242612014-02-19 14:07:34 +0800652 rcu_read_unlock();
653
Jiang Liu161f6932014-07-11 14:19:37 +0800654 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100655}
656
Sheng Yang58c610b2009-03-18 15:33:05 +0800657/* Some capabilities may be different across iommus */
658static void domain_update_iommu_cap(struct dmar_domain *domain)
659{
660 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800661 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
662 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800663}
664
David Woodhouse03ecc322015-02-13 14:35:21 +0000665static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu,
666 u8 bus, u8 devfn, int alloc)
667{
668 struct root_entry *root = &iommu->root_entry[bus];
669 struct context_entry *context;
670 u64 *entry;
671
672 if (ecap_ecs(iommu->ecap)) {
673 if (devfn >= 0x80) {
674 devfn -= 0x80;
675 entry = &root->hi;
676 }
677 devfn *= 2;
678 }
679 entry = &root->lo;
680 if (*entry & 1)
681 context = phys_to_virt(*entry & VTD_PAGE_MASK);
682 else {
683 unsigned long phy_addr;
684 if (!alloc)
685 return NULL;
686
687 context = alloc_pgtable_page(iommu->node);
688 if (!context)
689 return NULL;
690
691 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
692 phy_addr = virt_to_phys((void *)context);
693 *entry = phy_addr | 1;
694 __iommu_flush_cache(iommu, entry, sizeof(*entry));
695 }
696 return &context[devfn];
697}
698
David Woodhouse156baca2014-03-09 14:00:57 -0700699static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800700{
701 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800702 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700703 struct device *tmp;
704 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800705 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800706 int i;
707
David Woodhouse156baca2014-03-09 14:00:57 -0700708 if (dev_is_pci(dev)) {
709 pdev = to_pci_dev(dev);
710 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100711 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700712 dev = &ACPI_COMPANION(dev)->dev;
713
Jiang Liu0e242612014-02-19 14:07:34 +0800714 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800715 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700716 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100717 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800718
Jiang Liub683b232014-02-19 14:07:32 +0800719 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700720 drhd->devices_cnt, i, tmp) {
721 if (tmp == dev) {
722 *bus = drhd->devices[i].bus;
723 *devfn = drhd->devices[i].devfn;
724 goto out;
725 }
726
727 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000728 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700729
730 ptmp = to_pci_dev(tmp);
731 if (ptmp->subordinate &&
732 ptmp->subordinate->number <= pdev->bus->number &&
733 ptmp->subordinate->busn_res.end >= pdev->bus->number)
734 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100735 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800736
David Woodhouse156baca2014-03-09 14:00:57 -0700737 if (pdev && drhd->include_all) {
738 got_pdev:
739 *bus = pdev->bus->number;
740 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800741 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700742 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800743 }
Jiang Liub683b232014-02-19 14:07:32 +0800744 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700745 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800746 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800747
Jiang Liub683b232014-02-19 14:07:32 +0800748 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800749}
750
Weidong Han5331fe62008-12-08 23:00:00 +0800751static void domain_flush_cache(struct dmar_domain *domain,
752 void *addr, int size)
753{
754 if (!domain->iommu_coherency)
755 clflush_cache_range(addr, size);
756}
757
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700758static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
759{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700760 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000761 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700762 unsigned long flags;
763
764 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000765 context = iommu_context_addr(iommu, bus, devfn, 0);
766 if (context)
767 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700768 spin_unlock_irqrestore(&iommu->lock, flags);
769 return ret;
770}
771
772static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
773{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700774 struct context_entry *context;
775 unsigned long flags;
776
777 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000778 context = iommu_context_addr(iommu, bus, devfn, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700779 if (context) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000780 context_clear_entry(context);
781 __iommu_flush_cache(iommu, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700782 }
783 spin_unlock_irqrestore(&iommu->lock, flags);
784}
785
786static void free_context_table(struct intel_iommu *iommu)
787{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700788 int i;
789 unsigned long flags;
790 struct context_entry *context;
791
792 spin_lock_irqsave(&iommu->lock, flags);
793 if (!iommu->root_entry) {
794 goto out;
795 }
796 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000797 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700798 if (context)
799 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000800
801 if (!ecap_ecs(iommu->ecap))
802 continue;
803
804 context = iommu_context_addr(iommu, i, 0x80, 0);
805 if (context)
806 free_pgtable_page(context);
807
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700808 }
809 free_pgtable_page(iommu->root_entry);
810 iommu->root_entry = NULL;
811out:
812 spin_unlock_irqrestore(&iommu->lock, flags);
813}
814
David Woodhouseb026fd22009-06-28 10:37:25 +0100815static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000816 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700817{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700818 struct dma_pte *parent, *pte = NULL;
819 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700820 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700821
822 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200823
Jiang Liu162d1b12014-07-11 14:19:35 +0800824 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200825 /* Address beyond IOMMU's addressing capabilities. */
826 return NULL;
827
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700828 parent = domain->pgd;
829
David Woodhouse5cf0a762014-03-19 16:07:49 +0000830 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700831 void *tmp_page;
832
David Woodhouseb026fd22009-06-28 10:37:25 +0100833 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700834 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000835 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100836 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000837 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700838 break;
839
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000840 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100841 uint64_t pteval;
842
Suresh Siddha4c923d42009-10-02 11:01:24 -0700843 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700844
David Woodhouse206a73c12009-07-01 19:30:28 +0100845 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700846 return NULL;
David Woodhouse206a73c12009-07-01 19:30:28 +0100847
David Woodhousec85994e2009-07-01 19:21:24 +0100848 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400849 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 +0800850 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100851 /* Someone else set it while we were thinking; use theirs. */
852 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800853 else
David Woodhousec85994e2009-07-01 19:21:24 +0100854 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700855 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000856 if (level == 1)
857 break;
858
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000859 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700860 level--;
861 }
862
David Woodhouse5cf0a762014-03-19 16:07:49 +0000863 if (!*target_level)
864 *target_level = level;
865
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700866 return pte;
867}
868
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100869
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700870/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100871static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
872 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100873 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700874{
875 struct dma_pte *parent, *pte = NULL;
876 int total = agaw_to_level(domain->agaw);
877 int offset;
878
879 parent = domain->pgd;
880 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100881 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700882 pte = &parent[offset];
883 if (level == total)
884 return pte;
885
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100886 if (!dma_pte_present(pte)) {
887 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700888 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100889 }
890
Yijing Wange16922a2014-05-20 20:37:51 +0800891 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100892 *large_page = total;
893 return pte;
894 }
895
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000896 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700897 total--;
898 }
899 return NULL;
900}
901
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700902/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000903static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf2009-06-27 22:09:11 +0100904 unsigned long start_pfn,
905 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700906{
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100907 unsigned int large_page = 1;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100908 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700909
Jiang Liu162d1b12014-07-11 14:19:35 +0800910 BUG_ON(!domain_pfn_supported(domain, start_pfn));
911 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700912 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100913
David Woodhouse04b18e62009-06-27 19:15:01 +0100914 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700915 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100916 large_page = 1;
917 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100918 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100919 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100920 continue;
921 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100922 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100923 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100924 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100925 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100926 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
927
David Woodhouse310a5ab2009-06-28 18:52:20 +0100928 domain_flush_cache(domain, first_pte,
929 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700930
931 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700932}
933
Alex Williamson3269ee02013-06-15 10:27:19 -0600934static void dma_pte_free_level(struct dmar_domain *domain, int level,
935 struct dma_pte *pte, unsigned long pfn,
936 unsigned long start_pfn, unsigned long last_pfn)
937{
938 pfn = max(start_pfn, pfn);
939 pte = &pte[pfn_level_offset(pfn, level)];
940
941 do {
942 unsigned long level_pfn;
943 struct dma_pte *level_pte;
944
945 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
946 goto next;
947
948 level_pfn = pfn & level_mask(level - 1);
949 level_pte = phys_to_virt(dma_pte_addr(pte));
950
951 if (level > 2)
952 dma_pte_free_level(domain, level - 1, level_pte,
953 level_pfn, start_pfn, last_pfn);
954
955 /* If range covers entire pagetable, free it */
956 if (!(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -0800957 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -0600958 dma_clear_pte(pte);
959 domain_flush_cache(domain, pte, sizeof(*pte));
960 free_pgtable_page(level_pte);
961 }
962next:
963 pfn += level_size(level);
964 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
965}
966
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700967/* free page table pages. last level pte should already be cleared */
968static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +0100969 unsigned long start_pfn,
970 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700971{
Jiang Liu162d1b12014-07-11 14:19:35 +0800972 BUG_ON(!domain_pfn_supported(domain, start_pfn));
973 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700974 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700975
Jiang Liud41a4ad2014-07-11 14:19:34 +0800976 dma_pte_clear_range(domain, start_pfn, last_pfn);
977
David Woodhousef3a0a522009-06-30 03:40:07 +0100978 /* We don't need lock here; nobody else touches the iova range */
Alex Williamson3269ee02013-06-15 10:27:19 -0600979 dma_pte_free_level(domain, agaw_to_level(domain->agaw),
980 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +0100981
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700982 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +0100983 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700984 free_pgtable_page(domain->pgd);
985 domain->pgd = NULL;
986 }
987}
988
David Woodhouseea8ea462014-03-05 17:09:32 +0000989/* When a page at a given level is being unlinked from its parent, we don't
990 need to *modify* it at all. All we need to do is make a list of all the
991 pages which can be freed just as soon as we've flushed the IOTLB and we
992 know the hardware page-walk will no longer touch them.
993 The 'pte' argument is the *parent* PTE, pointing to the page that is to
994 be freed. */
995static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
996 int level, struct dma_pte *pte,
997 struct page *freelist)
998{
999 struct page *pg;
1000
1001 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1002 pg->freelist = freelist;
1003 freelist = pg;
1004
1005 if (level == 1)
1006 return freelist;
1007
Jiang Liuadeb2592014-04-09 10:20:39 +08001008 pte = page_address(pg);
1009 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001010 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1011 freelist = dma_pte_list_pagetables(domain, level - 1,
1012 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001013 pte++;
1014 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001015
1016 return freelist;
1017}
1018
1019static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1020 struct dma_pte *pte, unsigned long pfn,
1021 unsigned long start_pfn,
1022 unsigned long last_pfn,
1023 struct page *freelist)
1024{
1025 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1026
1027 pfn = max(start_pfn, pfn);
1028 pte = &pte[pfn_level_offset(pfn, level)];
1029
1030 do {
1031 unsigned long level_pfn;
1032
1033 if (!dma_pte_present(pte))
1034 goto next;
1035
1036 level_pfn = pfn & level_mask(level);
1037
1038 /* If range covers entire pagetable, free it */
1039 if (start_pfn <= level_pfn &&
1040 last_pfn >= level_pfn + level_size(level) - 1) {
1041 /* These suborbinate page tables are going away entirely. Don't
1042 bother to clear them; we're just going to *free* them. */
1043 if (level > 1 && !dma_pte_superpage(pte))
1044 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1045
1046 dma_clear_pte(pte);
1047 if (!first_pte)
1048 first_pte = pte;
1049 last_pte = pte;
1050 } else if (level > 1) {
1051 /* Recurse down into a level that isn't *entirely* obsolete */
1052 freelist = dma_pte_clear_level(domain, level - 1,
1053 phys_to_virt(dma_pte_addr(pte)),
1054 level_pfn, start_pfn, last_pfn,
1055 freelist);
1056 }
1057next:
1058 pfn += level_size(level);
1059 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1060
1061 if (first_pte)
1062 domain_flush_cache(domain, first_pte,
1063 (void *)++last_pte - (void *)first_pte);
1064
1065 return freelist;
1066}
1067
1068/* We can't just free the pages because the IOMMU may still be walking
1069 the page tables, and may have cached the intermediate levels. The
1070 pages can only be freed after the IOTLB flush has been done. */
1071struct page *domain_unmap(struct dmar_domain *domain,
1072 unsigned long start_pfn,
1073 unsigned long last_pfn)
1074{
David Woodhouseea8ea462014-03-05 17:09:32 +00001075 struct page *freelist = NULL;
1076
Jiang Liu162d1b12014-07-11 14:19:35 +08001077 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1078 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001079 BUG_ON(start_pfn > last_pfn);
1080
1081 /* we don't need lock here; nobody else touches the iova range */
1082 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1083 domain->pgd, 0, start_pfn, last_pfn, NULL);
1084
1085 /* free pgd */
1086 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1087 struct page *pgd_page = virt_to_page(domain->pgd);
1088 pgd_page->freelist = freelist;
1089 freelist = pgd_page;
1090
1091 domain->pgd = NULL;
1092 }
1093
1094 return freelist;
1095}
1096
1097void dma_free_pagelist(struct page *freelist)
1098{
1099 struct page *pg;
1100
1101 while ((pg = freelist)) {
1102 freelist = pg->freelist;
1103 free_pgtable_page(page_address(pg));
1104 }
1105}
1106
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001107/* iommu handling */
1108static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1109{
1110 struct root_entry *root;
1111 unsigned long flags;
1112
Suresh Siddha4c923d42009-10-02 11:01:24 -07001113 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001114 if (!root) {
1115 pr_err("IOMMU: allocating root entry for %s failed\n",
1116 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001117 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001118 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001119
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001120 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001121
1122 spin_lock_irqsave(&iommu->lock, flags);
1123 iommu->root_entry = root;
1124 spin_unlock_irqrestore(&iommu->lock, flags);
1125
1126 return 0;
1127}
1128
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001129static void iommu_set_root_entry(struct intel_iommu *iommu)
1130{
David Woodhouse03ecc322015-02-13 14:35:21 +00001131 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001132 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001133 unsigned long flag;
1134
David Woodhouse03ecc322015-02-13 14:35:21 +00001135 addr = virt_to_phys(iommu->root_entry);
1136 if (ecap_ecs(iommu->ecap))
1137 addr |= DMA_RTADDR_RTT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001138
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001139 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001140 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001141
David Woodhousec416daa2009-05-10 20:30:58 +01001142 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001143
1144 /* Make sure hardware complete it */
1145 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001146 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001147
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001148 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001149}
1150
1151static void iommu_flush_write_buffer(struct intel_iommu *iommu)
1152{
1153 u32 val;
1154 unsigned long flag;
1155
David Woodhouse9af88142009-02-13 23:18:03 +00001156 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001157 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001158
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001159 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001160 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001161
1162 /* Make sure hardware complete it */
1163 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001164 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001165
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001166 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001167}
1168
1169/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001170static void __iommu_flush_context(struct intel_iommu *iommu,
1171 u16 did, u16 source_id, u8 function_mask,
1172 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001173{
1174 u64 val = 0;
1175 unsigned long flag;
1176
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001177 switch (type) {
1178 case DMA_CCMD_GLOBAL_INVL:
1179 val = DMA_CCMD_GLOBAL_INVL;
1180 break;
1181 case DMA_CCMD_DOMAIN_INVL:
1182 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1183 break;
1184 case DMA_CCMD_DEVICE_INVL:
1185 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1186 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1187 break;
1188 default:
1189 BUG();
1190 }
1191 val |= DMA_CCMD_ICC;
1192
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001193 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001194 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1195
1196 /* Make sure hardware complete it */
1197 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1198 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1199
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001200 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001201}
1202
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001203/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001204static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1205 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001206{
1207 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1208 u64 val = 0, val_iva = 0;
1209 unsigned long flag;
1210
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001211 switch (type) {
1212 case DMA_TLB_GLOBAL_FLUSH:
1213 /* global flush doesn't need set IVA_REG */
1214 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1215 break;
1216 case DMA_TLB_DSI_FLUSH:
1217 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1218 break;
1219 case DMA_TLB_PSI_FLUSH:
1220 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001221 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001222 val_iva = size_order | addr;
1223 break;
1224 default:
1225 BUG();
1226 }
1227 /* Note: set drain read/write */
1228#if 0
1229 /*
1230 * This is probably to be super secure.. Looks like we can
1231 * ignore it without any impact.
1232 */
1233 if (cap_read_drain(iommu->cap))
1234 val |= DMA_TLB_READ_DRAIN;
1235#endif
1236 if (cap_write_drain(iommu->cap))
1237 val |= DMA_TLB_WRITE_DRAIN;
1238
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001239 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001240 /* Note: Only uses first TLB reg currently */
1241 if (val_iva)
1242 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1243 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1244
1245 /* Make sure hardware complete it */
1246 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1247 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1248
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001249 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001250
1251 /* check IOTLB invalidation granularity */
1252 if (DMA_TLB_IAIG(val) == 0)
1253 printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
1254 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
1255 pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001256 (unsigned long long)DMA_TLB_IIRG(type),
1257 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001258}
1259
David Woodhouse64ae8922014-03-09 12:52:30 -07001260static struct device_domain_info *
1261iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1262 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001263{
Quentin Lambert2f119c72015-02-06 10:59:53 +01001264 bool found = false;
Yu Zhao93a23a72009-05-18 13:51:37 +08001265 unsigned long flags;
1266 struct device_domain_info *info;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001267 struct pci_dev *pdev;
Yu Zhao93a23a72009-05-18 13:51:37 +08001268
1269 if (!ecap_dev_iotlb_support(iommu->ecap))
1270 return NULL;
1271
1272 if (!iommu->qi)
1273 return NULL;
1274
1275 spin_lock_irqsave(&device_domain_lock, flags);
1276 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001277 if (info->iommu == iommu && info->bus == bus &&
1278 info->devfn == devfn) {
Quentin Lambert2f119c72015-02-06 10:59:53 +01001279 found = true;
Yu Zhao93a23a72009-05-18 13:51:37 +08001280 break;
1281 }
1282 spin_unlock_irqrestore(&device_domain_lock, flags);
1283
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001284 if (!found || !info->dev || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001285 return NULL;
1286
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001287 pdev = to_pci_dev(info->dev);
1288
1289 if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
Yu Zhao93a23a72009-05-18 13:51:37 +08001290 return NULL;
1291
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001292 if (!dmar_find_matched_atsr_unit(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001293 return NULL;
1294
Yu Zhao93a23a72009-05-18 13:51:37 +08001295 return info;
1296}
1297
1298static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1299{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001300 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001301 return;
1302
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001303 pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
Yu Zhao93a23a72009-05-18 13:51:37 +08001304}
1305
1306static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1307{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001308 if (!info->dev || !dev_is_pci(info->dev) ||
1309 !pci_ats_enabled(to_pci_dev(info->dev)))
Yu Zhao93a23a72009-05-18 13:51:37 +08001310 return;
1311
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001312 pci_disable_ats(to_pci_dev(info->dev));
Yu Zhao93a23a72009-05-18 13:51:37 +08001313}
1314
1315static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1316 u64 addr, unsigned mask)
1317{
1318 u16 sid, qdep;
1319 unsigned long flags;
1320 struct device_domain_info *info;
1321
1322 spin_lock_irqsave(&device_domain_lock, flags);
1323 list_for_each_entry(info, &domain->devices, link) {
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001324 struct pci_dev *pdev;
1325 if (!info->dev || !dev_is_pci(info->dev))
1326 continue;
1327
1328 pdev = to_pci_dev(info->dev);
1329 if (!pci_ats_enabled(pdev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001330 continue;
1331
1332 sid = info->bus << 8 | info->devfn;
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001333 qdep = pci_ats_queue_depth(pdev);
Yu Zhao93a23a72009-05-18 13:51:37 +08001334 qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
1335 }
1336 spin_unlock_irqrestore(&device_domain_lock, flags);
1337}
1338
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001339static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
David Woodhouseea8ea462014-03-05 17:09:32 +00001340 unsigned long pfn, unsigned int pages, int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001341{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001342 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001343 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001344
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001345 BUG_ON(pages == 0);
1346
David Woodhouseea8ea462014-03-05 17:09:32 +00001347 if (ih)
1348 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001349 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001350 * Fallback to domain selective flush if no PSI support or the size is
1351 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001352 * PSI requires page size to be 2 ^ x, and the base address is naturally
1353 * aligned to the size
1354 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001355 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1356 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001357 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001358 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001359 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001360 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001361
1362 /*
Nadav Amit82653632010-04-01 13:24:40 +03001363 * In caching mode, changes of pages from non-present to present require
1364 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001365 */
Nadav Amit82653632010-04-01 13:24:40 +03001366 if (!cap_caching_mode(iommu->cap) || !map)
Yu Zhao93a23a72009-05-18 13:51:37 +08001367 iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001368}
1369
mark grossf8bab732008-02-08 04:18:38 -08001370static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1371{
1372 u32 pmen;
1373 unsigned long flags;
1374
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001375 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001376 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1377 pmen &= ~DMA_PMEN_EPM;
1378 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1379
1380 /* wait for the protected region status bit to clear */
1381 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1382 readl, !(pmen & DMA_PMEN_PRS), pmen);
1383
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001384 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001385}
1386
Jiang Liu2a41cce2014-07-11 14:19:33 +08001387static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001388{
1389 u32 sts;
1390 unsigned long flags;
1391
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001392 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001393 iommu->gcmd |= DMA_GCMD_TE;
1394 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001395
1396 /* Make sure hardware complete it */
1397 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001398 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001399
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001400 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001401}
1402
Jiang Liu2a41cce2014-07-11 14:19:33 +08001403static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001404{
1405 u32 sts;
1406 unsigned long flag;
1407
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001408 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001409 iommu->gcmd &= ~DMA_GCMD_TE;
1410 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1411
1412 /* Make sure hardware complete it */
1413 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001414 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001415
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001416 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001417}
1418
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001419
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001420static int iommu_init_domains(struct intel_iommu *iommu)
1421{
1422 unsigned long ndomains;
1423 unsigned long nlongs;
1424
1425 ndomains = cap_ndoms(iommu->cap);
Jiang Liu852bdb02014-01-06 14:18:11 +08001426 pr_debug("IOMMU%d: Number of Domains supported <%ld>\n",
1427 iommu->seq_id, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001428 nlongs = BITS_TO_LONGS(ndomains);
1429
Donald Dutile94a91b52009-08-20 16:51:34 -04001430 spin_lock_init(&iommu->lock);
1431
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001432 /* TBD: there might be 64K domains,
1433 * consider other allocation for future chip
1434 */
1435 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1436 if (!iommu->domain_ids) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001437 pr_err("IOMMU%d: allocating domain id array failed\n",
1438 iommu->seq_id);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001439 return -ENOMEM;
1440 }
1441 iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
1442 GFP_KERNEL);
1443 if (!iommu->domains) {
Jiang Liu852bdb02014-01-06 14:18:11 +08001444 pr_err("IOMMU%d: allocating domain array failed\n",
1445 iommu->seq_id);
1446 kfree(iommu->domain_ids);
1447 iommu->domain_ids = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001448 return -ENOMEM;
1449 }
1450
1451 /*
1452 * if Caching mode is set, then invalid translations are tagged
1453 * with domainid 0. Hence we need to pre-allocate it.
1454 */
1455 if (cap_caching_mode(iommu->cap))
1456 set_bit(0, iommu->domain_ids);
1457 return 0;
1458}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001459
Jiang Liuffebeb42014-11-09 22:48:02 +08001460static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001461{
1462 struct dmar_domain *domain;
Jiang Liu2a46ddf2014-07-11 14:19:30 +08001463 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001464
Donald Dutile94a91b52009-08-20 16:51:34 -04001465 if ((iommu->domains) && (iommu->domain_ids)) {
Akinobu Mitaa45946a2010-03-11 14:04:08 -08001466 for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
Jiang Liua4eaa862014-02-19 14:07:30 +08001467 /*
1468 * Domain id 0 is reserved for invalid translation
1469 * if hardware supports caching mode.
1470 */
1471 if (cap_caching_mode(iommu->cap) && i == 0)
1472 continue;
1473
Donald Dutile94a91b52009-08-20 16:51:34 -04001474 domain = iommu->domains[i];
1475 clear_bit(i, iommu->domain_ids);
Jiang Liu129ad282014-07-11 14:19:31 +08001476 if (domain_detach_iommu(domain, iommu) == 0 &&
1477 !domain_type_is_vm(domain))
Jiang Liu92d03cc2014-02-19 14:07:28 +08001478 domain_exit(domain);
Weidong Han5e98c4b2008-12-08 23:03:27 +08001479 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001480 }
1481
1482 if (iommu->gcmd & DMA_GCMD_TE)
1483 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001484}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001485
Jiang Liuffebeb42014-11-09 22:48:02 +08001486static void free_dmar_iommu(struct intel_iommu *iommu)
1487{
1488 if ((iommu->domains) && (iommu->domain_ids)) {
1489 kfree(iommu->domains);
1490 kfree(iommu->domain_ids);
1491 iommu->domains = NULL;
1492 iommu->domain_ids = NULL;
1493 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001494
Weidong Hand9630fe2008-12-08 11:06:32 +08001495 g_iommus[iommu->seq_id] = NULL;
1496
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001497 /* free context mapping */
1498 free_context_table(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001499}
1500
Jiang Liuab8dfe22014-07-11 14:19:27 +08001501static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001502{
Jiang Liu92d03cc2014-02-19 14:07:28 +08001503 /* domain id for virtual machine, it won't be set in context */
1504 static atomic_t vm_domid = ATOMIC_INIT(0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001505 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001506
1507 domain = alloc_domain_mem();
1508 if (!domain)
1509 return NULL;
1510
Jiang Liuab8dfe22014-07-11 14:19:27 +08001511 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001512 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001513 domain->flags = flags;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001514 spin_lock_init(&domain->iommu_lock);
1515 INIT_LIST_HEAD(&domain->devices);
Jiang Liuab8dfe22014-07-11 14:19:27 +08001516 if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
Jiang Liu92d03cc2014-02-19 14:07:28 +08001517 domain->id = atomic_inc_return(&vm_domid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001518
1519 return domain;
1520}
1521
Jiang Liufb170fb2014-07-11 14:19:28 +08001522static int __iommu_attach_domain(struct dmar_domain *domain,
1523 struct intel_iommu *iommu)
1524{
1525 int num;
1526 unsigned long ndomains;
1527
1528 ndomains = cap_ndoms(iommu->cap);
1529 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1530 if (num < ndomains) {
1531 set_bit(num, iommu->domain_ids);
1532 iommu->domains[num] = domain;
1533 } else {
1534 num = -ENOSPC;
1535 }
1536
1537 return num;
1538}
1539
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001540static int iommu_attach_domain(struct dmar_domain *domain,
1541 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001542{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001543 int num;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001544 unsigned long flags;
1545
Weidong Han8c11e792008-12-08 15:29:22 +08001546 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001547 num = __iommu_attach_domain(domain, iommu);
Jiang Liu44bde612014-07-11 14:19:29 +08001548 spin_unlock_irqrestore(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001549 if (num < 0)
1550 pr_err("IOMMU: no free domain ids\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001551
Jiang Liufb170fb2014-07-11 14:19:28 +08001552 return num;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001553}
1554
Jiang Liu44bde612014-07-11 14:19:29 +08001555static int iommu_attach_vm_domain(struct dmar_domain *domain,
1556 struct intel_iommu *iommu)
1557{
1558 int num;
1559 unsigned long ndomains;
1560
1561 ndomains = cap_ndoms(iommu->cap);
1562 for_each_set_bit(num, iommu->domain_ids, ndomains)
1563 if (iommu->domains[num] == domain)
1564 return num;
1565
1566 return __iommu_attach_domain(domain, iommu);
1567}
1568
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001569static void iommu_detach_domain(struct dmar_domain *domain,
1570 struct intel_iommu *iommu)
1571{
1572 unsigned long flags;
1573 int num, ndomains;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001574
1575 spin_lock_irqsave(&iommu->lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08001576 if (domain_type_is_vm_or_si(domain)) {
1577 ndomains = cap_ndoms(iommu->cap);
1578 for_each_set_bit(num, iommu->domain_ids, ndomains) {
1579 if (iommu->domains[num] == domain) {
1580 clear_bit(num, iommu->domain_ids);
1581 iommu->domains[num] = NULL;
1582 break;
1583 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001584 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001585 } else {
1586 clear_bit(domain->id, iommu->domain_ids);
1587 iommu->domains[domain->id] = NULL;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001588 }
Weidong Han8c11e792008-12-08 15:29:22 +08001589 spin_unlock_irqrestore(&iommu->lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001590}
1591
Jiang Liufb170fb2014-07-11 14:19:28 +08001592static void domain_attach_iommu(struct dmar_domain *domain,
1593 struct intel_iommu *iommu)
1594{
1595 unsigned long flags;
1596
1597 spin_lock_irqsave(&domain->iommu_lock, flags);
1598 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
1599 domain->iommu_count++;
1600 if (domain->iommu_count == 1)
1601 domain->nid = iommu->node;
1602 domain_update_iommu_cap(domain);
1603 }
1604 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1605}
1606
1607static int domain_detach_iommu(struct dmar_domain *domain,
1608 struct intel_iommu *iommu)
1609{
1610 unsigned long flags;
1611 int count = INT_MAX;
1612
1613 spin_lock_irqsave(&domain->iommu_lock, flags);
1614 if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
1615 count = --domain->iommu_count;
1616 domain_update_iommu_cap(domain);
1617 }
1618 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1619
1620 return count;
1621}
1622
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001623static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001624static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001625
Joseph Cihula51a63e62011-03-21 11:04:24 -07001626static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001627{
1628 struct pci_dev *pdev = NULL;
1629 struct iova *iova;
1630 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001631
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001632 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN,
1633 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001634
Mark Gross8a443df2008-03-04 14:59:31 -08001635 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1636 &reserved_rbtree_key);
1637
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001638 /* IOAPIC ranges shouldn't be accessed by DMA */
1639 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1640 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001641 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001642 printk(KERN_ERR "Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001643 return -ENODEV;
1644 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001645
1646 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1647 for_each_pci_dev(pdev) {
1648 struct resource *r;
1649
1650 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1651 r = &pdev->resource[i];
1652 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1653 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001654 iova = reserve_iova(&reserved_iova_list,
1655 IOVA_PFN(r->start),
1656 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001657 if (!iova) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001658 printk(KERN_ERR "Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001659 return -ENODEV;
1660 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001661 }
1662 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001663 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001664}
1665
1666static void domain_reserve_special_ranges(struct dmar_domain *domain)
1667{
1668 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1669}
1670
1671static inline int guestwidth_to_adjustwidth(int gaw)
1672{
1673 int agaw;
1674 int r = (gaw - 12) % 9;
1675
1676 if (r == 0)
1677 agaw = gaw;
1678 else
1679 agaw = gaw + 9 - r;
1680 if (agaw > 64)
1681 agaw = 64;
1682 return agaw;
1683}
1684
1685static int domain_init(struct dmar_domain *domain, int guest_width)
1686{
1687 struct intel_iommu *iommu;
1688 int adjust_width, agaw;
1689 unsigned long sagaw;
1690
Robin Murphy0fb5fe82015-01-12 17:51:16 +00001691 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
1692 DMA_32BIT_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001693 domain_reserve_special_ranges(domain);
1694
1695 /* calculate AGAW */
Weidong Han8c11e792008-12-08 15:29:22 +08001696 iommu = domain_get_iommu(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001697 if (guest_width > cap_mgaw(iommu->cap))
1698 guest_width = cap_mgaw(iommu->cap);
1699 domain->gaw = guest_width;
1700 adjust_width = guestwidth_to_adjustwidth(guest_width);
1701 agaw = width_to_agaw(adjust_width);
1702 sagaw = cap_sagaw(iommu->cap);
1703 if (!test_bit(agaw, &sagaw)) {
1704 /* hardware doesn't support it, choose a bigger one */
1705 pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
1706 agaw = find_next_bit(&sagaw, 5, agaw);
1707 if (agaw >= 5)
1708 return -ENODEV;
1709 }
1710 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711
Weidong Han8e6040972008-12-08 15:49:06 +08001712 if (ecap_coherent(iommu->ecap))
1713 domain->iommu_coherency = 1;
1714 else
1715 domain->iommu_coherency = 0;
1716
Sheng Yang58c610b2009-03-18 15:33:05 +08001717 if (ecap_sc_support(iommu->ecap))
1718 domain->iommu_snooping = 1;
1719 else
1720 domain->iommu_snooping = 0;
1721
David Woodhouse214e39a2014-03-19 10:38:49 +00001722 if (intel_iommu_superpage)
1723 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1724 else
1725 domain->iommu_superpage = 0;
1726
Suresh Siddha4c923d42009-10-02 11:01:24 -07001727 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001728
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001729 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001730 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001731 if (!domain->pgd)
1732 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001733 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001734 return 0;
1735}
1736
1737static void domain_exit(struct dmar_domain *domain)
1738{
David Woodhouseea8ea462014-03-05 17:09:32 +00001739 struct page *freelist = NULL;
Alex Williamson71684402015-03-04 11:30:10 -07001740 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001741
1742 /* Domain 0 is reserved, so dont process it */
1743 if (!domain)
1744 return;
1745
Alex Williamson7b668352011-05-24 12:02:41 +01001746 /* Flush any lazy unmaps that may reference this domain */
1747 if (!intel_iommu_strict)
1748 flush_unmaps_timeout(0);
1749
Jiang Liu92d03cc2014-02-19 14:07:28 +08001750 /* remove associated devices */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001751 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001752
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001753 /* destroy iovas */
1754 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001755
David Woodhouseea8ea462014-03-05 17:09:32 +00001756 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001757
Jiang Liu92d03cc2014-02-19 14:07:28 +08001758 /* clear attached or cached domains */
Jiang Liu0e242612014-02-19 14:07:34 +08001759 rcu_read_lock();
Alex Williamson71684402015-03-04 11:30:10 -07001760 for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus)
1761 iommu_detach_domain(domain, g_iommus[i]);
Jiang Liu0e242612014-02-19 14:07:34 +08001762 rcu_read_unlock();
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001763
David Woodhouseea8ea462014-03-05 17:09:32 +00001764 dma_free_pagelist(freelist);
1765
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001766 free_domain_mem(domain);
1767}
1768
David Woodhouse64ae8922014-03-09 12:52:30 -07001769static int domain_context_mapping_one(struct dmar_domain *domain,
1770 struct intel_iommu *iommu,
1771 u8 bus, u8 devfn, int translation)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001772{
1773 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001774 unsigned long flags;
Weidong Hanea6606b2008-12-08 23:08:15 +08001775 struct dma_pte *pgd;
Weidong Hanea6606b2008-12-08 23:08:15 +08001776 int id;
1777 int agaw;
Yu Zhao93a23a72009-05-18 13:51:37 +08001778 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001779
1780 pr_debug("Set context mapping for %02x:%02x.%d\n",
1781 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001782
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001783 BUG_ON(!domain->pgd);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001784 BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
1785 translation != CONTEXT_TT_MULTI_LEVEL);
Weidong Han5331fe62008-12-08 23:00:00 +08001786
David Woodhouse03ecc322015-02-13 14:35:21 +00001787 spin_lock_irqsave(&iommu->lock, flags);
1788 context = iommu_context_addr(iommu, bus, devfn, 1);
1789 spin_unlock_irqrestore(&iommu->lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001790 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 Mingarelliea2447f2012-11-20 19:43:17 +00002514{
2515 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002516 struct device *tmp;
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002517 int i;
2518
Jiang Liu0e242612014-02-19 14:07:34 +08002519 rcu_read_lock();
Tom Mingarelliea2447f2012-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 Mingarelliea2447f2012-11-20 19:43:17 +00002529 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002530 }
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002531 }
Jiang Liu0e242612014-02-19 14:07:34 +08002532 rcu_read_unlock();
Tom Mingarelliea2447f2012-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.
David Woodhouse18436af2015-03-25 15:05:47 +00002553 *
2554 * The same exception is made for graphics devices, with the requirement that
2555 * any use of the RMRR regions will be torn down before assigning the device
2556 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002557 */
2558static bool device_is_rmrr_locked(struct device *dev)
2559{
2560 if (!device_has_rmrr(dev))
2561 return false;
2562
2563 if (dev_is_pci(dev)) {
2564 struct pci_dev *pdev = to_pci_dev(dev);
2565
David Woodhouse18436af2015-03-25 15:05:47 +00002566 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002567 return false;
2568 }
2569
2570 return true;
2571}
2572
David Woodhouse3bdb2592014-03-09 16:03:08 -07002573static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002574{
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002575
David Woodhouse3bdb2592014-03-09 16:03:08 -07002576 if (dev_is_pci(dev)) {
2577 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f2012-11-20 19:43:17 +00002578
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002579 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002580 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002581
David Woodhouse3bdb2592014-03-09 16:03:08 -07002582 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2583 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002584
David Woodhouse3bdb2592014-03-09 16:03:08 -07002585 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2586 return 1;
2587
2588 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2589 return 0;
2590
2591 /*
2592 * We want to start off with all devices in the 1:1 domain, and
2593 * take them out later if we find they can't access all of memory.
2594 *
2595 * However, we can't do this for PCI devices behind bridges,
2596 * because all PCI devices behind the same bridge will end up
2597 * with the same source-id on their transactions.
2598 *
2599 * Practically speaking, we can't change things around for these
2600 * devices at run-time, because we can't be sure there'll be no
2601 * DMA transactions in flight for any of their siblings.
2602 *
2603 * So PCI devices (unless they're on the root bus) as well as
2604 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2605 * the 1:1 domain, just in _case_ one of their siblings turns out
2606 * not to be able to map all of memory.
2607 */
2608 if (!pci_is_pcie(pdev)) {
2609 if (!pci_is_root_bus(pdev->bus))
2610 return 0;
2611 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2612 return 0;
2613 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2614 return 0;
2615 } else {
2616 if (device_has_rmrr(dev))
2617 return 0;
2618 }
David Woodhouse6941af22009-07-04 18:24:27 +01002619
David Woodhouse3dfc8132009-07-04 19:11:08 +01002620 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002621 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002622 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002623 * take them out of the 1:1 domain later.
2624 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002625 if (!startup) {
2626 /*
2627 * If the device's dma_mask is less than the system's memory
2628 * size then this is not a candidate for identity mapping.
2629 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002630 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002631
David Woodhouse3bdb2592014-03-09 16:03:08 -07002632 if (dev->coherent_dma_mask &&
2633 dev->coherent_dma_mask < dma_mask)
2634 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002635
David Woodhouse3bdb2592014-03-09 16:03:08 -07002636 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05002637 }
David Woodhouse6941af22009-07-04 18:24:27 +01002638
2639 return 1;
2640}
2641
David Woodhousecf04eee2014-03-21 16:49:04 +00002642static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
2643{
2644 int ret;
2645
2646 if (!iommu_should_identity_map(dev, 1))
2647 return 0;
2648
2649 ret = domain_add_dev_info(si_domain, dev,
2650 hw ? CONTEXT_TT_PASS_THROUGH :
2651 CONTEXT_TT_MULTI_LEVEL);
2652 if (!ret)
2653 pr_info("IOMMU: %s identity mapping for device %s\n",
2654 hw ? "hardware" : "software", dev_name(dev));
2655 else if (ret == -ENODEV)
2656 /* device not associated with an iommu */
2657 ret = 0;
2658
2659 return ret;
2660}
2661
2662
Matt Kraai071e1372009-08-23 22:30:22 -07002663static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002664{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002665 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00002666 struct dmar_drhd_unit *drhd;
2667 struct intel_iommu *iommu;
2668 struct device *dev;
2669 int i;
2670 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002671
David Woodhouse19943b02009-08-04 16:19:20 +01002672 ret = si_domain_init(hw);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002673 if (ret)
2674 return -EFAULT;
2675
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002676 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00002677 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
2678 if (ret)
2679 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002680 }
2681
David Woodhousecf04eee2014-03-21 16:49:04 +00002682 for_each_active_iommu(iommu, drhd)
2683 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
2684 struct acpi_device_physical_node *pn;
2685 struct acpi_device *adev;
2686
2687 if (dev->bus != &acpi_bus_type)
2688 continue;
2689
2690 adev= to_acpi_device(dev);
2691 mutex_lock(&adev->physical_node_lock);
2692 list_for_each_entry(pn, &adev->physical_node_list, node) {
2693 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
2694 if (ret)
2695 break;
2696 }
2697 mutex_unlock(&adev->physical_node_lock);
2698 if (ret)
2699 return ret;
2700 }
2701
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002702 return 0;
2703}
2704
Jiang Liuffebeb42014-11-09 22:48:02 +08002705static void intel_iommu_init_qi(struct intel_iommu *iommu)
2706{
2707 /*
2708 * Start from the sane iommu hardware state.
2709 * If the queued invalidation is already initialized by us
2710 * (for example, while enabling interrupt-remapping) then
2711 * we got the things already rolling from a sane state.
2712 */
2713 if (!iommu->qi) {
2714 /*
2715 * Clear any previous faults.
2716 */
2717 dmar_fault(-1, iommu);
2718 /*
2719 * Disable queued invalidation if supported and already enabled
2720 * before OS handover.
2721 */
2722 dmar_disable_qi(iommu);
2723 }
2724
2725 if (dmar_enable_qi(iommu)) {
2726 /*
2727 * Queued Invalidate not enabled, use Register Based Invalidate
2728 */
2729 iommu->flush.flush_context = __iommu_flush_context;
2730 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
2731 pr_info("IOMMU: %s using Register based invalidation\n",
2732 iommu->name);
2733 } else {
2734 iommu->flush.flush_context = qi_flush_context;
2735 iommu->flush.flush_iotlb = qi_flush_iotlb;
2736 pr_info("IOMMU: %s using Queued invalidation\n", iommu->name);
2737 }
2738}
2739
Joseph Cihulab7792602011-05-03 00:08:37 -07002740static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002741{
2742 struct dmar_drhd_unit *drhd;
2743 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002744 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002745 struct intel_iommu *iommu;
Suresh Siddha9d783ba2009-03-16 17:04:55 -07002746 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002747
2748 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002749 * for each drhd
2750 * allocate root
2751 * initialize and program root entry to not present
2752 * endfor
2753 */
2754 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08002755 /*
2756 * lock not needed as this is only incremented in the single
2757 * threaded kernel __init code path all other access are read
2758 * only
2759 */
Jiang Liu78d8e702014-11-09 22:47:57 +08002760 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08002761 g_num_of_iommus++;
2762 continue;
2763 }
2764 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
Jiang Liu78d8e702014-11-09 22:47:57 +08002765 DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08002766 }
2767
Jiang Liuffebeb42014-11-09 22:48:02 +08002768 /* Preallocate enough resources for IOMMU hot-addition */
2769 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
2770 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
2771
Weidong Hand9630fe2008-12-08 11:06:32 +08002772 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
2773 GFP_KERNEL);
2774 if (!g_iommus) {
2775 printk(KERN_ERR "Allocating global iommu array failed\n");
2776 ret = -ENOMEM;
2777 goto error;
2778 }
2779
mark gross80b20dd2008-04-18 13:53:58 -07002780 deferred_flush = kzalloc(g_num_of_iommus *
2781 sizeof(struct deferred_flush_tables), GFP_KERNEL);
2782 if (!deferred_flush) {
mark gross5e0d2a62008-03-04 15:22:08 -08002783 ret = -ENOMEM;
Jiang Liu989d51f2014-02-19 14:07:21 +08002784 goto free_g_iommus;
mark gross5e0d2a62008-03-04 15:22:08 -08002785 }
2786
Jiang Liu7c919772014-01-06 14:18:18 +08002787 for_each_active_iommu(iommu, drhd) {
Weidong Hand9630fe2008-12-08 11:06:32 +08002788 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002789
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002790 ret = iommu_init_domains(iommu);
2791 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002792 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07002793
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002794 /*
2795 * TBD:
2796 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002797 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002798 */
2799 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002800 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002801 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002802 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01002803 hw_pass_through = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002804 }
2805
Jiang Liuffebeb42014-11-09 22:48:02 +08002806 for_each_active_iommu(iommu, drhd)
2807 intel_iommu_init_qi(iommu);
Youquan Songa77b67d2008-10-16 16:31:56 -07002808
David Woodhouse19943b02009-08-04 16:19:20 +01002809 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07002810 iommu_identity_mapping |= IDENTMAP_ALL;
2811
Suresh Siddhad3f13812011-08-23 17:05:25 -07002812#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07002813 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01002814#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07002815
2816 check_tylersburg_isoch();
2817
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002818 /*
2819 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002820 * identity mappings for rmrr, gfx, and isa and may fall back to static
2821 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002822 */
David Woodhouse19943b02009-08-04 16:19:20 +01002823 if (iommu_identity_mapping) {
2824 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
2825 if (ret) {
2826 printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08002827 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002828 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002829 }
David Woodhouse19943b02009-08-04 16:19:20 +01002830 /*
2831 * For each rmrr
2832 * for each dev attached to rmrr
2833 * do
2834 * locate drhd for dev, alloc domain for dev
2835 * allocate free domain
2836 * allocate page table entries for rmrr
2837 * if context not allocated for bus
2838 * allocate and init context
2839 * set present in root table for this bus
2840 * init context with domain, translation etc
2841 * endfor
2842 * endfor
2843 */
2844 printk(KERN_INFO "IOMMU: Setting RMRR:\n");
2845 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002846 /* some BIOS lists non-exist devices in DMAR table. */
2847 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00002848 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07002849 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01002850 if (ret)
2851 printk(KERN_ERR
2852 "IOMMU: mapping reserved region failed\n");
2853 }
2854 }
2855
2856 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002857
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002858 /*
2859 * for each drhd
2860 * enable fault log
2861 * global invalidate context cache
2862 * global invalidate iotlb
2863 * enable translation
2864 */
Jiang Liu7c919772014-01-06 14:18:18 +08002865 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07002866 if (drhd->ignored) {
2867 /*
2868 * we always have to disable PMRs or DMA may fail on
2869 * this device
2870 */
2871 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08002872 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002873 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07002874 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002875
2876 iommu_flush_write_buffer(iommu);
2877
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002878 ret = dmar_set_interrupt(iommu);
2879 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08002880 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07002881
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002882 iommu_set_root_entry(iommu);
2883
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002884 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01002885 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
Jiang Liu2a41cce2014-07-11 14:19:33 +08002886 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07002887 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002888 }
2889
2890 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08002891
2892free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08002893 for_each_active_iommu(iommu, drhd) {
2894 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08002895 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08002896 }
Jiang Liu9bdc5312014-01-06 14:18:27 +08002897 kfree(deferred_flush);
Jiang Liu989d51f2014-02-19 14:07:21 +08002898free_g_iommus:
Weidong Hand9630fe2008-12-08 11:06:32 +08002899 kfree(g_iommus);
Jiang Liu989d51f2014-02-19 14:07:21 +08002900error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002901 return ret;
2902}
2903
David Woodhouse5a5e02a2009-07-04 09:35:44 +01002904/* This takes a number of _MM_ pages, not VTD pages */
David Woodhouse875764d2009-06-28 21:20:51 +01002905static struct iova *intel_alloc_iova(struct device *dev,
2906 struct dmar_domain *domain,
2907 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002908{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002909 struct iova *iova = NULL;
2910
David Woodhouse875764d2009-06-28 21:20:51 +01002911 /* Restrict dma_mask to the width that the iommu can handle */
2912 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
2913
2914 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002915 /*
2916 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07002917 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08002918 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002919 */
David Woodhouse875764d2009-06-28 21:20:51 +01002920 iova = alloc_iova(&domain->iovad, nrpages,
2921 IOVA_PFN(DMA_BIT_MASK(32)), 1);
2922 if (iova)
2923 return iova;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002924 }
David Woodhouse875764d2009-06-28 21:20:51 +01002925 iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
2926 if (unlikely(!iova)) {
2927 printk(KERN_ERR "Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07002928 nrpages, dev_name(dev));
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002929 return NULL;
2930 }
2931
2932 return iova;
2933}
2934
David Woodhoused4b709f2014-03-09 16:07:40 -07002935static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002936{
2937 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002938 int ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002939
David Woodhoused4b709f2014-03-09 16:07:40 -07002940 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002941 if (!domain) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002942 printk(KERN_ERR "Allocating domain for %s failed",
2943 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002944 return NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002945 }
2946
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002947 /* make sure context mapping is ok */
David Woodhoused4b709f2014-03-09 16:07:40 -07002948 if (unlikely(!domain_context_mapped(dev))) {
2949 ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002950 if (ret) {
David Woodhoused4b709f2014-03-09 16:07:40 -07002951 printk(KERN_ERR "Domain context map for %s failed",
2952 dev_name(dev));
Al Viro4fe05bb2007-10-29 04:51:16 +00002953 return NULL;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002954 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002955 }
2956
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07002957 return domain;
2958}
2959
David Woodhoused4b709f2014-03-09 16:07:40 -07002960static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
David Woodhouse147202a2009-07-07 19:43:20 +01002961{
2962 struct device_domain_info *info;
2963
2964 /* No lock here, assumes no domain exit in normal case */
David Woodhoused4b709f2014-03-09 16:07:40 -07002965 info = dev->archdata.iommu;
David Woodhouse147202a2009-07-07 19:43:20 +01002966 if (likely(info))
2967 return info->domain;
2968
2969 return __get_valid_domain_for_dev(dev);
2970}
2971
David Woodhouse3d891942014-03-06 15:59:26 +00002972static int iommu_dummy(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002973{
David Woodhouse3d891942014-03-06 15:59:26 +00002974 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002975}
2976
David Woodhouseecb509e2014-03-09 16:29:55 -07002977/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01002978static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002979{
2980 int found;
2981
David Woodhouse3d891942014-03-06 15:59:26 +00002982 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002983 return 1;
2984
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002985 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01002986 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002987
David Woodhouse9b226622014-03-09 14:03:28 -07002988 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002989 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07002990 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002991 return 1;
2992 else {
2993 /*
2994 * 32 bit DMA is removed from si_domain and fall back
2995 * to non-identity mapping.
2996 */
David Woodhousebf9c9ed2014-03-09 16:19:13 -07002997 domain_remove_one_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002998 printk(KERN_INFO "32bit %s uses non-identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07002999 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003000 return 0;
3001 }
3002 } else {
3003 /*
3004 * In case of a detached 64 bit DMA device from vm, the device
3005 * is put into si_domain for identity mapping.
3006 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003007 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003008 int ret;
David Woodhouse5913c9b2014-03-09 16:27:31 -07003009 ret = domain_add_dev_info(si_domain, dev,
David Woodhouse5fe60f42009-08-09 10:53:41 +01003010 hw_pass_through ?
3011 CONTEXT_TT_PASS_THROUGH :
3012 CONTEXT_TT_MULTI_LEVEL);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003013 if (!ret) {
3014 printk(KERN_INFO "64bit %s uses identity mapping\n",
David Woodhouseecb509e2014-03-09 16:29:55 -07003015 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003016 return 1;
3017 }
3018 }
3019 }
3020
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003021 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003022}
3023
David Woodhouse5040a912014-03-09 16:14:00 -07003024static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003025 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003026{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003027 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003028 phys_addr_t start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003029 struct iova *iova;
3030 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003031 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003032 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003033 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003034
3035 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003036
David Woodhouse5040a912014-03-09 16:14:00 -07003037 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003038 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003039
David Woodhouse5040a912014-03-09 16:14:00 -07003040 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003041 if (!domain)
3042 return 0;
3043
Weidong Han8c11e792008-12-08 15:29:22 +08003044 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003045 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003046
David Woodhouse5040a912014-03-09 16:14:00 -07003047 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003048 if (!iova)
3049 goto error;
3050
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003051 /*
3052 * Check if DMAR supports zero-length reads on write only
3053 * mappings..
3054 */
3055 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003056 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003057 prot |= DMA_PTE_READ;
3058 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3059 prot |= DMA_PTE_WRITE;
3060 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003061 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003062 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003063 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003064 * is not a big problem
3065 */
David Woodhouse0ab36de2009-06-28 14:01:43 +01003066 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003067 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003068 if (ret)
3069 goto error;
3070
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003071 /* it's a non-present to present mapping. Only flush if caching mode */
3072 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003073 iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003074 else
Weidong Han8c11e792008-12-08 15:29:22 +08003075 iommu_flush_write_buffer(iommu);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003076
David Woodhouse03d6a242009-06-28 15:33:46 +01003077 start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
3078 start_paddr += paddr & ~PAGE_MASK;
3079 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003080
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003081error:
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003082 if (iova)
3083 __free_iova(&domain->iovad, iova);
David Woodhouse4cf2e752009-02-11 17:23:43 +00003084 printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003085 dev_name(dev), size, (unsigned long long)paddr, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003086 return 0;
3087}
3088
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003089static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3090 unsigned long offset, size_t size,
3091 enum dma_data_direction dir,
3092 struct dma_attrs *attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003093{
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003094 return __intel_map_single(dev, page_to_phys(page) + offset, size,
David Woodhouse46333e32014-03-10 20:01:21 -07003095 dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003096}
3097
mark gross5e0d2a62008-03-04 15:22:08 -08003098static void flush_unmaps(void)
3099{
mark gross80b20dd2008-04-18 13:53:58 -07003100 int i, j;
mark gross5e0d2a62008-03-04 15:22:08 -08003101
mark gross5e0d2a62008-03-04 15:22:08 -08003102 timer_on = 0;
3103
3104 /* just flush them all */
3105 for (i = 0; i < g_num_of_iommus; i++) {
Weidong Hana2bb8452008-12-08 11:24:12 +08003106 struct intel_iommu *iommu = g_iommus[i];
3107 if (!iommu)
3108 continue;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003109
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003110 if (!deferred_flush[i].next)
3111 continue;
3112
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003113 /* In caching mode, global flushes turn emulation expensive */
3114 if (!cap_caching_mode(iommu->cap))
3115 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
Yu Zhao93a23a72009-05-18 13:51:37 +08003116 DMA_TLB_GLOBAL_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003117 for (j = 0; j < deferred_flush[i].next; j++) {
Yu Zhao93a23a72009-05-18 13:51:37 +08003118 unsigned long mask;
3119 struct iova *iova = deferred_flush[i].iova[j];
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003120 struct dmar_domain *domain = deferred_flush[i].domain[j];
Yu Zhao93a23a72009-05-18 13:51:37 +08003121
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003122 /* On real hardware multiple invalidations are expensive */
3123 if (cap_caching_mode(iommu->cap))
3124 iommu_flush_iotlb_psi(iommu, domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08003125 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00003126 !deferred_flush[i].freelist[j], 0);
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003127 else {
Jiang Liua156ef92014-07-11 14:19:36 +08003128 mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
Nadav Amit78d5f0f2010-04-08 23:00:41 +03003129 iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
3130 (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
3131 }
Yu Zhao93a23a72009-05-18 13:51:37 +08003132 __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003133 if (deferred_flush[i].freelist[j])
3134 dma_free_pagelist(deferred_flush[i].freelist[j]);
mark gross80b20dd2008-04-18 13:53:58 -07003135 }
Yu Zhao9dd2fe82009-05-18 13:51:36 +08003136 deferred_flush[i].next = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003137 }
3138
mark gross5e0d2a62008-03-04 15:22:08 -08003139 list_size = 0;
mark gross5e0d2a62008-03-04 15:22:08 -08003140}
3141
3142static void flush_unmaps_timeout(unsigned long data)
3143{
mark gross80b20dd2008-04-18 13:53:58 -07003144 unsigned long flags;
3145
3146 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003147 flush_unmaps();
mark gross80b20dd2008-04-18 13:53:58 -07003148 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
mark gross5e0d2a62008-03-04 15:22:08 -08003149}
3150
David Woodhouseea8ea462014-03-05 17:09:32 +00003151static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist)
mark gross5e0d2a62008-03-04 15:22:08 -08003152{
3153 unsigned long flags;
mark gross80b20dd2008-04-18 13:53:58 -07003154 int next, iommu_id;
Weidong Han8c11e792008-12-08 15:29:22 +08003155 struct intel_iommu *iommu;
mark gross5e0d2a62008-03-04 15:22:08 -08003156
3157 spin_lock_irqsave(&async_umap_flush_lock, flags);
mark gross80b20dd2008-04-18 13:53:58 -07003158 if (list_size == HIGH_WATER_MARK)
3159 flush_unmaps();
3160
Weidong Han8c11e792008-12-08 15:29:22 +08003161 iommu = domain_get_iommu(dom);
3162 iommu_id = iommu->seq_id;
Suresh Siddhac42d9f32008-07-10 11:16:36 -07003163
mark gross80b20dd2008-04-18 13:53:58 -07003164 next = deferred_flush[iommu_id].next;
3165 deferred_flush[iommu_id].domain[next] = dom;
3166 deferred_flush[iommu_id].iova[next] = iova;
David Woodhouseea8ea462014-03-05 17:09:32 +00003167 deferred_flush[iommu_id].freelist[next] = freelist;
mark gross80b20dd2008-04-18 13:53:58 -07003168 deferred_flush[iommu_id].next++;
mark gross5e0d2a62008-03-04 15:22:08 -08003169
3170 if (!timer_on) {
3171 mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
3172 timer_on = 1;
3173 }
3174 list_size++;
3175 spin_unlock_irqrestore(&async_umap_flush_lock, flags);
3176}
3177
Jiang Liud41a4ad2014-07-11 14:19:34 +08003178static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003179{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003180 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003181 unsigned long start_pfn, last_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003182 struct iova *iova;
Weidong Han8c11e792008-12-08 15:29:22 +08003183 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003184 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003185
David Woodhouse73676832009-07-04 14:08:36 +01003186 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003187 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003188
David Woodhouse1525a292014-03-06 16:19:30 +00003189 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003190 BUG_ON(!domain);
3191
Weidong Han8c11e792008-12-08 15:29:22 +08003192 iommu = domain_get_iommu(domain);
3193
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003194 iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
David Woodhouse85b98272009-07-01 19:27:53 +01003195 if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
3196 (unsigned long long)dev_addr))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003197 return;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003198
David Woodhoused794dc92009-06-28 00:27:49 +01003199 start_pfn = mm_to_dma_pfn(iova->pfn_lo);
3200 last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003201
David Woodhoused794dc92009-06-28 00:27:49 +01003202 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003203 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003204
David Woodhouseea8ea462014-03-05 17:09:32 +00003205 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003206
mark gross5e0d2a62008-03-04 15:22:08 -08003207 if (intel_iommu_strict) {
David Woodhouse03d6a242009-06-28 15:33:46 +01003208 iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
David Woodhouseea8ea462014-03-05 17:09:32 +00003209 last_pfn - start_pfn + 1, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003210 /* free iova */
3211 __free_iova(&domain->iovad, iova);
David Woodhouseea8ea462014-03-05 17:09:32 +00003212 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003213 } else {
David Woodhouseea8ea462014-03-05 17:09:32 +00003214 add_unmap(domain, iova, freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003215 /*
3216 * queue up the release of the unmap to save the 1/6th of the
3217 * cpu used up by the iotlb flush operation...
3218 */
mark gross5e0d2a62008-03-04 15:22:08 -08003219 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003220}
3221
Jiang Liud41a4ad2014-07-11 14:19:34 +08003222static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3223 size_t size, enum dma_data_direction dir,
3224 struct dma_attrs *attrs)
3225{
3226 intel_unmap(dev, dev_addr);
3227}
3228
David Woodhouse5040a912014-03-09 16:14:00 -07003229static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003230 dma_addr_t *dma_handle, gfp_t flags,
3231 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003232{
Akinobu Mita36746432014-06-04 16:06:51 -07003233 struct page *page = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003234 int order;
3235
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003236 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003237 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003238
David Woodhouse5040a912014-03-09 16:14:00 -07003239 if (!iommu_no_mapping(dev))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003240 flags &= ~(GFP_DMA | GFP_DMA32);
David Woodhouse5040a912014-03-09 16:14:00 -07003241 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3242 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
Alex Williamsone8bb9102009-11-04 15:59:34 -07003243 flags |= GFP_DMA;
3244 else
3245 flags |= GFP_DMA32;
3246 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003247
Akinobu Mita36746432014-06-04 16:06:51 -07003248 if (flags & __GFP_WAIT) {
3249 unsigned int count = size >> PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003250
Akinobu Mita36746432014-06-04 16:06:51 -07003251 page = dma_alloc_from_contiguous(dev, count, order);
3252 if (page && iommu_no_mapping(dev) &&
3253 page_to_phys(page) + size > dev->coherent_dma_mask) {
3254 dma_release_from_contiguous(dev, page, count);
3255 page = NULL;
3256 }
3257 }
3258
3259 if (!page)
3260 page = alloc_pages(flags, order);
3261 if (!page)
3262 return NULL;
3263 memset(page_address(page), 0, size);
3264
3265 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003266 DMA_BIDIRECTIONAL,
David Woodhouse5040a912014-03-09 16:14:00 -07003267 dev->coherent_dma_mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003268 if (*dma_handle)
Akinobu Mita36746432014-06-04 16:06:51 -07003269 return page_address(page);
3270 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3271 __free_pages(page, order);
3272
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003273 return NULL;
3274}
3275
David Woodhouse5040a912014-03-09 16:14:00 -07003276static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003277 dma_addr_t dma_handle, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003278{
3279 int order;
Akinobu Mita36746432014-06-04 16:06:51 -07003280 struct page *page = virt_to_page(vaddr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003281
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003282 size = PAGE_ALIGN(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003283 order = get_order(size);
3284
Jiang Liud41a4ad2014-07-11 14:19:34 +08003285 intel_unmap(dev, dma_handle);
Akinobu Mita36746432014-06-04 16:06:51 -07003286 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3287 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003288}
3289
David Woodhouse5040a912014-03-09 16:14:00 -07003290static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003291 int nelems, enum dma_data_direction dir,
3292 struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003293{
Jiang Liud41a4ad2014-07-11 14:19:34 +08003294 intel_unmap(dev, sglist[0].dma_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003295}
3296
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003297static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003298 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003299{
3300 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003301 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003302
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003303 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003304 BUG_ON(!sg_page(sg));
David Woodhouse4cf2e752009-02-11 17:23:43 +00003305 sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003306 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003307 }
3308 return nelems;
3309}
3310
David Woodhouse5040a912014-03-09 16:14:00 -07003311static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003312 enum dma_data_direction dir, struct dma_attrs *attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003313{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003314 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003315 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003316 size_t size = 0;
3317 int prot = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003318 struct iova *iova = NULL;
3319 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003320 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003321 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003322 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003323
3324 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003325 if (iommu_no_mapping(dev))
3326 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003327
David Woodhouse5040a912014-03-09 16:14:00 -07003328 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003329 if (!domain)
3330 return 0;
3331
Weidong Han8c11e792008-12-08 15:29:22 +08003332 iommu = domain_get_iommu(domain);
3333
David Woodhouseb536d242009-06-28 14:49:31 +01003334 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003335 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003336
David Woodhouse5040a912014-03-09 16:14:00 -07003337 iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
3338 *dev->dma_mask);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003339 if (!iova) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003340 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003341 return 0;
3342 }
3343
3344 /*
3345 * Check if DMAR supports zero-length reads on write only
3346 * mappings..
3347 */
3348 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003349 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003350 prot |= DMA_PTE_READ;
3351 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3352 prot |= DMA_PTE_WRITE;
3353
David Woodhouseb536d242009-06-28 14:49:31 +01003354 start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
David Woodhousee1605492009-06-29 11:17:38 +01003355
Fenghua Yuf5329592009-08-04 15:09:37 -07003356 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003357 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003358 dma_pte_free_pagetable(domain, start_vpfn,
3359 start_vpfn + size - 1);
David Woodhousee1605492009-06-29 11:17:38 +01003360 __free_iova(&domain->iovad, iova);
3361 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003362 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003363
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003364 /* it's a non-present to present mapping. Only flush if caching mode */
3365 if (cap_caching_mode(iommu->cap))
David Woodhouseea8ea462014-03-05 17:09:32 +00003366 iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 0, 1);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003367 else
Weidong Han8c11e792008-12-08 15:29:22 +08003368 iommu_flush_write_buffer(iommu);
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003369
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003370 return nelems;
3371}
3372
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003373static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
3374{
3375 return !dma_addr;
3376}
3377
FUJITA Tomonori160c1d82009-01-05 23:59:02 +09003378struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003379 .alloc = intel_alloc_coherent,
3380 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003381 .map_sg = intel_map_sg,
3382 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003383 .map_page = intel_map_page,
3384 .unmap_page = intel_unmap_page,
FUJITA Tomonoridfb805e2009-01-28 21:53:17 +09003385 .mapping_error = intel_mapping_error,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003386};
3387
3388static inline int iommu_domain_cache_init(void)
3389{
3390 int ret = 0;
3391
3392 iommu_domain_cache = kmem_cache_create("iommu_domain",
3393 sizeof(struct dmar_domain),
3394 0,
3395 SLAB_HWCACHE_ALIGN,
3396
3397 NULL);
3398 if (!iommu_domain_cache) {
3399 printk(KERN_ERR "Couldn't create iommu_domain cache\n");
3400 ret = -ENOMEM;
3401 }
3402
3403 return ret;
3404}
3405
3406static inline int iommu_devinfo_cache_init(void)
3407{
3408 int ret = 0;
3409
3410 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3411 sizeof(struct device_domain_info),
3412 0,
3413 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003414 NULL);
3415 if (!iommu_devinfo_cache) {
3416 printk(KERN_ERR "Couldn't create devinfo cache\n");
3417 ret = -ENOMEM;
3418 }
3419
3420 return ret;
3421}
3422
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003423static int __init iommu_init_mempool(void)
3424{
3425 int ret;
3426 ret = iommu_iova_cache_init();
3427 if (ret)
3428 return ret;
3429
3430 ret = iommu_domain_cache_init();
3431 if (ret)
3432 goto domain_error;
3433
3434 ret = iommu_devinfo_cache_init();
3435 if (!ret)
3436 return ret;
3437
3438 kmem_cache_destroy(iommu_domain_cache);
3439domain_error:
Robin Murphy85b45452015-01-12 17:51:14 +00003440 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003441
3442 return -ENOMEM;
3443}
3444
3445static void __init iommu_exit_mempool(void)
3446{
3447 kmem_cache_destroy(iommu_devinfo_cache);
3448 kmem_cache_destroy(iommu_domain_cache);
Robin Murphy85b45452015-01-12 17:51:14 +00003449 iommu_iova_cache_destroy();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003450}
3451
Dan Williams556ab452010-07-23 15:47:56 -07003452static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3453{
3454 struct dmar_drhd_unit *drhd;
3455 u32 vtbar;
3456 int rc;
3457
3458 /* We know that this device on this chipset has its own IOMMU.
3459 * If we find it under a different IOMMU, then the BIOS is lying
3460 * to us. Hope that the IOMMU for this device is actually
3461 * disabled, and it needs no translation...
3462 */
3463 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
3464 if (rc) {
3465 /* "can't" happen */
3466 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
3467 return;
3468 }
3469 vtbar &= 0xffff0000;
3470
3471 /* we know that the this iommu should be at offset 0xa000 from vtbar */
3472 drhd = dmar_find_matched_drhd_unit(pdev);
3473 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
3474 TAINT_FIRMWARE_WORKAROUND,
3475 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
3476 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
3477}
3478DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3479
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003480static void __init init_no_remapping_devices(void)
3481{
3482 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00003483 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08003484 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003485
3486 for_each_drhd_unit(drhd) {
3487 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08003488 for_each_active_dev_scope(drhd->devices,
3489 drhd->devices_cnt, i, dev)
3490 break;
David Woodhouse832bd852014-03-07 15:08:36 +00003491 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003492 if (i == drhd->devices_cnt)
3493 drhd->ignored = 1;
3494 }
3495 }
3496
Jiang Liu7c919772014-01-06 14:18:18 +08003497 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08003498 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003499 continue;
3500
Jiang Liub683b232014-02-19 14:07:32 +08003501 for_each_active_dev_scope(drhd->devices,
3502 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003503 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003504 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003505 if (i < drhd->devices_cnt)
3506 continue;
3507
David Woodhousec0771df2011-10-14 20:59:46 +01003508 /* This IOMMU has *only* gfx devices. Either bypass it or
3509 set the gfx_mapped flag, as appropriate */
3510 if (dmar_map_gfx) {
3511 intel_iommu_gfx_mapped = 1;
3512 } else {
3513 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08003514 for_each_active_dev_scope(drhd->devices,
3515 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00003516 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003517 }
3518 }
3519}
3520
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003521#ifdef CONFIG_SUSPEND
3522static int init_iommu_hw(void)
3523{
3524 struct dmar_drhd_unit *drhd;
3525 struct intel_iommu *iommu = NULL;
3526
3527 for_each_active_iommu(iommu, drhd)
3528 if (iommu->qi)
3529 dmar_reenable_qi(iommu);
3530
Joseph Cihulab7792602011-05-03 00:08:37 -07003531 for_each_iommu(iommu, drhd) {
3532 if (drhd->ignored) {
3533 /*
3534 * we always have to disable PMRs or DMA may fail on
3535 * this device
3536 */
3537 if (force_on)
3538 iommu_disable_protect_mem_regions(iommu);
3539 continue;
3540 }
3541
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003542 iommu_flush_write_buffer(iommu);
3543
3544 iommu_set_root_entry(iommu);
3545
3546 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003547 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08003548 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3549 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07003550 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003551 }
3552
3553 return 0;
3554}
3555
3556static void iommu_flush_all(void)
3557{
3558 struct dmar_drhd_unit *drhd;
3559 struct intel_iommu *iommu;
3560
3561 for_each_active_iommu(iommu, drhd) {
3562 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003563 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003564 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01003565 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003566 }
3567}
3568
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003569static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003570{
3571 struct dmar_drhd_unit *drhd;
3572 struct intel_iommu *iommu = NULL;
3573 unsigned long flag;
3574
3575 for_each_active_iommu(iommu, drhd) {
3576 iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
3577 GFP_ATOMIC);
3578 if (!iommu->iommu_state)
3579 goto nomem;
3580 }
3581
3582 iommu_flush_all();
3583
3584 for_each_active_iommu(iommu, drhd) {
3585 iommu_disable_translation(iommu);
3586
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003587 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003588
3589 iommu->iommu_state[SR_DMAR_FECTL_REG] =
3590 readl(iommu->reg + DMAR_FECTL_REG);
3591 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
3592 readl(iommu->reg + DMAR_FEDATA_REG);
3593 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
3594 readl(iommu->reg + DMAR_FEADDR_REG);
3595 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
3596 readl(iommu->reg + DMAR_FEUADDR_REG);
3597
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003598 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003599 }
3600 return 0;
3601
3602nomem:
3603 for_each_active_iommu(iommu, drhd)
3604 kfree(iommu->iommu_state);
3605
3606 return -ENOMEM;
3607}
3608
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003609static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003610{
3611 struct dmar_drhd_unit *drhd;
3612 struct intel_iommu *iommu = NULL;
3613 unsigned long flag;
3614
3615 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07003616 if (force_on)
3617 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
3618 else
3619 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003620 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003621 }
3622
3623 for_each_active_iommu(iommu, drhd) {
3624
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003625 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003626
3627 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
3628 iommu->reg + DMAR_FECTL_REG);
3629 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
3630 iommu->reg + DMAR_FEDATA_REG);
3631 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
3632 iommu->reg + DMAR_FEADDR_REG);
3633 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
3634 iommu->reg + DMAR_FEUADDR_REG);
3635
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02003636 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003637 }
3638
3639 for_each_active_iommu(iommu, drhd)
3640 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003641}
3642
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003643static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003644 .resume = iommu_resume,
3645 .suspend = iommu_suspend,
3646};
3647
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003648static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003649{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01003650 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003651}
3652
3653#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02003654static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07003655#endif /* CONFIG_PM */
3656
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003657
Jiang Liuc2a0b532014-11-09 22:47:56 +08003658int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003659{
3660 struct acpi_dmar_reserved_memory *rmrr;
3661 struct dmar_rmrr_unit *rmrru;
3662
3663 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
3664 if (!rmrru)
3665 return -ENOMEM;
3666
3667 rmrru->hdr = header;
3668 rmrr = (struct acpi_dmar_reserved_memory *)header;
3669 rmrru->base_address = rmrr->base_address;
3670 rmrru->end_address = rmrr->end_address;
Jiang Liu2e455282014-02-19 14:07:36 +08003671 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
3672 ((void *)rmrr) + rmrr->header.length,
3673 &rmrru->devices_cnt);
3674 if (rmrru->devices_cnt && rmrru->devices == NULL) {
3675 kfree(rmrru);
3676 return -ENOMEM;
3677 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003678
Jiang Liu2e455282014-02-19 14:07:36 +08003679 list_add(&rmrru->list, &dmar_rmrr_units);
3680
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003681 return 0;
3682}
3683
Jiang Liu6b197242014-11-09 22:47:58 +08003684static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
3685{
3686 struct dmar_atsr_unit *atsru;
3687 struct acpi_dmar_atsr *tmp;
3688
3689 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3690 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
3691 if (atsr->segment != tmp->segment)
3692 continue;
3693 if (atsr->header.length != tmp->header.length)
3694 continue;
3695 if (memcmp(atsr, tmp, atsr->header.length) == 0)
3696 return atsru;
3697 }
3698
3699 return NULL;
3700}
3701
3702int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003703{
3704 struct acpi_dmar_atsr *atsr;
3705 struct dmar_atsr_unit *atsru;
3706
Jiang Liu6b197242014-11-09 22:47:58 +08003707 if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
3708 return 0;
3709
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003710 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08003711 atsru = dmar_find_atsr(atsr);
3712 if (atsru)
3713 return 0;
3714
3715 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003716 if (!atsru)
3717 return -ENOMEM;
3718
Jiang Liu6b197242014-11-09 22:47:58 +08003719 /*
3720 * If memory is allocated from slab by ACPI _DSM method, we need to
3721 * copy the memory content because the memory buffer will be freed
3722 * on return.
3723 */
3724 atsru->hdr = (void *)(atsru + 1);
3725 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003726 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08003727 if (!atsru->include_all) {
3728 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
3729 (void *)atsr + atsr->header.length,
3730 &atsru->devices_cnt);
3731 if (atsru->devices_cnt && atsru->devices == NULL) {
3732 kfree(atsru);
3733 return -ENOMEM;
3734 }
3735 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003736
Jiang Liu0e242612014-02-19 14:07:34 +08003737 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003738
3739 return 0;
3740}
3741
Jiang Liu9bdc5312014-01-06 14:18:27 +08003742static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3743{
3744 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
3745 kfree(atsru);
3746}
3747
Jiang Liu6b197242014-11-09 22:47:58 +08003748int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3749{
3750 struct acpi_dmar_atsr *atsr;
3751 struct dmar_atsr_unit *atsru;
3752
3753 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3754 atsru = dmar_find_atsr(atsr);
3755 if (atsru) {
3756 list_del_rcu(&atsru->list);
3757 synchronize_rcu();
3758 intel_iommu_free_atsr(atsru);
3759 }
3760
3761 return 0;
3762}
3763
3764int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3765{
3766 int i;
3767 struct device *dev;
3768 struct acpi_dmar_atsr *atsr;
3769 struct dmar_atsr_unit *atsru;
3770
3771 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3772 atsru = dmar_find_atsr(atsr);
3773 if (!atsru)
3774 return 0;
3775
3776 if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
3777 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
3778 i, dev)
3779 return -EBUSY;
3780
3781 return 0;
3782}
3783
Jiang Liuffebeb42014-11-09 22:48:02 +08003784static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
3785{
3786 int sp, ret = 0;
3787 struct intel_iommu *iommu = dmaru->iommu;
3788
3789 if (g_iommus[iommu->seq_id])
3790 return 0;
3791
3792 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
3793 pr_warn("IOMMU: %s doesn't support hardware pass through.\n",
3794 iommu->name);
3795 return -ENXIO;
3796 }
3797 if (!ecap_sc_support(iommu->ecap) &&
3798 domain_update_iommu_snooping(iommu)) {
3799 pr_warn("IOMMU: %s doesn't support snooping.\n",
3800 iommu->name);
3801 return -ENXIO;
3802 }
3803 sp = domain_update_iommu_superpage(iommu) - 1;
3804 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
3805 pr_warn("IOMMU: %s doesn't support large page.\n",
3806 iommu->name);
3807 return -ENXIO;
3808 }
3809
3810 /*
3811 * Disable translation if already enabled prior to OS handover.
3812 */
3813 if (iommu->gcmd & DMA_GCMD_TE)
3814 iommu_disable_translation(iommu);
3815
3816 g_iommus[iommu->seq_id] = iommu;
3817 ret = iommu_init_domains(iommu);
3818 if (ret == 0)
3819 ret = iommu_alloc_root_entry(iommu);
3820 if (ret)
3821 goto out;
3822
3823 if (dmaru->ignored) {
3824 /*
3825 * we always have to disable PMRs or DMA may fail on this device
3826 */
3827 if (force_on)
3828 iommu_disable_protect_mem_regions(iommu);
3829 return 0;
3830 }
3831
3832 intel_iommu_init_qi(iommu);
3833 iommu_flush_write_buffer(iommu);
3834 ret = dmar_set_interrupt(iommu);
3835 if (ret)
3836 goto disable_iommu;
3837
3838 iommu_set_root_entry(iommu);
3839 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3840 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3841 iommu_enable_translation(iommu);
3842
3843 if (si_domain) {
3844 ret = iommu_attach_domain(si_domain, iommu);
3845 if (ret < 0 || si_domain->id != ret)
3846 goto disable_iommu;
3847 domain_attach_iommu(si_domain, iommu);
3848 }
3849
3850 iommu_disable_protect_mem_regions(iommu);
3851 return 0;
3852
3853disable_iommu:
3854 disable_dmar_iommu(iommu);
3855out:
3856 free_dmar_iommu(iommu);
3857 return ret;
3858}
3859
Jiang Liu6b197242014-11-09 22:47:58 +08003860int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
3861{
Jiang Liuffebeb42014-11-09 22:48:02 +08003862 int ret = 0;
3863 struct intel_iommu *iommu = dmaru->iommu;
3864
3865 if (!intel_iommu_enabled)
3866 return 0;
3867 if (iommu == NULL)
3868 return -EINVAL;
3869
3870 if (insert) {
3871 ret = intel_iommu_add(dmaru);
3872 } else {
3873 disable_dmar_iommu(iommu);
3874 free_dmar_iommu(iommu);
3875 }
3876
3877 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08003878}
3879
Jiang Liu9bdc5312014-01-06 14:18:27 +08003880static void intel_iommu_free_dmars(void)
3881{
3882 struct dmar_rmrr_unit *rmrru, *rmrr_n;
3883 struct dmar_atsr_unit *atsru, *atsr_n;
3884
3885 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
3886 list_del(&rmrru->list);
3887 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
3888 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003889 }
3890
Jiang Liu9bdc5312014-01-06 14:18:27 +08003891 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
3892 list_del(&atsru->list);
3893 intel_iommu_free_atsr(atsru);
3894 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003895}
3896
3897int dmar_find_matched_atsr_unit(struct pci_dev *dev)
3898{
Jiang Liub683b232014-02-19 14:07:32 +08003899 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003900 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00003901 struct pci_dev *bridge = NULL;
3902 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003903 struct acpi_dmar_atsr *atsr;
3904 struct dmar_atsr_unit *atsru;
3905
3906 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003907 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08003908 bridge = bus->self;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003909 if (!bridge || !pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08003910 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003911 return 0;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003912 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003913 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003914 }
Jiang Liub5f82dd2014-02-19 14:07:31 +08003915 if (!bridge)
3916 return 0;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003917
Jiang Liu0e242612014-02-19 14:07:34 +08003918 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08003919 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3920 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3921 if (atsr->segment != pci_domain_nr(dev->bus))
3922 continue;
3923
Jiang Liub683b232014-02-19 14:07:32 +08003924 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00003925 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08003926 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003927
3928 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08003929 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08003930 }
Jiang Liub683b232014-02-19 14:07:32 +08003931 ret = 0;
3932out:
Jiang Liu0e242612014-02-19 14:07:34 +08003933 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003934
Jiang Liub683b232014-02-19 14:07:32 +08003935 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07003936}
3937
Jiang Liu59ce0512014-02-19 14:07:35 +08003938int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3939{
3940 int ret = 0;
3941 struct dmar_rmrr_unit *rmrru;
3942 struct dmar_atsr_unit *atsru;
3943 struct acpi_dmar_atsr *atsr;
3944 struct acpi_dmar_reserved_memory *rmrr;
3945
3946 if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
3947 return 0;
3948
3949 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
3950 rmrr = container_of(rmrru->hdr,
3951 struct acpi_dmar_reserved_memory, header);
3952 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3953 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
3954 ((void *)rmrr) + rmrr->header.length,
3955 rmrr->segment, rmrru->devices,
3956 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08003957 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08003958 return ret;
3959 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08003960 dmar_remove_dev_scope(info, rmrr->segment,
3961 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08003962 }
3963 }
3964
3965 list_for_each_entry(atsru, &dmar_atsr_units, list) {
3966 if (atsru->include_all)
3967 continue;
3968
3969 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3970 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
3971 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
3972 (void *)atsr + atsr->header.length,
3973 atsr->segment, atsru->devices,
3974 atsru->devices_cnt);
3975 if (ret > 0)
3976 break;
3977 else if(ret < 0)
3978 return ret;
3979 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
3980 if (dmar_remove_dev_scope(info, atsr->segment,
3981 atsru->devices, atsru->devices_cnt))
3982 break;
3983 }
3984 }
3985
3986 return 0;
3987}
3988
Fenghua Yu99dcade2009-11-11 07:23:06 -08003989/*
3990 * Here we only respond to action of unbound device from driver.
3991 *
3992 * Added device is not attached to its DMAR domain here yet. That will happen
3993 * when mapping the device to iova.
3994 */
3995static int device_notifier(struct notifier_block *nb,
3996 unsigned long action, void *data)
3997{
3998 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08003999 struct dmar_domain *domain;
4000
David Woodhouse3d891942014-03-06 15:59:26 +00004001 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004002 return 0;
4003
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004004 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004005 return 0;
4006
David Woodhouse1525a292014-03-06 16:19:30 +00004007 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004008 if (!domain)
4009 return 0;
4010
Jiang Liu3a5670e2014-02-19 14:07:33 +08004011 down_read(&dmar_global_lock);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004012 domain_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004013 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004014 domain_exit(domain);
Jiang Liu3a5670e2014-02-19 14:07:33 +08004015 up_read(&dmar_global_lock);
Alex Williamsona97590e2011-03-04 14:52:16 -07004016
Fenghua Yu99dcade2009-11-11 07:23:06 -08004017 return 0;
4018}
4019
4020static struct notifier_block device_nb = {
4021 .notifier_call = device_notifier,
4022};
4023
Jiang Liu75f05562014-02-19 14:07:37 +08004024static int intel_iommu_memory_notifier(struct notifier_block *nb,
4025 unsigned long val, void *v)
4026{
4027 struct memory_notify *mhp = v;
4028 unsigned long long start, end;
4029 unsigned long start_vpfn, last_vpfn;
4030
4031 switch (val) {
4032 case MEM_GOING_ONLINE:
4033 start = mhp->start_pfn << PAGE_SHIFT;
4034 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4035 if (iommu_domain_identity_map(si_domain, start, end)) {
4036 pr_warn("dmar: failed to build identity map for [%llx-%llx]\n",
4037 start, end);
4038 return NOTIFY_BAD;
4039 }
4040 break;
4041
4042 case MEM_OFFLINE:
4043 case MEM_CANCEL_ONLINE:
4044 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4045 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4046 while (start_vpfn <= last_vpfn) {
4047 struct iova *iova;
4048 struct dmar_drhd_unit *drhd;
4049 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004050 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004051
4052 iova = find_iova(&si_domain->iovad, start_vpfn);
4053 if (iova == NULL) {
4054 pr_debug("dmar: failed get IOVA for PFN %lx\n",
4055 start_vpfn);
4056 break;
4057 }
4058
4059 iova = split_and_remove_iova(&si_domain->iovad, iova,
4060 start_vpfn, last_vpfn);
4061 if (iova == NULL) {
4062 pr_warn("dmar: failed to split IOVA PFN [%lx-%lx]\n",
4063 start_vpfn, last_vpfn);
4064 return NOTIFY_BAD;
4065 }
4066
David Woodhouseea8ea462014-03-05 17:09:32 +00004067 freelist = domain_unmap(si_domain, iova->pfn_lo,
4068 iova->pfn_hi);
4069
Jiang Liu75f05562014-02-19 14:07:37 +08004070 rcu_read_lock();
4071 for_each_active_iommu(iommu, drhd)
4072 iommu_flush_iotlb_psi(iommu, si_domain->id,
Jiang Liua156ef92014-07-11 14:19:36 +08004073 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004074 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004075 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004076 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004077
4078 start_vpfn = iova->pfn_hi + 1;
4079 free_iova_mem(iova);
4080 }
4081 break;
4082 }
4083
4084 return NOTIFY_OK;
4085}
4086
4087static struct notifier_block intel_iommu_memory_nb = {
4088 .notifier_call = intel_iommu_memory_notifier,
4089 .priority = 0
4090};
4091
Alex Williamsona5459cf2014-06-12 16:12:31 -06004092
4093static ssize_t intel_iommu_show_version(struct device *dev,
4094 struct device_attribute *attr,
4095 char *buf)
4096{
4097 struct intel_iommu *iommu = dev_get_drvdata(dev);
4098 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4099 return sprintf(buf, "%d:%d\n",
4100 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4101}
4102static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4103
4104static ssize_t intel_iommu_show_address(struct device *dev,
4105 struct device_attribute *attr,
4106 char *buf)
4107{
4108 struct intel_iommu *iommu = dev_get_drvdata(dev);
4109 return sprintf(buf, "%llx\n", iommu->reg_phys);
4110}
4111static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4112
4113static ssize_t intel_iommu_show_cap(struct device *dev,
4114 struct device_attribute *attr,
4115 char *buf)
4116{
4117 struct intel_iommu *iommu = dev_get_drvdata(dev);
4118 return sprintf(buf, "%llx\n", iommu->cap);
4119}
4120static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4121
4122static ssize_t intel_iommu_show_ecap(struct device *dev,
4123 struct device_attribute *attr,
4124 char *buf)
4125{
4126 struct intel_iommu *iommu = dev_get_drvdata(dev);
4127 return sprintf(buf, "%llx\n", iommu->ecap);
4128}
4129static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4130
4131static struct attribute *intel_iommu_attrs[] = {
4132 &dev_attr_version.attr,
4133 &dev_attr_address.attr,
4134 &dev_attr_cap.attr,
4135 &dev_attr_ecap.attr,
4136 NULL,
4137};
4138
4139static struct attribute_group intel_iommu_group = {
4140 .name = "intel-iommu",
4141 .attrs = intel_iommu_attrs,
4142};
4143
4144const struct attribute_group *intel_iommu_groups[] = {
4145 &intel_iommu_group,
4146 NULL,
4147};
4148
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004149int __init intel_iommu_init(void)
4150{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004151 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004152 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004153 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004154
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004155 /* VT-d is required for a TXT/tboot launch, so enforce that */
4156 force_on = tboot_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004157
Jiang Liu3a5670e2014-02-19 14:07:33 +08004158 if (iommu_init_mempool()) {
4159 if (force_on)
4160 panic("tboot: Failed to initialize iommu memory\n");
4161 return -ENOMEM;
4162 }
4163
4164 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004165 if (dmar_table_init()) {
4166 if (force_on)
4167 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004168 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004169 }
4170
Takao Indoh3a93c842013-04-23 17:35:03 +09004171 /*
4172 * Disable translation if already enabled prior to OS handover.
4173 */
Jiang Liu7c919772014-01-06 14:18:18 +08004174 for_each_active_iommu(iommu, drhd)
Takao Indoh3a93c842013-04-23 17:35:03 +09004175 if (iommu->gcmd & DMA_GCMD_TE)
4176 iommu_disable_translation(iommu);
Takao Indoh3a93c842013-04-23 17:35:03 +09004177
Suresh Siddhac2c72862011-08-23 17:05:19 -07004178 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004179 if (force_on)
4180 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004181 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004182 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004183
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004184 if (no_iommu || dmar_disabled)
Jiang Liu9bdc5312014-01-06 14:18:27 +08004185 goto out_free_dmar;
Suresh Siddha2ae21012008-07-10 11:16:43 -07004186
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004187 if (list_empty(&dmar_rmrr_units))
4188 printk(KERN_INFO "DMAR: No RMRR found\n");
4189
4190 if (list_empty(&dmar_atsr_units))
4191 printk(KERN_INFO "DMAR: No ATSR found\n");
4192
Joseph Cihula51a63e62011-03-21 11:04:24 -07004193 if (dmar_init_reserved_ranges()) {
4194 if (force_on)
4195 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004196 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004197 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004198
4199 init_no_remapping_devices();
4200
Joseph Cihulab7792602011-05-03 00:08:37 -07004201 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004202 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004203 if (force_on)
4204 panic("tboot: Failed to initialize DMARs\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004205 printk(KERN_ERR "IOMMU: dmar init failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004206 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004207 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004208 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004209 printk(KERN_INFO
4210 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
4211
mark gross5e0d2a62008-03-04 15:22:08 -08004212 init_timer(&unmap_timer);
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004213#ifdef CONFIG_SWIOTLB
4214 swiotlb = 0;
4215#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004216 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004217
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004218 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004219
Alex Williamsona5459cf2014-06-12 16:12:31 -06004220 for_each_active_iommu(iommu, drhd)
4221 iommu->iommu_dev = iommu_device_create(NULL, iommu,
4222 intel_iommu_groups,
4223 iommu->name);
4224
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004225 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004226 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004227 if (si_domain && !hw_pass_through)
4228 register_memory_notifier(&intel_iommu_memory_nb);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004229
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004230 intel_iommu_enabled = 1;
4231
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004232 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004233
4234out_free_reserved_range:
4235 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004236out_free_dmar:
4237 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004238 up_write(&dmar_global_lock);
4239 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004240 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004241}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004242
Alex Williamson579305f2014-07-03 09:51:43 -06004243static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
4244{
4245 struct intel_iommu *iommu = opaque;
4246
4247 iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4248 return 0;
4249}
4250
4251/*
4252 * NB - intel-iommu lacks any sort of reference counting for the users of
4253 * dependent devices. If multiple endpoints have intersecting dependent
4254 * devices, unbinding the driver from any one of them will possibly leave
4255 * the others unable to operate.
4256 */
Han, Weidong3199aa62009-02-26 17:31:12 +08004257static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004258 struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004259{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004260 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004261 return;
4262
Alex Williamson579305f2014-07-03 09:51:43 -06004263 pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004264}
4265
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004266static void domain_remove_one_dev_info(struct dmar_domain *domain,
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004267 struct device *dev)
Weidong Hanc7151a82008-12-08 22:51:37 +08004268{
Yijing Wangbca2b912013-10-31 17:26:04 +08004269 struct device_domain_info *info, *tmp;
Weidong Hanc7151a82008-12-08 22:51:37 +08004270 struct intel_iommu *iommu;
4271 unsigned long flags;
Quentin Lambert2f119c72015-02-06 10:59:53 +01004272 bool found = false;
David Woodhouse156baca2014-03-09 14:00:57 -07004273 u8 bus, devfn;
Weidong Hanc7151a82008-12-08 22:51:37 +08004274
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004275 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanc7151a82008-12-08 22:51:37 +08004276 if (!iommu)
4277 return;
4278
4279 spin_lock_irqsave(&device_domain_lock, flags);
Yijing Wangbca2b912013-10-31 17:26:04 +08004280 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004281 if (info->iommu == iommu && info->bus == bus &&
4282 info->devfn == devfn) {
David Woodhouse109b9b02012-05-25 17:43:02 +01004283 unlink_domain_info(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004284 spin_unlock_irqrestore(&device_domain_lock, flags);
4285
Yu Zhao93a23a72009-05-18 13:51:37 +08004286 iommu_disable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004287 iommu_detach_dev(iommu, info->bus, info->devfn);
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004288 iommu_detach_dependent_devices(iommu, dev);
Weidong Hanc7151a82008-12-08 22:51:37 +08004289 free_devinfo_mem(info);
4290
4291 spin_lock_irqsave(&device_domain_lock, flags);
4292
4293 if (found)
4294 break;
4295 else
4296 continue;
4297 }
4298
4299 /* if there is no other devices under the same iommu
4300 * owned by this domain, clear this iommu in iommu_bmp
4301 * update iommu count and coherency
4302 */
David Woodhouse8bbc4412014-03-09 13:52:37 -07004303 if (info->iommu == iommu)
Quentin Lambert2f119c72015-02-06 10:59:53 +01004304 found = true;
Weidong Hanc7151a82008-12-08 22:51:37 +08004305 }
4306
Roland Dreier3e7abe22011-07-20 06:22:21 -07004307 spin_unlock_irqrestore(&device_domain_lock, flags);
4308
Weidong Hanc7151a82008-12-08 22:51:37 +08004309 if (found == 0) {
Jiang Liufb170fb2014-07-11 14:19:28 +08004310 domain_detach_iommu(domain, iommu);
4311 if (!domain_type_is_vm_or_si(domain))
4312 iommu_detach_domain(domain, iommu);
Weidong Hanc7151a82008-12-08 22:51:37 +08004313 }
Weidong Hanc7151a82008-12-08 22:51:37 +08004314}
4315
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004316static int md_domain_init(struct dmar_domain *domain, int guest_width)
Weidong Han5e98c4b2008-12-08 23:03:27 +08004317{
4318 int adjust_width;
4319
Robin Murphy0fb5fe82015-01-12 17:51:16 +00004320 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
4321 DMA_32BIT_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004322 domain_reserve_special_ranges(domain);
4323
4324 /* calculate AGAW */
4325 domain->gaw = guest_width;
4326 adjust_width = guestwidth_to_adjustwidth(guest_width);
4327 domain->agaw = width_to_agaw(adjust_width);
4328
Weidong Han5e98c4b2008-12-08 23:03:27 +08004329 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08004330 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01004331 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004332 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08004333
4334 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07004335 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004336 if (!domain->pgd)
4337 return -ENOMEM;
4338 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
4339 return 0;
4340}
4341
Joerg Roedel00a77de2015-03-26 13:43:08 +01004342static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03004343{
Joerg Roedel5d450802008-12-03 14:52:32 +01004344 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01004345 struct iommu_domain *domain;
4346
4347 if (type != IOMMU_DOMAIN_UNMANAGED)
4348 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004349
Jiang Liuab8dfe22014-07-11 14:19:27 +08004350 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01004351 if (!dmar_domain) {
Kay, Allen M38717942008-09-09 18:37:29 +03004352 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004353 "intel_iommu_domain_init: dmar_domain == NULL\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01004354 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004355 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07004356 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Kay, Allen M38717942008-09-09 18:37:29 +03004357 printk(KERN_ERR
Joerg Roedel5d450802008-12-03 14:52:32 +01004358 "intel_iommu_domain_init() failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08004359 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01004360 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03004361 }
Allen Kay8140a952011-10-14 12:32:17 -07004362 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004363
Joerg Roedel00a77de2015-03-26 13:43:08 +01004364 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01004365 domain->geometry.aperture_start = 0;
4366 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
4367 domain->geometry.force_aperture = true;
4368
Joerg Roedel00a77de2015-03-26 13:43:08 +01004369 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03004370}
Kay, Allen M38717942008-09-09 18:37:29 +03004371
Joerg Roedel00a77de2015-03-26 13:43:08 +01004372static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03004373{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004374 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03004375}
Kay, Allen M38717942008-09-09 18:37:29 +03004376
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004377static int intel_iommu_attach_device(struct iommu_domain *domain,
4378 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004379{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004380 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004381 struct intel_iommu *iommu;
4382 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07004383 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03004384
Alex Williamsonc875d2c2014-07-03 09:57:02 -06004385 if (device_is_rmrr_locked(dev)) {
4386 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
4387 return -EPERM;
4388 }
4389
David Woodhouse7207d8f2014-03-09 16:31:06 -07004390 /* normally dev is not mapped */
4391 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004392 struct dmar_domain *old_domain;
4393
David Woodhouse1525a292014-03-06 16:19:30 +00004394 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004395 if (old_domain) {
Jiang Liuab8dfe22014-07-11 14:19:27 +08004396 if (domain_type_is_vm_or_si(dmar_domain))
David Woodhousebf9c9ed2014-03-09 16:19:13 -07004397 domain_remove_one_dev_info(old_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004398 else
4399 domain_remove_dev_info(old_domain);
Joerg Roedel62c22162014-12-09 12:56:45 +01004400
4401 if (!domain_type_is_vm_or_si(old_domain) &&
4402 list_empty(&old_domain->devices))
4403 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004404 }
4405 }
4406
David Woodhouse156baca2014-03-09 14:00:57 -07004407 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004408 if (!iommu)
4409 return -ENODEV;
4410
4411 /* check if this iommu agaw is sufficient for max mapped address */
4412 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01004413 if (addr_width > cap_mgaw(iommu->cap))
4414 addr_width = cap_mgaw(iommu->cap);
4415
4416 if (dmar_domain->max_addr > (1LL << addr_width)) {
4417 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004418 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01004419 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004420 return -EFAULT;
4421 }
Tom Lyona99c47a2010-05-17 08:20:45 +01004422 dmar_domain->gaw = addr_width;
4423
4424 /*
4425 * Knock out extra levels of page tables if necessary
4426 */
4427 while (iommu->agaw < dmar_domain->agaw) {
4428 struct dma_pte *pte;
4429
4430 pte = dmar_domain->pgd;
4431 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08004432 dmar_domain->pgd = (struct dma_pte *)
4433 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01004434 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01004435 }
4436 dmar_domain->agaw--;
4437 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004438
David Woodhouse5913c9b2014-03-09 16:27:31 -07004439 return domain_add_dev_info(dmar_domain, dev, CONTEXT_TT_MULTI_LEVEL);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004440}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004441
Joerg Roedel4c5478c2008-12-03 14:58:24 +01004442static void intel_iommu_detach_device(struct iommu_domain *domain,
4443 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03004444{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004445 domain_remove_one_dev_info(to_dmar_domain(domain), dev);
Kay, Allen M38717942008-09-09 18:37:29 +03004446}
Kay, Allen M38717942008-09-09 18:37:29 +03004447
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004448static int intel_iommu_map(struct iommu_domain *domain,
4449 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004450 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03004451{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004452 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004453 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004454 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004455 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004456
Joerg Roedeldde57a22008-12-03 15:04:09 +01004457 if (iommu_prot & IOMMU_READ)
4458 prot |= DMA_PTE_READ;
4459 if (iommu_prot & IOMMU_WRITE)
4460 prot |= DMA_PTE_WRITE;
Sheng Yang9cf066972009-03-18 15:33:07 +08004461 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
4462 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004463
David Woodhouse163cc522009-06-28 00:51:17 +01004464 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01004465 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004466 u64 end;
4467
4468 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01004469 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004470 if (end < max_addr) {
Tom Lyon8954da12010-05-17 08:19:52 +01004471 printk(KERN_ERR "%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004472 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01004473 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004474 return -EFAULT;
4475 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01004476 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004477 }
David Woodhousead051222009-06-28 14:22:28 +01004478 /* Round up size to next multiple of PAGE_SIZE, if it and
4479 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01004480 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01004481 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
4482 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004483 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03004484}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004485
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02004486static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00004487 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004488{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004489 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00004490 struct page *freelist = NULL;
4491 struct intel_iommu *iommu;
4492 unsigned long start_pfn, last_pfn;
4493 unsigned int npages;
4494 int iommu_id, num, ndomains, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01004495
David Woodhouse5cf0a762014-03-19 16:07:49 +00004496 /* Cope with horrid API which requires us to unmap more than the
4497 size argument if it happens to be a large-page mapping. */
4498 if (!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level))
4499 BUG();
4500
4501 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
4502 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
4503
David Woodhouseea8ea462014-03-05 17:09:32 +00004504 start_pfn = iova >> VTD_PAGE_SHIFT;
4505 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
4506
4507 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
4508
4509 npages = last_pfn - start_pfn + 1;
4510
4511 for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) {
4512 iommu = g_iommus[iommu_id];
4513
4514 /*
4515 * find bit position of dmar_domain
4516 */
4517 ndomains = cap_ndoms(iommu->cap);
4518 for_each_set_bit(num, iommu->domain_ids, ndomains) {
4519 if (iommu->domains[num] == dmar_domain)
4520 iommu_flush_iotlb_psi(iommu, num, start_pfn,
4521 npages, !freelist, 0);
4522 }
4523
4524 }
4525
4526 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08004527
David Woodhouse163cc522009-06-28 00:51:17 +01004528 if (dmar_domain->max_addr == iova + size)
4529 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004530
David Woodhouse5cf0a762014-03-19 16:07:49 +00004531 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004532}
Kay, Allen M38717942008-09-09 18:37:29 +03004533
Joerg Roedeld14d6572008-12-03 15:06:57 +01004534static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547ac2013-03-29 01:23:58 +05304535 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03004536{
Joerg Roedel00a77de2015-03-26 13:43:08 +01004537 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03004538 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00004539 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004540 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03004541
David Woodhouse5cf0a762014-03-19 16:07:49 +00004542 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03004543 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004544 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03004545
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08004546 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03004547}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004548
Joerg Roedel5d587b82014-09-05 10:50:45 +02004549static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004550{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004551 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004552 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04004553 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02004554 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004555
Joerg Roedel5d587b82014-09-05 10:50:45 +02004556 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08004557}
4558
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004559static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004560{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004561 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004562 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07004563 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04004564
Alex Williamsona5459cf2014-06-12 16:12:31 -06004565 iommu = device_to_iommu(dev, &bus, &devfn);
4566 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04004567 return -ENODEV;
4568
Alex Williamsona5459cf2014-06-12 16:12:31 -06004569 iommu_device_link(iommu->iommu_dev, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004570
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004571 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06004572
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004573 if (IS_ERR(group))
4574 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004575
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004576 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06004577 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004578}
4579
4580static void intel_iommu_remove_device(struct device *dev)
4581{
Alex Williamsona5459cf2014-06-12 16:12:31 -06004582 struct intel_iommu *iommu;
4583 u8 bus, devfn;
4584
4585 iommu = device_to_iommu(dev, &bus, &devfn);
4586 if (!iommu)
4587 return;
4588
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004589 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004590
4591 iommu_device_unlink(iommu->iommu_dev, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04004592}
4593
Thierry Redingb22f6432014-06-27 09:03:12 +02004594static const struct iommu_ops intel_iommu_ops = {
Joerg Roedel5d587b82014-09-05 10:50:45 +02004595 .capable = intel_iommu_capable,
Joerg Roedel00a77de2015-03-26 13:43:08 +01004596 .domain_alloc = intel_iommu_domain_alloc,
4597 .domain_free = intel_iommu_domain_free,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004598 .attach_dev = intel_iommu_attach_device,
4599 .detach_dev = intel_iommu_detach_device,
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01004600 .map = intel_iommu_map,
4601 .unmap = intel_iommu_unmap,
Olav Haugan315786e2014-10-25 09:55:16 -07004602 .map_sg = default_iommu_map_sg,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004603 .iova_to_phys = intel_iommu_iova_to_phys,
Alex Williamsonabdfdde2012-05-30 14:19:19 -06004604 .add_device = intel_iommu_add_device,
4605 .remove_device = intel_iommu_remove_device,
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +02004606 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004607};
David Woodhouse9af88142009-02-13 23:18:03 +00004608
Daniel Vetter94526182013-01-20 23:50:13 +01004609static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
4610{
4611 /* G4x/GM45 integrated gfx dmar support is totally busted. */
4612 printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
4613 dmar_map_gfx = 0;
4614}
4615
4616DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
4617DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
4618DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
4619DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
4620DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
4621DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
4622DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
4623
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004624static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00004625{
4626 /*
4627 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01004628 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00004629 */
4630 printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
4631 rwbf_quirk = 1;
4632}
4633
4634DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01004635DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
4636DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
4637DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
4638DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
4639DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
4640DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07004641
Adam Jacksoneecfd572010-08-25 21:17:34 +01004642#define GGC 0x52
4643#define GGC_MEMORY_SIZE_MASK (0xf << 8)
4644#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
4645#define GGC_MEMORY_SIZE_1M (0x1 << 8)
4646#define GGC_MEMORY_SIZE_2M (0x3 << 8)
4647#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
4648#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
4649#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
4650#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
4651
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08004652static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01004653{
4654 unsigned short ggc;
4655
Adam Jacksoneecfd572010-08-25 21:17:34 +01004656 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01004657 return;
4658
Adam Jacksoneecfd572010-08-25 21:17:34 +01004659 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
David Woodhouse9eecabc2010-09-21 22:28:23 +01004660 printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
4661 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07004662 } else if (dmar_map_gfx) {
4663 /* we have to ensure the gfx device is idle before we flush */
4664 printk(KERN_INFO "DMAR: Disabling batched IOTLB flush on Ironlake\n");
4665 intel_iommu_strict = 1;
4666 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01004667}
4668DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
4669DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
4670DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
4671DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
4672
David Woodhousee0fc7e02009-09-30 09:12:17 -07004673/* On Tylersburg chipsets, some BIOSes have been known to enable the
4674 ISOCH DMAR unit for the Azalia sound device, but not give it any
4675 TLB entries, which causes it to deadlock. Check for that. We do
4676 this in a function called from init_dmars(), instead of in a PCI
4677 quirk, because we don't want to print the obnoxious "BIOS broken"
4678 message if VT-d is actually disabled.
4679*/
4680static void __init check_tylersburg_isoch(void)
4681{
4682 struct pci_dev *pdev;
4683 uint32_t vtisochctrl;
4684
4685 /* If there's no Azalia in the system anyway, forget it. */
4686 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
4687 if (!pdev)
4688 return;
4689 pci_dev_put(pdev);
4690
4691 /* System Management Registers. Might be hidden, in which case
4692 we can't do the sanity check. But that's OK, because the
4693 known-broken BIOSes _don't_ actually hide it, so far. */
4694 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
4695 if (!pdev)
4696 return;
4697
4698 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
4699 pci_dev_put(pdev);
4700 return;
4701 }
4702
4703 pci_dev_put(pdev);
4704
4705 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
4706 if (vtisochctrl & 1)
4707 return;
4708
4709 /* Drop all bits other than the number of TLB entries */
4710 vtisochctrl &= 0x1c;
4711
4712 /* If we have the recommended number of TLB entries (16), fine. */
4713 if (vtisochctrl == 0x10)
4714 return;
4715
4716 /* Zero TLB entries? You get to ride the short bus to school. */
4717 if (!vtisochctrl) {
4718 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
4719 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4720 dmi_get_system_info(DMI_BIOS_VENDOR),
4721 dmi_get_system_info(DMI_BIOS_VERSION),
4722 dmi_get_system_info(DMI_PRODUCT_VERSION));
4723 iommu_identity_mapping |= IDENTMAP_AZALIA;
4724 return;
4725 }
4726
4727 printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
4728 vtisochctrl);
4729}