blob: 64dab37c0b96b581c90c8c8f6c7da495dfeaa5bf [file] [log] [blame]
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001/*
David Woodhouseea8ea462014-03-05 17:09:32 +00002 * Copyright © 2006-2014 Intel Corporation.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
David Woodhouseea8ea462014-03-05 17:09:32 +000013 * Authors: David Woodhouse <dwmw2@infradead.org>,
14 * Ashok Raj <ashok.raj@intel.com>,
15 * Shaohua Li <shaohua.li@intel.com>,
16 * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
17 * Fenghua Yu <fenghua.yu@intel.com>
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020018 * Joerg Roedel <jroedel@suse.de>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070019 */
20
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020021#define pr_fmt(fmt) "DMAR: " fmt
22
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070023#include <linux/init.h>
24#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080025#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040026#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070027#include <linux/slab.h>
28#include <linux/irq.h>
29#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070030#include <linux/spinlock.h>
31#include <linux/pci.h>
32#include <linux/dmar.h>
33#include <linux/dma-mapping.h>
34#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080035#include <linux/memory.h>
Omer Pelegaa473242016-04-20 11:33:02 +030036#include <linux/cpu.h>
mark gross5e0d2a62008-03-04 15:22:08 -080037#include <linux/timer.h>
Dan Williamsdfddb962015-10-09 18:16:46 -040038#include <linux/io.h>
Kay, Allen M38717942008-09-09 18:37:29 +030039#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010040#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030041#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010042#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070043#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100044#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020045#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080046#include <linux/memblock.h>
Akinobu Mita36746432014-06-04 16:06:51 -070047#include <linux/dma-contiguous.h>
Christoph Hellwigfec777c2018-03-19 11:38:15 +010048#include <linux/dma-direct.h>
Joerg Roedel091d42e2015-06-12 11:56:10 +020049#include <linux/crash_dump.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070050#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070051#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090052#include <asm/iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070053
Joerg Roedel078e1ee2012-09-26 12:44:43 +020054#include "irq_remapping.h"
Lu Baolu56283172018-07-14 15:46:54 +080055#include "intel-pasid.h"
Joerg Roedel078e1ee2012-09-26 12:44:43 +020056
Fenghua Yu5b6985c2008-10-16 18:02:32 -070057#define ROOT_SIZE VTD_PAGE_SIZE
58#define CONTEXT_SIZE VTD_PAGE_SIZE
59
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070060#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000061#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070062#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070063#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070064
65#define IOAPIC_RANGE_START (0xfee00000)
66#define IOAPIC_RANGE_END (0xfeefffff)
67#define IOVA_START_ADDR (0x1000)
68
Sohil Mehta5e3b4a12017-12-20 11:59:24 -080069#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070070
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070071#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080072#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070073
David Woodhouse2ebe3152009-09-19 07:34:04 -070074#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
75#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
76
77/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
78 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
79#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
80 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
81#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070082
Robin Murphy1b722502015-01-12 17:51:15 +000083/* IO virtual address start page frame number */
84#define IOVA_START_PFN (1)
85
Mark McLoughlinf27be032008-11-20 15:49:43 +000086#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
mark gross5e0d2a62008-03-04 15:22:08 -080087
Andrew Mortondf08cdc2010-09-22 13:05:11 -070088/* page table handling */
89#define LEVEL_STRIDE (9)
90#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
91
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020092/*
93 * This bitmap is used to advertise the page sizes our hardware support
94 * to the IOMMU core, which will then use this information to split
95 * physically contiguous memory regions it is mapping into page sizes
96 * that we support.
97 *
98 * Traditionally the IOMMU core just handed us the mappings directly,
99 * after making sure the size is an order of a 4KiB page and that the
100 * mapping has natural alignment.
101 *
102 * To retain this behavior, we currently advertise that we support
103 * all page sizes that are an order of 4KiB.
104 *
105 * If at some point we'd like to utilize the IOMMU core's new behavior,
106 * we could change this to advertise the real page sizes we support.
107 */
108#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
109
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700110static inline int agaw_to_level(int agaw)
111{
112 return agaw + 2;
113}
114
115static inline int agaw_to_width(int agaw)
116{
Jiang Liu5c645b32014-01-06 14:18:12 +0800117 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700118}
119
120static inline int width_to_agaw(int width)
121{
Jiang Liu5c645b32014-01-06 14:18:12 +0800122 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700123}
124
125static inline unsigned int level_to_offset_bits(int level)
126{
127 return (level - 1) * LEVEL_STRIDE;
128}
129
130static inline int pfn_level_offset(unsigned long pfn, int level)
131{
132 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
133}
134
135static inline unsigned long level_mask(int level)
136{
137 return -1UL << level_to_offset_bits(level);
138}
139
140static inline unsigned long level_size(int level)
141{
142 return 1UL << level_to_offset_bits(level);
143}
144
145static inline unsigned long align_to_level(unsigned long pfn, int level)
146{
147 return (pfn + level_size(level) - 1) & level_mask(level);
148}
David Woodhousefd18de52009-05-10 23:57:41 +0100149
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100150static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
151{
Jiang Liu5c645b32014-01-06 14:18:12 +0800152 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100153}
154
David Woodhousedd4e8312009-06-27 16:21:20 +0100155/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
156 are never going to work. */
157static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
158{
159 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
160}
161
162static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
163{
164 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
165}
166static inline unsigned long page_to_dma_pfn(struct page *pg)
167{
168 return mm_to_dma_pfn(page_to_pfn(pg));
169}
170static inline unsigned long virt_to_dma_pfn(void *p)
171{
172 return page_to_dma_pfn(virt_to_page(p));
173}
174
Weidong Hand9630fe2008-12-08 11:06:32 +0800175/* global iommu list, set NULL for ignored DMAR units */
176static struct intel_iommu **g_iommus;
177
David Woodhousee0fc7e02009-09-30 09:12:17 -0700178static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000179static int rwbf_quirk;
180
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000181/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700182 * set to 1 to panic kernel if can't successfully enable VT-d
183 * (used when kernel is launched w/ TXT)
184 */
185static int force_on = 0;
Shaohua Libfd20f12017-04-26 09:18:35 -0700186int intel_iommu_tboot_noforce;
Lu Baolu89a60792018-10-23 15:45:01 +0800187static int no_platform_optin;
Joseph Cihulab7792602011-05-03 00:08:37 -0700188
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000189#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000190
Joerg Roedel091d42e2015-06-12 11:56:10 +0200191/*
192 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
193 * if marked present.
194 */
195static phys_addr_t root_entry_lctp(struct root_entry *re)
196{
197 if (!(re->lo & 1))
198 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000199
Joerg Roedel091d42e2015-06-12 11:56:10 +0200200 return re->lo & VTD_PAGE_MASK;
201}
202
203/*
204 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
205 * if marked present.
206 */
207static phys_addr_t root_entry_uctp(struct root_entry *re)
208{
209 if (!(re->hi & 1))
210 return 0;
211
212 return re->hi & VTD_PAGE_MASK;
213}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000214
Joerg Roedelcf484d02015-06-12 12:21:46 +0200215static inline void context_clear_pasid_enable(struct context_entry *context)
216{
217 context->lo &= ~(1ULL << 11);
218}
219
220static inline bool context_pasid_enabled(struct context_entry *context)
221{
222 return !!(context->lo & (1ULL << 11));
223}
224
225static inline void context_set_copied(struct context_entry *context)
226{
227 context->hi |= (1ull << 3);
228}
229
230static inline bool context_copied(struct context_entry *context)
231{
232 return !!(context->hi & (1ULL << 3));
233}
234
235static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000236{
237 return (context->lo & 1);
238}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200239
Sohil Mehta26b86092018-09-11 17:11:36 -0700240bool context_present(struct context_entry *context)
Joerg Roedelcf484d02015-06-12 12:21:46 +0200241{
242 return context_pasid_enabled(context) ?
243 __context_present(context) :
244 __context_present(context) && !context_copied(context);
245}
246
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000247static inline void context_set_present(struct context_entry *context)
248{
249 context->lo |= 1;
250}
251
252static inline void context_set_fault_enable(struct context_entry *context)
253{
254 context->lo &= (((u64)-1) << 2) | 1;
255}
256
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000257static inline void context_set_translation_type(struct context_entry *context,
258 unsigned long value)
259{
260 context->lo &= (((u64)-1) << 4) | 3;
261 context->lo |= (value & 3) << 2;
262}
263
264static inline void context_set_address_root(struct context_entry *context,
265 unsigned long value)
266{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800267 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000268 context->lo |= value & VTD_PAGE_MASK;
269}
270
271static inline void context_set_address_width(struct context_entry *context,
272 unsigned long value)
273{
274 context->hi |= value & 7;
275}
276
277static inline void context_set_domain_id(struct context_entry *context,
278 unsigned long value)
279{
280 context->hi |= (value & ((1 << 16) - 1)) << 8;
281}
282
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200283static inline int context_domain_id(struct context_entry *c)
284{
285 return((c->hi >> 8) & 0xffff);
286}
287
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000288static inline void context_clear_entry(struct context_entry *context)
289{
290 context->lo = 0;
291 context->hi = 0;
292}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000293
Mark McLoughlin622ba122008-11-20 15:49:46 +0000294/*
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700295 * This domain is a statically identity mapping domain.
296 * 1. This domain creats a static 1:1 mapping to all usable memory.
297 * 2. It maps to each iommu if successful.
298 * 3. Each iommu mapps to this domain if successful.
299 */
David Woodhouse19943b02009-08-04 16:19:20 +0100300static struct dmar_domain *si_domain;
301static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700302
Joerg Roedel28ccce02015-07-21 14:45:31 +0200303/*
304 * Domain represents a virtual machine, more than one devices
Weidong Han1ce28fe2008-12-08 16:35:39 +0800305 * across iommus may be owned in one domain, e.g. kvm guest.
306 */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800307#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
Weidong Han1ce28fe2008-12-08 16:35:39 +0800308
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700309/* si_domain contains mulitple devices */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800310#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700311
Joerg Roedel29a27712015-07-21 17:17:12 +0200312#define for_each_domain_iommu(idx, domain) \
313 for (idx = 0; idx < g_num_of_iommus; idx++) \
314 if (domain->iommu_refcnt[idx])
315
Jiang Liub94e4112014-02-19 14:07:25 +0800316struct dmar_rmrr_unit {
317 struct list_head list; /* list of rmrr units */
318 struct acpi_dmar_header *hdr; /* ACPI header */
319 u64 base_address; /* reserved base address*/
320 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000321 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800322 int devices_cnt; /* target device count */
Eric Auger0659b8d2017-01-19 20:57:53 +0000323 struct iommu_resv_region *resv; /* reserved region handle */
Jiang Liub94e4112014-02-19 14:07:25 +0800324};
325
326struct dmar_atsr_unit {
327 struct list_head list; /* list of ATSR units */
328 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000329 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800330 int devices_cnt; /* target device count */
331 u8 include_all:1; /* include all ports */
332};
333
334static LIST_HEAD(dmar_atsr_units);
335static LIST_HEAD(dmar_rmrr_units);
336
337#define for_each_rmrr_units(rmrr) \
338 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
339
mark gross5e0d2a62008-03-04 15:22:08 -0800340/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800341static int g_num_of_iommus;
342
Jiang Liu92d03cc2014-02-19 14:07:28 +0800343static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700344static void domain_remove_dev_info(struct dmar_domain *domain);
Joerg Roedele6de0f82015-07-22 16:30:36 +0200345static void dmar_remove_one_dev_info(struct dmar_domain *domain,
346 struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200347static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Joerg Roedel2452d9d2015-07-23 16:20:14 +0200348static void domain_context_clear(struct intel_iommu *iommu,
349 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800350static int domain_detach_iommu(struct dmar_domain *domain,
351 struct intel_iommu *iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700352
Suresh Siddhad3f13812011-08-23 17:05:25 -0700353#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800354int dmar_disabled = 0;
355#else
356int dmar_disabled = 1;
Suresh Siddhad3f13812011-08-23 17:05:25 -0700357#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800358
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200359int intel_iommu_enabled = 0;
360EXPORT_SYMBOL_GPL(intel_iommu_enabled);
361
David Woodhouse2d9e6672010-06-15 10:57:57 +0100362static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700363static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800364static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100365static int intel_iommu_superpage = 1;
Lu Baolu765b6a92018-12-10 09:58:55 +0800366static int intel_iommu_sm = 1;
David Woodhouseae853dd2015-09-09 11:58:59 +0100367static int iommu_identity_mapping;
David Woodhousec83b2f22015-06-12 10:15:49 +0100368
David Woodhouseae853dd2015-09-09 11:58:59 +0100369#define IDENTMAP_ALL 1
370#define IDENTMAP_GFX 2
371#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100372
Lu Baolu765b6a92018-12-10 09:58:55 +0800373#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))
374#define pasid_supported(iommu) (sm_supported(iommu) && \
375 ecap_pasid((iommu)->ecap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700376
David Woodhousec0771df2011-10-14 20:59:46 +0100377int intel_iommu_gfx_mapped;
378EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
379
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700380#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
381static DEFINE_SPINLOCK(device_domain_lock);
382static LIST_HEAD(device_domain_list);
383
Lu Baolu85319dc2018-07-14 15:46:58 +0800384/*
385 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800386 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800387 */
388int for_each_device_domain(int (*fn)(struct device_domain_info *info,
389 void *data), void *data)
390{
391 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800392 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800393 struct device_domain_info *info;
394
Lu Baolu0bbeb012018-12-10 09:58:56 +0800395 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800396 list_for_each_entry(info, &device_domain_list, global) {
397 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800398 if (ret) {
399 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800400 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800401 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800402 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800403 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800404
405 return 0;
406}
407
Joerg Roedelb0119e82017-02-01 13:23:08 +0100408const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100409
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200410static bool translation_pre_enabled(struct intel_iommu *iommu)
411{
412 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
413}
414
Joerg Roedel091d42e2015-06-12 11:56:10 +0200415static void clear_translation_pre_enabled(struct intel_iommu *iommu)
416{
417 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
418}
419
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200420static void init_translation_status(struct intel_iommu *iommu)
421{
422 u32 gsts;
423
424 gsts = readl(iommu->reg + DMAR_GSTS_REG);
425 if (gsts & DMA_GSTS_TES)
426 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
427}
428
Joerg Roedel00a77de2015-03-26 13:43:08 +0100429/* Convert generic 'struct iommu_domain to private struct dmar_domain */
430static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
431{
432 return container_of(dom, struct dmar_domain, domain);
433}
434
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700435static int __init intel_iommu_setup(char *str)
436{
437 if (!str)
438 return -EINVAL;
439 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800440 if (!strncmp(str, "on", 2)) {
441 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200442 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800443 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700444 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800445 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200446 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700447 } else if (!strncmp(str, "igfx_off", 8)) {
448 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200449 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700450 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200451 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700452 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800453 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200454 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800455 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100456 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200457 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100458 intel_iommu_superpage = 0;
Lu Baolu765b6a92018-12-10 09:58:55 +0800459 } else if (!strncmp(str, "sm_off", 6)) {
460 pr_info("Intel-IOMMU: disable scalable mode support\n");
461 intel_iommu_sm = 0;
Shaohua Libfd20f12017-04-26 09:18:35 -0700462 } else if (!strncmp(str, "tboot_noforce", 13)) {
463 printk(KERN_INFO
464 "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
465 intel_iommu_tboot_noforce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700466 }
467
468 str += strcspn(str, ",");
469 while (*str == ',')
470 str++;
471 }
472 return 0;
473}
474__setup("intel_iommu=", intel_iommu_setup);
475
476static struct kmem_cache *iommu_domain_cache;
477static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700478
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200479static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
480{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200481 struct dmar_domain **domains;
482 int idx = did >> 8;
483
484 domains = iommu->domains[idx];
485 if (!domains)
486 return NULL;
487
488 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200489}
490
491static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
492 struct dmar_domain *domain)
493{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200494 struct dmar_domain **domains;
495 int idx = did >> 8;
496
497 if (!iommu->domains[idx]) {
498 size_t size = 256 * sizeof(struct dmar_domain *);
499 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
500 }
501
502 domains = iommu->domains[idx];
503 if (WARN_ON(!domains))
504 return;
505 else
506 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200507}
508
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800509void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700510{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700511 struct page *page;
512 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700513
Suresh Siddha4c923d42009-10-02 11:01:24 -0700514 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
515 if (page)
516 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700517 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700518}
519
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800520void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700521{
522 free_page((unsigned long)vaddr);
523}
524
525static inline void *alloc_domain_mem(void)
526{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900527 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700528}
529
Kay, Allen M38717942008-09-09 18:37:29 +0300530static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700531{
532 kmem_cache_free(iommu_domain_cache, vaddr);
533}
534
535static inline void * alloc_devinfo_mem(void)
536{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900537 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700538}
539
540static inline void free_devinfo_mem(void *vaddr)
541{
542 kmem_cache_free(iommu_devinfo_cache, vaddr);
543}
544
Jiang Liuab8dfe22014-07-11 14:19:27 +0800545static inline int domain_type_is_vm(struct dmar_domain *domain)
546{
547 return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
548}
549
Joerg Roedel28ccce02015-07-21 14:45:31 +0200550static inline int domain_type_is_si(struct dmar_domain *domain)
551{
552 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
553}
554
Jiang Liuab8dfe22014-07-11 14:19:27 +0800555static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
556{
557 return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
558 DOMAIN_FLAG_STATIC_IDENTITY);
559}
Weidong Han1b573682008-12-08 15:34:06 +0800560
Jiang Liu162d1b12014-07-11 14:19:35 +0800561static inline int domain_pfn_supported(struct dmar_domain *domain,
562 unsigned long pfn)
563{
564 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
565
566 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
567}
568
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700569static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800570{
571 unsigned long sagaw;
572 int agaw = -1;
573
574 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700575 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800576 agaw >= 0; agaw--) {
577 if (test_bit(agaw, &sagaw))
578 break;
579 }
580
581 return agaw;
582}
583
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700584/*
585 * Calculate max SAGAW for each iommu.
586 */
587int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
588{
589 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
590}
591
592/*
593 * calculate agaw for each iommu.
594 * "SAGAW" may be different across iommus, use a default agaw, and
595 * get a supported less agaw for iommus that don't support the default agaw.
596 */
597int iommu_calculate_agaw(struct intel_iommu *iommu)
598{
599 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
600}
601
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700602/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800603struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800604{
605 int iommu_id;
606
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700607 /* si_domain and vm domain should not get here. */
Jiang Liuab8dfe22014-07-11 14:19:27 +0800608 BUG_ON(domain_type_is_vm_or_si(domain));
Joerg Roedel29a27712015-07-21 17:17:12 +0200609 for_each_domain_iommu(iommu_id, domain)
610 break;
611
Weidong Han8c11e792008-12-08 15:29:22 +0800612 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
613 return NULL;
614
615 return g_iommus[iommu_id];
616}
617
Weidong Han8e6040972008-12-08 15:49:06 +0800618static void domain_update_iommu_coherency(struct dmar_domain *domain)
619{
David Woodhoused0501962014-03-11 17:10:29 -0700620 struct dmar_drhd_unit *drhd;
621 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100622 bool found = false;
623 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800624
David Woodhoused0501962014-03-11 17:10:29 -0700625 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800626
Joerg Roedel29a27712015-07-21 17:17:12 +0200627 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100628 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800629 if (!ecap_coherent(g_iommus[i]->ecap)) {
630 domain->iommu_coherency = 0;
631 break;
632 }
Weidong Han8e6040972008-12-08 15:49:06 +0800633 }
David Woodhoused0501962014-03-11 17:10:29 -0700634 if (found)
635 return;
636
637 /* No hardware attached; use lowest common denominator */
638 rcu_read_lock();
639 for_each_active_iommu(iommu, drhd) {
640 if (!ecap_coherent(iommu->ecap)) {
641 domain->iommu_coherency = 0;
642 break;
643 }
644 }
645 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800646}
647
Jiang Liu161f6932014-07-11 14:19:37 +0800648static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100649{
Allen Kay8140a952011-10-14 12:32:17 -0700650 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800651 struct intel_iommu *iommu;
652 int ret = 1;
653
654 rcu_read_lock();
655 for_each_active_iommu(iommu, drhd) {
656 if (iommu != skip) {
657 if (!ecap_sc_support(iommu->ecap)) {
658 ret = 0;
659 break;
660 }
661 }
662 }
663 rcu_read_unlock();
664
665 return ret;
666}
667
668static int domain_update_iommu_superpage(struct intel_iommu *skip)
669{
670 struct dmar_drhd_unit *drhd;
671 struct intel_iommu *iommu;
Allen Kay8140a952011-10-14 12:32:17 -0700672 int mask = 0xf;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100673
674 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800675 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100676 }
677
Allen Kay8140a952011-10-14 12:32:17 -0700678 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800679 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700680 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800681 if (iommu != skip) {
682 mask &= cap_super_page_val(iommu->cap);
683 if (!mask)
684 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100685 }
686 }
Jiang Liu0e242612014-02-19 14:07:34 +0800687 rcu_read_unlock();
688
Jiang Liu161f6932014-07-11 14:19:37 +0800689 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100690}
691
Sheng Yang58c610b2009-03-18 15:33:05 +0800692/* Some capabilities may be different across iommus */
693static void domain_update_iommu_cap(struct dmar_domain *domain)
694{
695 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800696 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
697 domain->iommu_superpage = domain_update_iommu_superpage(NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800698}
699
Sohil Mehta26b86092018-09-11 17:11:36 -0700700struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
701 u8 devfn, int alloc)
David Woodhouse03ecc322015-02-13 14:35:21 +0000702{
703 struct root_entry *root = &iommu->root_entry[bus];
704 struct context_entry *context;
705 u64 *entry;
706
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200707 entry = &root->lo;
Lu Baolu765b6a92018-12-10 09:58:55 +0800708 if (sm_supported(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000709 if (devfn >= 0x80) {
710 devfn -= 0x80;
711 entry = &root->hi;
712 }
713 devfn *= 2;
714 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000715 if (*entry & 1)
716 context = phys_to_virt(*entry & VTD_PAGE_MASK);
717 else {
718 unsigned long phy_addr;
719 if (!alloc)
720 return NULL;
721
722 context = alloc_pgtable_page(iommu->node);
723 if (!context)
724 return NULL;
725
726 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
727 phy_addr = virt_to_phys((void *)context);
728 *entry = phy_addr | 1;
729 __iommu_flush_cache(iommu, entry, sizeof(*entry));
730 }
731 return &context[devfn];
732}
733
David Woodhouse4ed6a542015-05-11 14:59:20 +0100734static int iommu_dummy(struct device *dev)
735{
736 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
737}
738
David Woodhouse156baca2014-03-09 14:00:57 -0700739static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800740{
741 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800742 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700743 struct device *tmp;
744 struct pci_dev *ptmp, *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800745 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800746 int i;
747
David Woodhouse4ed6a542015-05-11 14:59:20 +0100748 if (iommu_dummy(dev))
749 return NULL;
750
David Woodhouse156baca2014-03-09 14:00:57 -0700751 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700752 struct pci_dev *pf_pdev;
753
David Woodhouse156baca2014-03-09 14:00:57 -0700754 pdev = to_pci_dev(dev);
Jon Derrick5823e332017-08-30 15:05:59 -0600755
756#ifdef CONFIG_X86
757 /* VMD child devices currently cannot be handled individually */
758 if (is_vmd(pdev->bus))
759 return NULL;
760#endif
761
Ashok Raj1c387182016-10-21 15:32:05 -0700762 /* VFs aren't listed in scope tables; we need to look up
763 * the PF instead to find the IOMMU. */
764 pf_pdev = pci_physfn(pdev);
765 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700766 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100767 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700768 dev = &ACPI_COMPANION(dev)->dev;
769
Jiang Liu0e242612014-02-19 14:07:34 +0800770 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800771 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700772 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100773 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800774
Jiang Liub683b232014-02-19 14:07:32 +0800775 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700776 drhd->devices_cnt, i, tmp) {
777 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700778 /* For a VF use its original BDF# not that of the PF
779 * which we used for the IOMMU lookup. Strictly speaking
780 * we could do this for all PCI devices; we only need to
781 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100782 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700783 goto got_pdev;
784
David Woodhouse156baca2014-03-09 14:00:57 -0700785 *bus = drhd->devices[i].bus;
786 *devfn = drhd->devices[i].devfn;
787 goto out;
788 }
789
790 if (!pdev || !dev_is_pci(tmp))
David Woodhouse832bd852014-03-07 15:08:36 +0000791 continue;
David Woodhouse156baca2014-03-09 14:00:57 -0700792
793 ptmp = to_pci_dev(tmp);
794 if (ptmp->subordinate &&
795 ptmp->subordinate->number <= pdev->bus->number &&
796 ptmp->subordinate->busn_res.end >= pdev->bus->number)
797 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100798 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800799
David Woodhouse156baca2014-03-09 14:00:57 -0700800 if (pdev && drhd->include_all) {
801 got_pdev:
802 *bus = pdev->bus->number;
803 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800804 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700805 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800806 }
Jiang Liub683b232014-02-19 14:07:32 +0800807 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700808 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800809 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800810
Jiang Liub683b232014-02-19 14:07:32 +0800811 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800812}
813
Weidong Han5331fe62008-12-08 23:00:00 +0800814static void domain_flush_cache(struct dmar_domain *domain,
815 void *addr, int size)
816{
817 if (!domain->iommu_coherency)
818 clflush_cache_range(addr, size);
819}
820
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700821static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
822{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700823 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000824 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700825 unsigned long flags;
826
827 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000828 context = iommu_context_addr(iommu, bus, devfn, 0);
829 if (context)
830 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700831 spin_unlock_irqrestore(&iommu->lock, flags);
832 return ret;
833}
834
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700835static void free_context_table(struct intel_iommu *iommu)
836{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700837 int i;
838 unsigned long flags;
839 struct context_entry *context;
840
841 spin_lock_irqsave(&iommu->lock, flags);
842 if (!iommu->root_entry) {
843 goto out;
844 }
845 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000846 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700847 if (context)
848 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000849
Lu Baolu765b6a92018-12-10 09:58:55 +0800850 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000851 continue;
852
853 context = iommu_context_addr(iommu, i, 0x80, 0);
854 if (context)
855 free_pgtable_page(context);
856
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700857 }
858 free_pgtable_page(iommu->root_entry);
859 iommu->root_entry = NULL;
860out:
861 spin_unlock_irqrestore(&iommu->lock, flags);
862}
863
David Woodhouseb026fd22009-06-28 10:37:25 +0100864static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000865 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700866{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700867 struct dma_pte *parent, *pte = NULL;
868 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700869 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700870
871 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200872
Jiang Liu162d1b12014-07-11 14:19:35 +0800873 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200874 /* Address beyond IOMMU's addressing capabilities. */
875 return NULL;
876
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700877 parent = domain->pgd;
878
David Woodhouse5cf0a762014-03-19 16:07:49 +0000879 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700880 void *tmp_page;
881
David Woodhouseb026fd22009-06-28 10:37:25 +0100882 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700883 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000884 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100885 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000886 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700887 break;
888
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000889 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100890 uint64_t pteval;
891
Suresh Siddha4c923d42009-10-02 11:01:24 -0700892 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700893
David Woodhouse206a73c2009-07-01 19:30:28 +0100894 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700895 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100896
David Woodhousec85994e2009-07-01 19:21:24 +0100897 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400898 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 +0800899 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100900 /* Someone else set it while we were thinking; use theirs. */
901 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800902 else
David Woodhousec85994e2009-07-01 19:21:24 +0100903 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700904 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000905 if (level == 1)
906 break;
907
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000908 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700909 level--;
910 }
911
David Woodhouse5cf0a762014-03-19 16:07:49 +0000912 if (!*target_level)
913 *target_level = level;
914
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700915 return pte;
916}
917
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100918
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700919/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100920static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
921 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100922 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700923{
924 struct dma_pte *parent, *pte = NULL;
925 int total = agaw_to_level(domain->agaw);
926 int offset;
927
928 parent = domain->pgd;
929 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100930 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700931 pte = &parent[offset];
932 if (level == total)
933 return pte;
934
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100935 if (!dma_pte_present(pte)) {
936 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700937 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100938 }
939
Yijing Wange16922a2014-05-20 20:37:51 +0800940 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100941 *large_page = total;
942 return pte;
943 }
944
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000945 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700946 total--;
947 }
948 return NULL;
949}
950
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700951/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000952static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +0100953 unsigned long start_pfn,
954 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700955{
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100956 unsigned int large_page = 1;
David Woodhouse310a5ab2009-06-28 18:52:20 +0100957 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700958
Jiang Liu162d1b12014-07-11 14:19:35 +0800959 BUG_ON(!domain_pfn_supported(domain, start_pfn));
960 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -0700961 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +0100962
David Woodhouse04b18e62009-06-27 19:15:01 +0100963 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -0700964 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100965 large_page = 1;
966 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100967 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100968 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100969 continue;
970 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100971 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +0100972 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100973 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +0100974 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +0100975 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
976
David Woodhouse310a5ab2009-06-28 18:52:20 +0100977 domain_flush_cache(domain, first_pte,
978 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -0700979
980 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700981}
982
Alex Williamson3269ee02013-06-15 10:27:19 -0600983static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -0700984 int retain_level, struct dma_pte *pte,
985 unsigned long pfn, unsigned long start_pfn,
986 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -0600987{
988 pfn = max(start_pfn, pfn);
989 pte = &pte[pfn_level_offset(pfn, level)];
990
991 do {
992 unsigned long level_pfn;
993 struct dma_pte *level_pte;
994
995 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
996 goto next;
997
David Dillowf7116e12017-01-30 19:11:11 -0800998 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -0600999 level_pte = phys_to_virt(dma_pte_addr(pte));
1000
David Dillowbc24c572017-06-28 19:42:23 -07001001 if (level > 2) {
1002 dma_pte_free_level(domain, level - 1, retain_level,
1003 level_pte, level_pfn, start_pfn,
1004 last_pfn);
1005 }
Alex Williamson3269ee02013-06-15 10:27:19 -06001006
David Dillowbc24c572017-06-28 19:42:23 -07001007 /*
1008 * Free the page table if we're below the level we want to
1009 * retain and the range covers the entire table.
1010 */
1011 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001012 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001013 dma_clear_pte(pte);
1014 domain_flush_cache(domain, pte, sizeof(*pte));
1015 free_pgtable_page(level_pte);
1016 }
1017next:
1018 pfn += level_size(level);
1019 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1020}
1021
David Dillowbc24c572017-06-28 19:42:23 -07001022/*
1023 * clear last level (leaf) ptes and free page table pages below the
1024 * level we wish to keep intact.
1025 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001026static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001027 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001028 unsigned long last_pfn,
1029 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001030{
Jiang Liu162d1b12014-07-11 14:19:35 +08001031 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1032 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001033 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001034
Jiang Liud41a4ad2014-07-11 14:19:34 +08001035 dma_pte_clear_range(domain, start_pfn, last_pfn);
1036
David Woodhousef3a0a522009-06-30 03:40:07 +01001037 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001038 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001039 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001040
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001041 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001042 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001043 free_pgtable_page(domain->pgd);
1044 domain->pgd = NULL;
1045 }
1046}
1047
David Woodhouseea8ea462014-03-05 17:09:32 +00001048/* When a page at a given level is being unlinked from its parent, we don't
1049 need to *modify* it at all. All we need to do is make a list of all the
1050 pages which can be freed just as soon as we've flushed the IOTLB and we
1051 know the hardware page-walk will no longer touch them.
1052 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1053 be freed. */
1054static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1055 int level, struct dma_pte *pte,
1056 struct page *freelist)
1057{
1058 struct page *pg;
1059
1060 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1061 pg->freelist = freelist;
1062 freelist = pg;
1063
1064 if (level == 1)
1065 return freelist;
1066
Jiang Liuadeb2592014-04-09 10:20:39 +08001067 pte = page_address(pg);
1068 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001069 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1070 freelist = dma_pte_list_pagetables(domain, level - 1,
1071 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001072 pte++;
1073 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001074
1075 return freelist;
1076}
1077
1078static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1079 struct dma_pte *pte, unsigned long pfn,
1080 unsigned long start_pfn,
1081 unsigned long last_pfn,
1082 struct page *freelist)
1083{
1084 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1085
1086 pfn = max(start_pfn, pfn);
1087 pte = &pte[pfn_level_offset(pfn, level)];
1088
1089 do {
1090 unsigned long level_pfn;
1091
1092 if (!dma_pte_present(pte))
1093 goto next;
1094
1095 level_pfn = pfn & level_mask(level);
1096
1097 /* If range covers entire pagetable, free it */
1098 if (start_pfn <= level_pfn &&
1099 last_pfn >= level_pfn + level_size(level) - 1) {
1100 /* These suborbinate page tables are going away entirely. Don't
1101 bother to clear them; we're just going to *free* them. */
1102 if (level > 1 && !dma_pte_superpage(pte))
1103 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1104
1105 dma_clear_pte(pte);
1106 if (!first_pte)
1107 first_pte = pte;
1108 last_pte = pte;
1109 } else if (level > 1) {
1110 /* Recurse down into a level that isn't *entirely* obsolete */
1111 freelist = dma_pte_clear_level(domain, level - 1,
1112 phys_to_virt(dma_pte_addr(pte)),
1113 level_pfn, start_pfn, last_pfn,
1114 freelist);
1115 }
1116next:
1117 pfn += level_size(level);
1118 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1119
1120 if (first_pte)
1121 domain_flush_cache(domain, first_pte,
1122 (void *)++last_pte - (void *)first_pte);
1123
1124 return freelist;
1125}
1126
1127/* We can't just free the pages because the IOMMU may still be walking
1128 the page tables, and may have cached the intermediate levels. The
1129 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001130static struct page *domain_unmap(struct dmar_domain *domain,
1131 unsigned long start_pfn,
1132 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001133{
David Woodhouseea8ea462014-03-05 17:09:32 +00001134 struct page *freelist = NULL;
1135
Jiang Liu162d1b12014-07-11 14:19:35 +08001136 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1137 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001138 BUG_ON(start_pfn > last_pfn);
1139
1140 /* we don't need lock here; nobody else touches the iova range */
1141 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1142 domain->pgd, 0, start_pfn, last_pfn, NULL);
1143
1144 /* free pgd */
1145 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1146 struct page *pgd_page = virt_to_page(domain->pgd);
1147 pgd_page->freelist = freelist;
1148 freelist = pgd_page;
1149
1150 domain->pgd = NULL;
1151 }
1152
1153 return freelist;
1154}
1155
Joerg Roedelb6904202015-08-13 11:32:18 +02001156static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001157{
1158 struct page *pg;
1159
1160 while ((pg = freelist)) {
1161 freelist = pg->freelist;
1162 free_pgtable_page(page_address(pg));
1163 }
1164}
1165
Joerg Roedel13cf0172017-08-11 11:40:10 +02001166static void iova_entry_free(unsigned long data)
1167{
1168 struct page *freelist = (struct page *)data;
1169
1170 dma_free_pagelist(freelist);
1171}
1172
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001173/* iommu handling */
1174static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1175{
1176 struct root_entry *root;
1177 unsigned long flags;
1178
Suresh Siddha4c923d42009-10-02 11:01:24 -07001179 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001180 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001181 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001182 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001183 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001184 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001185
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001186 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001187
1188 spin_lock_irqsave(&iommu->lock, flags);
1189 iommu->root_entry = root;
1190 spin_unlock_irqrestore(&iommu->lock, flags);
1191
1192 return 0;
1193}
1194
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001195static void iommu_set_root_entry(struct intel_iommu *iommu)
1196{
David Woodhouse03ecc322015-02-13 14:35:21 +00001197 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001198 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001199 unsigned long flag;
1200
David Woodhouse03ecc322015-02-13 14:35:21 +00001201 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001202 if (sm_supported(iommu))
1203 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001204
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001205 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001206 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001207
David Woodhousec416daa2009-05-10 20:30:58 +01001208 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001209
1210 /* Make sure hardware complete it */
1211 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001212 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001213
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001214 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001215}
1216
Lu Baolu6f7db752018-12-10 09:59:00 +08001217void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001218{
1219 u32 val;
1220 unsigned long flag;
1221
David Woodhouse9af88142009-02-13 23:18:03 +00001222 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001223 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001224
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001225 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001226 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001227
1228 /* Make sure hardware complete it */
1229 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001230 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001231
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001232 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001233}
1234
1235/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001236static void __iommu_flush_context(struct intel_iommu *iommu,
1237 u16 did, u16 source_id, u8 function_mask,
1238 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001239{
1240 u64 val = 0;
1241 unsigned long flag;
1242
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001243 switch (type) {
1244 case DMA_CCMD_GLOBAL_INVL:
1245 val = DMA_CCMD_GLOBAL_INVL;
1246 break;
1247 case DMA_CCMD_DOMAIN_INVL:
1248 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1249 break;
1250 case DMA_CCMD_DEVICE_INVL:
1251 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1252 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1253 break;
1254 default:
1255 BUG();
1256 }
1257 val |= DMA_CCMD_ICC;
1258
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001259 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001260 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1261
1262 /* Make sure hardware complete it */
1263 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1264 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1265
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001266 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001267}
1268
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001269/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001270static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1271 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001272{
1273 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1274 u64 val = 0, val_iva = 0;
1275 unsigned long flag;
1276
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001277 switch (type) {
1278 case DMA_TLB_GLOBAL_FLUSH:
1279 /* global flush doesn't need set IVA_REG */
1280 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1281 break;
1282 case DMA_TLB_DSI_FLUSH:
1283 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1284 break;
1285 case DMA_TLB_PSI_FLUSH:
1286 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001287 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001288 val_iva = size_order | addr;
1289 break;
1290 default:
1291 BUG();
1292 }
1293 /* Note: set drain read/write */
1294#if 0
1295 /*
1296 * This is probably to be super secure.. Looks like we can
1297 * ignore it without any impact.
1298 */
1299 if (cap_read_drain(iommu->cap))
1300 val |= DMA_TLB_READ_DRAIN;
1301#endif
1302 if (cap_write_drain(iommu->cap))
1303 val |= DMA_TLB_WRITE_DRAIN;
1304
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001305 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001306 /* Note: Only uses first TLB reg currently */
1307 if (val_iva)
1308 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1309 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1310
1311 /* Make sure hardware complete it */
1312 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1313 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1314
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001315 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001316
1317 /* check IOTLB invalidation granularity */
1318 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001319 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001320 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001321 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001322 (unsigned long long)DMA_TLB_IIRG(type),
1323 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001324}
1325
David Woodhouse64ae8922014-03-09 12:52:30 -07001326static struct device_domain_info *
1327iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1328 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001329{
Yu Zhao93a23a72009-05-18 13:51:37 +08001330 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001331
Joerg Roedel55d94042015-07-22 16:50:40 +02001332 assert_spin_locked(&device_domain_lock);
1333
Yu Zhao93a23a72009-05-18 13:51:37 +08001334 if (!iommu->qi)
1335 return NULL;
1336
Yu Zhao93a23a72009-05-18 13:51:37 +08001337 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001338 if (info->iommu == iommu && info->bus == bus &&
1339 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001340 if (info->ats_supported && info->dev)
1341 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001342 break;
1343 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001344
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001345 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001346}
1347
Omer Peleg0824c592016-04-20 19:03:35 +03001348static void domain_update_iotlb(struct dmar_domain *domain)
1349{
1350 struct device_domain_info *info;
1351 bool has_iotlb_device = false;
1352
1353 assert_spin_locked(&device_domain_lock);
1354
1355 list_for_each_entry(info, &domain->devices, link) {
1356 struct pci_dev *pdev;
1357
1358 if (!info->dev || !dev_is_pci(info->dev))
1359 continue;
1360
1361 pdev = to_pci_dev(info->dev);
1362 if (pdev->ats_enabled) {
1363 has_iotlb_device = true;
1364 break;
1365 }
1366 }
1367
1368 domain->has_iotlb_device = has_iotlb_device;
1369}
1370
Yu Zhao93a23a72009-05-18 13:51:37 +08001371static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1372{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001373 struct pci_dev *pdev;
1374
Omer Peleg0824c592016-04-20 19:03:35 +03001375 assert_spin_locked(&device_domain_lock);
1376
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001377 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001378 return;
1379
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001380 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001381 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1382 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1383 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1384 * reserved, which should be set to 0.
1385 */
1386 if (!ecap_dit(info->iommu->ecap))
1387 info->pfsid = 0;
1388 else {
1389 struct pci_dev *pf_pdev;
1390
1391 /* pdev will be returned if device is not a vf */
1392 pf_pdev = pci_physfn(pdev);
1393 info->pfsid = PCI_DEVID(pf_pdev->bus->number, pf_pdev->devfn);
1394 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001395
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001396#ifdef CONFIG_INTEL_IOMMU_SVM
1397 /* The PCIe spec, in its wisdom, declares that the behaviour of
1398 the device if you enable PASID support after ATS support is
1399 undefined. So always enable PASID support on devices which
1400 have it, even if we can't yet know if we're ever going to
1401 use it. */
1402 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1403 info->pasid_enabled = 1;
1404
1405 if (info->pri_supported && !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
1406 info->pri_enabled = 1;
1407#endif
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001408 if (!pdev->untrusted && info->ats_supported &&
1409 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001410 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001411 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001412 info->ats_qdep = pci_ats_queue_depth(pdev);
1413 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001414}
1415
1416static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1417{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001418 struct pci_dev *pdev;
1419
Omer Peleg0824c592016-04-20 19:03:35 +03001420 assert_spin_locked(&device_domain_lock);
1421
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001422 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001423 return;
1424
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001425 pdev = to_pci_dev(info->dev);
1426
1427 if (info->ats_enabled) {
1428 pci_disable_ats(pdev);
1429 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001430 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001431 }
1432#ifdef CONFIG_INTEL_IOMMU_SVM
1433 if (info->pri_enabled) {
1434 pci_disable_pri(pdev);
1435 info->pri_enabled = 0;
1436 }
1437 if (info->pasid_enabled) {
1438 pci_disable_pasid(pdev);
1439 info->pasid_enabled = 0;
1440 }
1441#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001442}
1443
1444static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1445 u64 addr, unsigned mask)
1446{
1447 u16 sid, qdep;
1448 unsigned long flags;
1449 struct device_domain_info *info;
1450
Omer Peleg0824c592016-04-20 19:03:35 +03001451 if (!domain->has_iotlb_device)
1452 return;
1453
Yu Zhao93a23a72009-05-18 13:51:37 +08001454 spin_lock_irqsave(&device_domain_lock, flags);
1455 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001456 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001457 continue;
1458
1459 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001460 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001461 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1462 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001463 }
1464 spin_unlock_irqrestore(&device_domain_lock, flags);
1465}
1466
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001467static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1468 struct dmar_domain *domain,
1469 unsigned long pfn, unsigned int pages,
1470 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001471{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001472 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001473 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001474 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001475
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001476 BUG_ON(pages == 0);
1477
David Woodhouseea8ea462014-03-05 17:09:32 +00001478 if (ih)
1479 ih = 1 << 6;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001480 /*
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001481 * Fallback to domain selective flush if no PSI support or the size is
1482 * too big.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001483 * PSI requires page size to be 2 ^ x, and the base address is naturally
1484 * aligned to the size
1485 */
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001486 if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
1487 iommu->flush.flush_iotlb(iommu, did, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001488 DMA_TLB_DSI_FLUSH);
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001489 else
David Woodhouseea8ea462014-03-05 17:09:32 +00001490 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001491 DMA_TLB_PSI_FLUSH);
Yu Zhaobf92df32009-06-29 11:31:45 +08001492
1493 /*
Nadav Amit82653632010-04-01 13:24:40 +03001494 * In caching mode, changes of pages from non-present to present require
1495 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001496 */
Nadav Amit82653632010-04-01 13:24:40 +03001497 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001498 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001499}
1500
Peter Xueed91a02018-05-04 10:34:52 +08001501/* Notification for newly created mappings */
1502static inline void __mapping_notify_one(struct intel_iommu *iommu,
1503 struct dmar_domain *domain,
1504 unsigned long pfn, unsigned int pages)
1505{
1506 /* It's a non-present to present mapping. Only flush if caching mode */
1507 if (cap_caching_mode(iommu->cap))
1508 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1509 else
1510 iommu_flush_write_buffer(iommu);
1511}
1512
Joerg Roedel13cf0172017-08-11 11:40:10 +02001513static void iommu_flush_iova(struct iova_domain *iovad)
1514{
1515 struct dmar_domain *domain;
1516 int idx;
1517
1518 domain = container_of(iovad, struct dmar_domain, iovad);
1519
1520 for_each_domain_iommu(idx, domain) {
1521 struct intel_iommu *iommu = g_iommus[idx];
1522 u16 did = domain->iommu_did[iommu->seq_id];
1523
1524 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
1525
1526 if (!cap_caching_mode(iommu->cap))
1527 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1528 0, MAX_AGAW_PFN_WIDTH);
1529 }
1530}
1531
mark grossf8bab732008-02-08 04:18:38 -08001532static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1533{
1534 u32 pmen;
1535 unsigned long flags;
1536
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001537 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001538 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1539 pmen &= ~DMA_PMEN_EPM;
1540 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1541
1542 /* wait for the protected region status bit to clear */
1543 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1544 readl, !(pmen & DMA_PMEN_PRS), pmen);
1545
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001546 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001547}
1548
Jiang Liu2a41cce2014-07-11 14:19:33 +08001549static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001550{
1551 u32 sts;
1552 unsigned long flags;
1553
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001554 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001555 iommu->gcmd |= DMA_GCMD_TE;
1556 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001557
1558 /* Make sure hardware complete it */
1559 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001560 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001561
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001562 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001563}
1564
Jiang Liu2a41cce2014-07-11 14:19:33 +08001565static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001566{
1567 u32 sts;
1568 unsigned long flag;
1569
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001570 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001571 iommu->gcmd &= ~DMA_GCMD_TE;
1572 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1573
1574 /* Make sure hardware complete it */
1575 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001576 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001577
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001578 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001579}
1580
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07001581
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001582static int iommu_init_domains(struct intel_iommu *iommu)
1583{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001584 u32 ndomains, nlongs;
1585 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001586
1587 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001588 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001589 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001590 nlongs = BITS_TO_LONGS(ndomains);
1591
Donald Dutile94a91b502009-08-20 16:51:34 -04001592 spin_lock_init(&iommu->lock);
1593
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001594 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1595 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001596 pr_err("%s: Allocating domain id array failed\n",
1597 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001598 return -ENOMEM;
1599 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001600
Wei Yang86f004c2016-05-21 02:41:51 +00001601 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001602 iommu->domains = kzalloc(size, GFP_KERNEL);
1603
1604 if (iommu->domains) {
1605 size = 256 * sizeof(struct dmar_domain *);
1606 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1607 }
1608
1609 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001610 pr_err("%s: Allocating domain array failed\n",
1611 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001612 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001613 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001614 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001615 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001616 return -ENOMEM;
1617 }
1618
Joerg Roedel8bf47812015-07-21 10:41:21 +02001619
1620
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001621 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001622 * If Caching mode is set, then invalid translations are tagged
1623 * with domain-id 0, hence we need to pre-allocate it. We also
1624 * use domain-id 0 as a marker for non-allocated domain-id, so
1625 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001626 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001627 set_bit(0, iommu->domain_ids);
1628
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001629 /*
1630 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1631 * entry for first-level or pass-through translation modes should
1632 * be programmed with a domain id different from those used for
1633 * second-level or nested translation. We reserve a domain id for
1634 * this purpose.
1635 */
1636 if (sm_supported(iommu))
1637 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1638
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001639 return 0;
1640}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001641
Jiang Liuffebeb42014-11-09 22:48:02 +08001642static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001643{
Joerg Roedel29a27712015-07-21 17:17:12 +02001644 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001645 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001646
Joerg Roedel29a27712015-07-21 17:17:12 +02001647 if (!iommu->domains || !iommu->domain_ids)
1648 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001649
Joerg Roedelbea64032016-11-08 15:08:26 +01001650again:
Joerg Roedel55d94042015-07-22 16:50:40 +02001651 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001652 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
1653 struct dmar_domain *domain;
1654
1655 if (info->iommu != iommu)
1656 continue;
1657
1658 if (!info->dev || !info->domain)
1659 continue;
1660
1661 domain = info->domain;
1662
Joerg Roedelbea64032016-11-08 15:08:26 +01001663 __dmar_remove_one_dev_info(info);
Joerg Roedel29a27712015-07-21 17:17:12 +02001664
Joerg Roedelbea64032016-11-08 15:08:26 +01001665 if (!domain_type_is_vm_or_si(domain)) {
1666 /*
1667 * The domain_exit() function can't be called under
1668 * device_domain_lock, as it takes this lock itself.
1669 * So release the lock here and re-run the loop
1670 * afterwards.
1671 */
1672 spin_unlock_irqrestore(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001673 domain_exit(domain);
Joerg Roedelbea64032016-11-08 15:08:26 +01001674 goto again;
1675 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001676 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001677 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001678
1679 if (iommu->gcmd & DMA_GCMD_TE)
1680 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001681}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001682
Jiang Liuffebeb42014-11-09 22:48:02 +08001683static void free_dmar_iommu(struct intel_iommu *iommu)
1684{
1685 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001686 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001687 int i;
1688
1689 for (i = 0; i < elems; i++)
1690 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001691 kfree(iommu->domains);
1692 kfree(iommu->domain_ids);
1693 iommu->domains = NULL;
1694 iommu->domain_ids = NULL;
1695 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001696
Weidong Hand9630fe2008-12-08 11:06:32 +08001697 g_iommus[iommu->seq_id] = NULL;
1698
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001699 /* free context mapping */
1700 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001701
1702#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001703 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001704 if (ecap_prs(iommu->ecap))
1705 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001706 }
David Woodhouse8a94ade2015-03-24 14:54:56 +00001707#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001708}
1709
Jiang Liuab8dfe22014-07-11 14:19:27 +08001710static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001711{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001712 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001713
1714 domain = alloc_domain_mem();
1715 if (!domain)
1716 return NULL;
1717
Jiang Liuab8dfe22014-07-11 14:19:27 +08001718 memset(domain, 0, sizeof(*domain));
Suresh Siddha4c923d42009-10-02 11:01:24 -07001719 domain->nid = -1;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001720 domain->flags = flags;
Omer Peleg0824c592016-04-20 19:03:35 +03001721 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001722 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001723
1724 return domain;
1725}
1726
Joerg Roedeld160aca2015-07-22 11:52:53 +02001727/* Must be called with iommu->lock */
1728static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001729 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001730{
Jiang Liu44bde612014-07-11 14:19:29 +08001731 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001732 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001733
Joerg Roedel55d94042015-07-22 16:50:40 +02001734 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001735 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001736
Joerg Roedel29a27712015-07-21 17:17:12 +02001737 domain->iommu_refcnt[iommu->seq_id] += 1;
1738 domain->iommu_count += 1;
1739 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001740 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001741 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1742
1743 if (num >= ndomains) {
1744 pr_err("%s: No free domain ids\n", iommu->name);
1745 domain->iommu_refcnt[iommu->seq_id] -= 1;
1746 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001747 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001748 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001749
Joerg Roedeld160aca2015-07-22 11:52:53 +02001750 set_bit(num, iommu->domain_ids);
1751 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001752
Joerg Roedeld160aca2015-07-22 11:52:53 +02001753 domain->iommu_did[iommu->seq_id] = num;
1754 domain->nid = iommu->node;
1755
Jiang Liufb170fb2014-07-11 14:19:28 +08001756 domain_update_iommu_cap(domain);
1757 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001758
Joerg Roedel55d94042015-07-22 16:50:40 +02001759 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001760}
1761
1762static int domain_detach_iommu(struct dmar_domain *domain,
1763 struct intel_iommu *iommu)
1764{
Joerg Roedeld160aca2015-07-22 11:52:53 +02001765 int num, count = INT_MAX;
Jiang Liufb170fb2014-07-11 14:19:28 +08001766
Joerg Roedel55d94042015-07-22 16:50:40 +02001767 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001768 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001769
Joerg Roedel29a27712015-07-21 17:17:12 +02001770 domain->iommu_refcnt[iommu->seq_id] -= 1;
1771 count = --domain->iommu_count;
1772 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001773 num = domain->iommu_did[iommu->seq_id];
1774 clear_bit(num, iommu->domain_ids);
1775 set_iommu_domain(iommu, num, NULL);
1776
Jiang Liufb170fb2014-07-11 14:19:28 +08001777 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001778 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001779 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001780
1781 return count;
1782}
1783
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001784static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001785static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001786
Joseph Cihula51a63e62011-03-21 11:04:24 -07001787static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001788{
1789 struct pci_dev *pdev = NULL;
1790 struct iova *iova;
1791 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001792
Zhen Leiaa3ac942017-09-21 16:52:45 +01001793 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001794
Mark Gross8a443df2008-03-04 14:59:31 -08001795 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1796 &reserved_rbtree_key);
1797
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001798 /* IOAPIC ranges shouldn't be accessed by DMA */
1799 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1800 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001801 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001802 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001803 return -ENODEV;
1804 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001805
1806 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1807 for_each_pci_dev(pdev) {
1808 struct resource *r;
1809
1810 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1811 r = &pdev->resource[i];
1812 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1813 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001814 iova = reserve_iova(&reserved_iova_list,
1815 IOVA_PFN(r->start),
1816 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001817 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001818 pr_err("Reserve iova failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001819 return -ENODEV;
1820 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001821 }
1822 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001823 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001824}
1825
1826static void domain_reserve_special_ranges(struct dmar_domain *domain)
1827{
1828 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1829}
1830
1831static inline int guestwidth_to_adjustwidth(int gaw)
1832{
1833 int agaw;
1834 int r = (gaw - 12) % 9;
1835
1836 if (r == 0)
1837 agaw = gaw;
1838 else
1839 agaw = gaw + 9 - r;
1840 if (agaw > 64)
1841 agaw = 64;
1842 return agaw;
1843}
1844
Joerg Roedeldc534b22015-07-22 12:44:02 +02001845static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1846 int guest_width)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001847{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001848 int adjust_width, agaw;
1849 unsigned long sagaw;
Joerg Roedel13cf0172017-08-11 11:40:10 +02001850 int err;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001851
Zhen Leiaa3ac942017-09-21 16:52:45 +01001852 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001853
1854 err = init_iova_flush_queue(&domain->iovad,
1855 iommu_flush_iova, iova_entry_free);
1856 if (err)
1857 return err;
1858
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001859 domain_reserve_special_ranges(domain);
1860
1861 /* calculate AGAW */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001862 if (guest_width > cap_mgaw(iommu->cap))
1863 guest_width = cap_mgaw(iommu->cap);
1864 domain->gaw = guest_width;
1865 adjust_width = guestwidth_to_adjustwidth(guest_width);
1866 agaw = width_to_agaw(adjust_width);
1867 sagaw = cap_sagaw(iommu->cap);
1868 if (!test_bit(agaw, &sagaw)) {
1869 /* hardware doesn't support it, choose a bigger one */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001870 pr_debug("Hardware doesn't support agaw %d\n", agaw);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001871 agaw = find_next_bit(&sagaw, 5, agaw);
1872 if (agaw >= 5)
1873 return -ENODEV;
1874 }
1875 domain->agaw = agaw;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001876
Weidong Han8e6040972008-12-08 15:49:06 +08001877 if (ecap_coherent(iommu->ecap))
1878 domain->iommu_coherency = 1;
1879 else
1880 domain->iommu_coherency = 0;
1881
Sheng Yang58c610b2009-03-18 15:33:05 +08001882 if (ecap_sc_support(iommu->ecap))
1883 domain->iommu_snooping = 1;
1884 else
1885 domain->iommu_snooping = 0;
1886
David Woodhouse214e39a2014-03-19 10:38:49 +00001887 if (intel_iommu_superpage)
1888 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1889 else
1890 domain->iommu_superpage = 0;
1891
Suresh Siddha4c923d42009-10-02 11:01:24 -07001892 domain->nid = iommu->node;
Weidong Hanc7151a82008-12-08 22:51:37 +08001893
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001894 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07001895 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001896 if (!domain->pgd)
1897 return -ENOMEM;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001898 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001899 return 0;
1900}
1901
1902static void domain_exit(struct dmar_domain *domain)
1903{
David Woodhouseea8ea462014-03-05 17:09:32 +00001904 struct page *freelist = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001905
1906 /* Domain 0 is reserved, so dont process it */
1907 if (!domain)
1908 return;
1909
Joerg Roedeld160aca2015-07-22 11:52:53 +02001910 /* Remove associated devices and clear attached or cached domains */
1911 rcu_read_lock();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001912 domain_remove_dev_info(domain);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001913 rcu_read_unlock();
Jiang Liu92d03cc2014-02-19 14:07:28 +08001914
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001915 /* destroy iovas */
1916 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001917
David Woodhouseea8ea462014-03-05 17:09:32 +00001918 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001919
David Woodhouseea8ea462014-03-05 17:09:32 +00001920 dma_free_pagelist(freelist);
1921
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001922 free_domain_mem(domain);
1923}
1924
Lu Baolu7373a8c2018-12-10 09:59:03 +08001925/*
1926 * Get the PASID directory size for scalable mode context entry.
1927 * Value of X in the PDTS field of a scalable mode context entry
1928 * indicates PASID directory with 2^(X + 7) entries.
1929 */
1930static inline unsigned long context_get_sm_pds(struct pasid_table *table)
1931{
1932 int pds, max_pde;
1933
1934 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
1935 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
1936 if (pds < 7)
1937 return 0;
1938
1939 return pds - 7;
1940}
1941
1942/*
1943 * Set the RID_PASID field of a scalable mode context entry. The
1944 * IOMMU hardware will use the PASID value set in this field for
1945 * DMA translations of DMA requests without PASID.
1946 */
1947static inline void
1948context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
1949{
1950 context->hi |= pasid & ((1 << 20) - 1);
1951 context->hi |= (1 << 20);
1952}
1953
1954/*
1955 * Set the DTE(Device-TLB Enable) field of a scalable mode context
1956 * entry.
1957 */
1958static inline void context_set_sm_dte(struct context_entry *context)
1959{
1960 context->lo |= (1 << 2);
1961}
1962
1963/*
1964 * Set the PRE(Page Request Enable) field of a scalable mode context
1965 * entry.
1966 */
1967static inline void context_set_sm_pre(struct context_entry *context)
1968{
1969 context->lo |= (1 << 4);
1970}
1971
1972/* Convert value to context PASID directory size field coding. */
1973#define context_pdts(pds) (((pds) & 0x7) << 9)
1974
David Woodhouse64ae8922014-03-09 12:52:30 -07001975static int domain_context_mapping_one(struct dmar_domain *domain,
1976 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08001977 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02001978 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001979{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001980 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02001981 int translation = CONTEXT_TT_MULTI_LEVEL;
1982 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001983 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001984 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08001985 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02001986
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02001987 WARN_ON(did == 0);
1988
Joerg Roedel28ccce02015-07-21 14:45:31 +02001989 if (hw_pass_through && domain_type_is_si(domain))
1990 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001991
1992 pr_debug("Set context mapping for %02x:%02x.%d\n",
1993 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07001994
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001995 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08001996
Joerg Roedel55d94042015-07-22 16:50:40 +02001997 spin_lock_irqsave(&device_domain_lock, flags);
1998 spin_lock(&iommu->lock);
1999
2000 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00002001 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002002 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02002003 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002004
Joerg Roedel55d94042015-07-22 16:50:40 +02002005 ret = 0;
2006 if (context_present(context))
2007 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002008
Xunlei Pangaec0e862016-12-05 20:09:07 +08002009 /*
2010 * For kdump cases, old valid entries may be cached due to the
2011 * in-flight DMA and copied pgtable, but there is no unmapping
2012 * behaviour for them, thus we need an explicit cache flush for
2013 * the newly-mapped device. For kdump, at this point, the device
2014 * is supposed to finish reset at its driver probe stage, so no
2015 * in-flight DMA will exist, and we don't need to worry anymore
2016 * hereafter.
2017 */
2018 if (context_copied(context)) {
2019 u16 did_old = context_domain_id(context);
2020
Christos Gkekasb117e032017-10-08 23:33:31 +01002021 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002022 iommu->flush.flush_context(iommu, did_old,
2023 (((u16)bus) << 8) | devfn,
2024 DMA_CCMD_MASK_NOBIT,
2025 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002026 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2027 DMA_TLB_DSI_FLUSH);
2028 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002029 }
2030
Joerg Roedelde24e552015-07-21 14:53:04 +02002031 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002032
Lu Baolu7373a8c2018-12-10 09:59:03 +08002033 if (sm_supported(iommu)) {
2034 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002035
Lu Baolu7373a8c2018-12-10 09:59:03 +08002036 WARN_ON(!table);
2037
2038 /* Setup the PASID DIR pointer: */
2039 pds = context_get_sm_pds(table);
2040 context->lo = (u64)virt_to_phys(table->table) |
2041 context_pdts(pds);
2042
2043 /* Setup the RID_PASID field: */
2044 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2045
2046 /*
2047 * Setup the Device-TLB enable bit and Page request
2048 * Enable bit:
2049 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002050 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002051 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002052 context_set_sm_dte(context);
2053 if (info && info->pri_supported)
2054 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002055 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002056 struct dma_pte *pgd = domain->pgd;
2057 int agaw;
2058
2059 context_set_domain_id(context, did);
2060 context_set_translation_type(context, translation);
2061
2062 if (translation != CONTEXT_TT_PASS_THROUGH) {
2063 /*
2064 * Skip top levels of page tables for iommu which has
2065 * less agaw than default. Unnecessary for PT mode.
2066 */
2067 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2068 ret = -ENOMEM;
2069 pgd = phys_to_virt(dma_pte_addr(pgd));
2070 if (!dma_pte_present(pgd))
2071 goto out_unlock;
2072 }
2073
2074 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2075 if (info && info->ats_supported)
2076 translation = CONTEXT_TT_DEV_IOTLB;
2077 else
2078 translation = CONTEXT_TT_MULTI_LEVEL;
2079
2080 context_set_address_root(context, virt_to_phys(pgd));
2081 context_set_address_width(context, agaw);
2082 } else {
2083 /*
2084 * In pass through mode, AW must be programmed to
2085 * indicate the largest AGAW value supported by
2086 * hardware. And ASR is ignored by hardware.
2087 */
2088 context_set_address_width(context, iommu->msagaw);
2089 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002090 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002091
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002092 context_set_fault_enable(context);
2093 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08002094 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002095
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002096 /*
2097 * It's a non-present to present mapping. If hardware doesn't cache
2098 * non-present entry we only need to flush the write-buffer. If the
2099 * _does_ cache non-present entries, then it does so in the special
2100 * domain #0, which we have to flush:
2101 */
2102 if (cap_caching_mode(iommu->cap)) {
2103 iommu->flush.flush_context(iommu, 0,
2104 (((u16)bus) << 8) | devfn,
2105 DMA_CCMD_MASK_NOBIT,
2106 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002107 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002108 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002109 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002110 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002111 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002112
Joerg Roedel55d94042015-07-22 16:50:40 +02002113 ret = 0;
2114
2115out_unlock:
2116 spin_unlock(&iommu->lock);
2117 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002118
Wei Yang5c365d12016-07-13 13:53:21 +00002119 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002120}
2121
Alex Williamson579305f2014-07-03 09:51:43 -06002122struct domain_context_mapping_data {
2123 struct dmar_domain *domain;
2124 struct intel_iommu *iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002125 struct pasid_table *table;
Alex Williamson579305f2014-07-03 09:51:43 -06002126};
2127
2128static int domain_context_mapping_cb(struct pci_dev *pdev,
2129 u16 alias, void *opaque)
2130{
2131 struct domain_context_mapping_data *data = opaque;
2132
2133 return domain_context_mapping_one(data->domain, data->iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002134 data->table, PCI_BUS_NUM(alias),
2135 alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06002136}
2137
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002138static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002139domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002140{
Lu Baoluca6e3222018-12-10 09:59:02 +08002141 struct domain_context_mapping_data data;
2142 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002143 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002144 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002145
David Woodhousee1f167f2014-03-09 15:24:46 -07002146 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002147 if (!iommu)
2148 return -ENODEV;
2149
Lu Baoluca6e3222018-12-10 09:59:02 +08002150 table = intel_pasid_get_table(dev);
2151
Alex Williamson579305f2014-07-03 09:51:43 -06002152 if (!dev_is_pci(dev))
Lu Baoluca6e3222018-12-10 09:59:02 +08002153 return domain_context_mapping_one(domain, iommu, table,
2154 bus, devfn);
Alex Williamson579305f2014-07-03 09:51:43 -06002155
2156 data.domain = domain;
2157 data.iommu = iommu;
Lu Baoluca6e3222018-12-10 09:59:02 +08002158 data.table = table;
Alex Williamson579305f2014-07-03 09:51:43 -06002159
2160 return pci_for_each_dma_alias(to_pci_dev(dev),
2161 &domain_context_mapping_cb, &data);
2162}
2163
2164static int domain_context_mapped_cb(struct pci_dev *pdev,
2165 u16 alias, void *opaque)
2166{
2167 struct intel_iommu *iommu = opaque;
2168
2169 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002170}
2171
David Woodhousee1f167f2014-03-09 15:24:46 -07002172static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002173{
Weidong Han5331fe62008-12-08 23:00:00 +08002174 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002175 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002176
David Woodhousee1f167f2014-03-09 15:24:46 -07002177 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002178 if (!iommu)
2179 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002180
Alex Williamson579305f2014-07-03 09:51:43 -06002181 if (!dev_is_pci(dev))
2182 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002183
Alex Williamson579305f2014-07-03 09:51:43 -06002184 return !pci_for_each_dma_alias(to_pci_dev(dev),
2185 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002186}
2187
Fenghua Yuf5329592009-08-04 15:09:37 -07002188/* Returns a number of VTD pages, but aligned to MM page size */
2189static inline unsigned long aligned_nrpages(unsigned long host_addr,
2190 size_t size)
2191{
2192 host_addr &= ~PAGE_MASK;
2193 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2194}
2195
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002196/* Return largest possible superpage level for a given mapping */
2197static inline int hardware_largepage_caps(struct dmar_domain *domain,
2198 unsigned long iov_pfn,
2199 unsigned long phy_pfn,
2200 unsigned long pages)
2201{
2202 int support, level = 1;
2203 unsigned long pfnmerge;
2204
2205 support = domain->iommu_superpage;
2206
2207 /* To use a large page, the virtual *and* physical addresses
2208 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2209 of them will mean we have to use smaller pages. So just
2210 merge them and check both at once. */
2211 pfnmerge = iov_pfn | phy_pfn;
2212
2213 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2214 pages >>= VTD_STRIDE_SHIFT;
2215 if (!pages)
2216 break;
2217 pfnmerge >>= VTD_STRIDE_SHIFT;
2218 level++;
2219 support--;
2220 }
2221 return level;
2222}
2223
David Woodhouse9051aa02009-06-29 12:30:54 +01002224static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2225 struct scatterlist *sg, unsigned long phys_pfn,
2226 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002227{
2228 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002229 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002230 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002231 unsigned int largepage_lvl = 0;
2232 unsigned long lvl_pages = 0;
David Woodhousee1605492009-06-29 11:17:38 +01002233
Jiang Liu162d1b12014-07-11 14:19:35 +08002234 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002235
2236 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2237 return -EINVAL;
2238
2239 prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
2240
Jiang Liucc4f14a2014-11-26 09:42:10 +08002241 if (!sg) {
2242 sg_res = nr_pages;
David Woodhouse9051aa02009-06-29 12:30:54 +01002243 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
2244 }
2245
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002246 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002247 uint64_t tmp;
2248
David Woodhousee1605492009-06-29 11:17:38 +01002249 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002250 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2251
Fenghua Yuf5329592009-08-04 15:09:37 -07002252 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002253 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002254 sg->dma_length = sg->length;
Robin Murphy29a90b72017-09-28 15:14:01 +01002255 pteval = (sg_phys(sg) - pgoff) | prot;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002256 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002257 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002258
David Woodhousee1605492009-06-29 11:17:38 +01002259 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002260 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2261
David Woodhouse5cf0a762014-03-19 16:07:49 +00002262 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002263 if (!pte)
2264 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002265 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002266 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002267 unsigned long nr_superpages, end_pfn;
2268
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002269 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002270 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002271
2272 nr_superpages = sg_res / lvl_pages;
2273 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2274
Jiang Liud41a4ad2014-07-11 14:19:34 +08002275 /*
2276 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002277 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002278 * We're adding new large pages, so make sure
2279 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002280 */
David Dillowbc24c572017-06-28 19:42:23 -07002281 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2282 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002283 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002284 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002285 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002286
David Woodhousee1605492009-06-29 11:17:38 +01002287 }
2288 /* We don't need lock here, nobody else
2289 * touches the iova range
2290 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002291 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002292 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002293 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002294 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2295 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002296 if (dumps) {
2297 dumps--;
2298 debug_dma_dump_mappings(NULL);
2299 }
2300 WARN_ON(1);
2301 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002302
2303 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2304
2305 BUG_ON(nr_pages < lvl_pages);
2306 BUG_ON(sg_res < lvl_pages);
2307
2308 nr_pages -= lvl_pages;
2309 iov_pfn += lvl_pages;
2310 phys_pfn += lvl_pages;
2311 pteval += lvl_pages * VTD_PAGE_SIZE;
2312 sg_res -= lvl_pages;
2313
2314 /* If the next PTE would be the first in a new page, then we
2315 need to flush the cache on the entries we've just written.
2316 And then we'll need to recalculate 'pte', so clear it and
2317 let it get set again in the if (!pte) block above.
2318
2319 If we're done (!nr_pages) we need to flush the cache too.
2320
2321 Also if we've been setting superpages, we may need to
2322 recalculate 'pte' and switch back to smaller pages for the
2323 end of the mapping, if the trailing size is not enough to
2324 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002325 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002326 if (!nr_pages || first_pte_in_page(pte) ||
2327 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002328 domain_flush_cache(domain, first_pte,
2329 (void *)pte - (void *)first_pte);
2330 pte = NULL;
2331 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002332
2333 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002334 sg = sg_next(sg);
2335 }
2336 return 0;
2337}
2338
Peter Xu87684fd2018-05-04 10:34:53 +08002339static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2340 struct scatterlist *sg, unsigned long phys_pfn,
2341 unsigned long nr_pages, int prot)
2342{
2343 int ret;
2344 struct intel_iommu *iommu;
2345
2346 /* Do the real mapping first */
2347 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2348 if (ret)
2349 return ret;
2350
2351 /* Notify about the new mapping */
2352 if (domain_type_is_vm(domain)) {
2353 /* VM typed domains can have more than one IOMMUs */
2354 int iommu_id;
2355 for_each_domain_iommu(iommu_id, domain) {
2356 iommu = g_iommus[iommu_id];
2357 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2358 }
2359 } else {
2360 /* General domains only have one IOMMU */
2361 iommu = domain_get_iommu(domain);
2362 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2363 }
2364
2365 return 0;
2366}
2367
David Woodhouse9051aa02009-06-29 12:30:54 +01002368static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2369 struct scatterlist *sg, unsigned long nr_pages,
2370 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002371{
Peter Xu87684fd2018-05-04 10:34:53 +08002372 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002373}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002374
David Woodhouse9051aa02009-06-29 12:30:54 +01002375static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2376 unsigned long phys_pfn, unsigned long nr_pages,
2377 int prot)
2378{
Peter Xu87684fd2018-05-04 10:34:53 +08002379 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002380}
2381
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002382static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002383{
Filippo Sironi50822192017-08-31 10:58:11 +02002384 unsigned long flags;
2385 struct context_entry *context;
2386 u16 did_old;
2387
Weidong Hanc7151a82008-12-08 22:51:37 +08002388 if (!iommu)
2389 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002390
Filippo Sironi50822192017-08-31 10:58:11 +02002391 spin_lock_irqsave(&iommu->lock, flags);
2392 context = iommu_context_addr(iommu, bus, devfn, 0);
2393 if (!context) {
2394 spin_unlock_irqrestore(&iommu->lock, flags);
2395 return;
2396 }
2397 did_old = context_domain_id(context);
2398 context_clear_entry(context);
2399 __iommu_flush_cache(iommu, context, sizeof(*context));
2400 spin_unlock_irqrestore(&iommu->lock, flags);
2401 iommu->flush.flush_context(iommu,
2402 did_old,
2403 (((u16)bus) << 8) | devfn,
2404 DMA_CCMD_MASK_NOBIT,
2405 DMA_CCMD_DEVICE_INVL);
2406 iommu->flush.flush_iotlb(iommu,
2407 did_old,
2408 0,
2409 0,
2410 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002411}
2412
David Woodhouse109b9b02012-05-25 17:43:02 +01002413static inline void unlink_domain_info(struct device_domain_info *info)
2414{
2415 assert_spin_locked(&device_domain_lock);
2416 list_del(&info->link);
2417 list_del(&info->global);
2418 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002419 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002420}
2421
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002422static void domain_remove_dev_info(struct dmar_domain *domain)
2423{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002424 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002425 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002426
2427 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002428 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002429 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002430 spin_unlock_irqrestore(&device_domain_lock, flags);
2431}
2432
2433/*
2434 * find_domain
David Woodhouse1525a292014-03-06 16:19:30 +00002435 * Note: we use struct device->archdata.iommu stores the info
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002436 */
David Woodhouse1525a292014-03-06 16:19:30 +00002437static struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002438{
2439 struct device_domain_info *info;
2440
2441 /* No lock here, assumes no domain exit in normal case */
David Woodhouse1525a292014-03-06 16:19:30 +00002442 info = dev->archdata.iommu;
Peter Xub316d022017-05-22 18:28:51 +08002443 if (likely(info))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002444 return info->domain;
2445 return NULL;
2446}
2447
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002448static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002449dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2450{
2451 struct device_domain_info *info;
2452
2453 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002454 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002455 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002456 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002457
2458 return NULL;
2459}
2460
Joerg Roedel5db31562015-07-22 12:40:43 +02002461static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2462 int bus, int devfn,
2463 struct device *dev,
2464 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002465{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002466 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002467 struct device_domain_info *info;
2468 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002469 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002470
2471 info = alloc_devinfo_mem();
2472 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002473 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002474
Jiang Liu745f2582014-02-19 14:07:26 +08002475 info->bus = bus;
2476 info->devfn = devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002477 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2478 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2479 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002480 info->dev = dev;
2481 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002482 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002483 info->pasid_table = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002484
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002485 if (dev && dev_is_pci(dev)) {
2486 struct pci_dev *pdev = to_pci_dev(info->dev);
2487
Gil Kupfercef74402018-05-10 17:56:02 -05002488 if (!pci_ats_disabled() &&
2489 ecap_dev_iotlb_support(iommu->ecap) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002490 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
2491 dmar_find_matched_atsr_unit(pdev))
2492 info->ats_supported = 1;
2493
Lu Baolu765b6a92018-12-10 09:58:55 +08002494 if (sm_supported(iommu)) {
2495 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002496 int features = pci_pasid_features(pdev);
2497 if (features >= 0)
2498 info->pasid_supported = features | 1;
2499 }
2500
2501 if (info->ats_supported && ecap_prs(iommu->ecap) &&
2502 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
2503 info->pri_supported = 1;
2504 }
2505 }
2506
Jiang Liu745f2582014-02-19 14:07:26 +08002507 spin_lock_irqsave(&device_domain_lock, flags);
2508 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002509 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002510
2511 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002512 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002513 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002514 if (info2) {
2515 found = info2->domain;
2516 info2->dev = dev;
2517 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002518 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002519
Jiang Liu745f2582014-02-19 14:07:26 +08002520 if (found) {
2521 spin_unlock_irqrestore(&device_domain_lock, flags);
2522 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002523 /* Caller must free the original domain */
2524 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002525 }
2526
Joerg Roedeld160aca2015-07-22 11:52:53 +02002527 spin_lock(&iommu->lock);
2528 ret = domain_attach_iommu(domain, iommu);
2529 spin_unlock(&iommu->lock);
2530
2531 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002532 spin_unlock_irqrestore(&device_domain_lock, flags);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302533 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002534 return NULL;
2535 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002536
David Woodhouseb718cd32014-03-09 13:11:33 -07002537 list_add(&info->link, &domain->devices);
2538 list_add(&info->global, &device_domain_list);
2539 if (dev)
2540 dev->archdata.iommu = info;
Lu Baolu0bbeb012018-12-10 09:58:56 +08002541 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002542
Lu Baolu0bbeb012018-12-10 09:58:56 +08002543 /* PASID table is mandatory for a PCI device in scalable mode. */
2544 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002545 ret = intel_pasid_alloc_table(dev);
2546 if (ret) {
Lu Baolu0bbeb012018-12-10 09:58:56 +08002547 pr_err("PASID table allocation for %s failed\n",
2548 dev_name(dev));
2549 dmar_remove_one_dev_info(domain, dev);
2550 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002551 }
Lu Baoluef848b72018-12-10 09:59:01 +08002552
2553 /* Setup the PASID entry for requests without PASID: */
2554 spin_lock(&iommu->lock);
2555 if (hw_pass_through && domain_type_is_si(domain))
2556 ret = intel_pasid_setup_pass_through(iommu, domain,
2557 dev, PASID_RID2PASID);
2558 else
2559 ret = intel_pasid_setup_second_level(iommu, domain,
2560 dev, PASID_RID2PASID);
2561 spin_unlock(&iommu->lock);
2562 if (ret) {
2563 pr_err("Setup RID2PASID for %s failed\n",
2564 dev_name(dev));
2565 dmar_remove_one_dev_info(domain, dev);
2566 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002567 }
2568 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002569
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002570 if (dev && domain_context_mapping(domain, dev)) {
2571 pr_err("Domain context map for %s failed\n", dev_name(dev));
Joerg Roedele6de0f82015-07-22 16:30:36 +02002572 dmar_remove_one_dev_info(domain, dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002573 return NULL;
2574 }
2575
David Woodhouseb718cd32014-03-09 13:11:33 -07002576 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002577}
2578
Alex Williamson579305f2014-07-03 09:51:43 -06002579static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2580{
2581 *(u16 *)opaque = alias;
2582 return 0;
2583}
2584
Joerg Roedel76208352016-08-25 14:25:12 +02002585static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002586{
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002587 struct device_domain_info *info = NULL;
Joerg Roedel76208352016-08-25 14:25:12 +02002588 struct dmar_domain *domain = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002589 struct intel_iommu *iommu;
Lu Baolufcc35c62018-05-04 13:08:17 +08002590 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002591 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002592 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002593
David Woodhouse146922e2014-03-09 15:44:17 -07002594 iommu = device_to_iommu(dev, &bus, &devfn);
2595 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002596 return NULL;
2597
2598 if (dev_is_pci(dev)) {
2599 struct pci_dev *pdev = to_pci_dev(dev);
2600
2601 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2602
2603 spin_lock_irqsave(&device_domain_lock, flags);
2604 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2605 PCI_BUS_NUM(dma_alias),
2606 dma_alias & 0xff);
2607 if (info) {
2608 iommu = info->iommu;
2609 domain = info->domain;
2610 }
2611 spin_unlock_irqrestore(&device_domain_lock, flags);
2612
Joerg Roedel76208352016-08-25 14:25:12 +02002613 /* DMA alias already has a domain, use it */
Alex Williamson579305f2014-07-03 09:51:43 -06002614 if (info)
Joerg Roedel76208352016-08-25 14:25:12 +02002615 goto out;
Alex Williamson579305f2014-07-03 09:51:43 -06002616 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002617
David Woodhouse146922e2014-03-09 15:44:17 -07002618 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002619 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002620 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002621 return NULL;
Joerg Roedeldc534b22015-07-22 12:44:02 +02002622 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002623 domain_exit(domain);
2624 return NULL;
2625 }
2626
Joerg Roedel76208352016-08-25 14:25:12 +02002627out:
Alex Williamson579305f2014-07-03 09:51:43 -06002628
Joerg Roedel76208352016-08-25 14:25:12 +02002629 return domain;
2630}
2631
2632static struct dmar_domain *set_domain_for_dev(struct device *dev,
2633 struct dmar_domain *domain)
2634{
2635 struct intel_iommu *iommu;
2636 struct dmar_domain *tmp;
2637 u16 req_id, dma_alias;
2638 u8 bus, devfn;
2639
2640 iommu = device_to_iommu(dev, &bus, &devfn);
2641 if (!iommu)
2642 return NULL;
2643
2644 req_id = ((u16)bus << 8) | devfn;
2645
2646 if (dev_is_pci(dev)) {
2647 struct pci_dev *pdev = to_pci_dev(dev);
2648
2649 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2650
2651 /* register PCI DMA alias device */
2652 if (req_id != dma_alias) {
2653 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2654 dma_alias & 0xff, NULL, domain);
2655
2656 if (!tmp || tmp != domain)
2657 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002658 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002659 }
2660
Joerg Roedel5db31562015-07-22 12:40:43 +02002661 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
Joerg Roedel76208352016-08-25 14:25:12 +02002662 if (!tmp || tmp != domain)
2663 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002664
Joerg Roedel76208352016-08-25 14:25:12 +02002665 return domain;
2666}
2667
2668static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2669{
2670 struct dmar_domain *domain, *tmp;
2671
2672 domain = find_domain(dev);
2673 if (domain)
2674 goto out;
2675
2676 domain = find_or_alloc_domain(dev, gaw);
2677 if (!domain)
2678 goto out;
2679
2680 tmp = set_domain_for_dev(dev, domain);
2681 if (!tmp || domain != tmp) {
Alex Williamson579305f2014-07-03 09:51:43 -06002682 domain_exit(domain);
2683 domain = tmp;
2684 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002685
Joerg Roedel76208352016-08-25 14:25:12 +02002686out:
2687
David Woodhouseb718cd32014-03-09 13:11:33 -07002688 return domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002689}
2690
David Woodhouseb2132032009-06-26 18:50:28 +01002691static int iommu_domain_identity_map(struct dmar_domain *domain,
2692 unsigned long long start,
2693 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002694{
David Woodhousec5395d52009-06-28 16:35:56 +01002695 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2696 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002697
David Woodhousec5395d52009-06-28 16:35:56 +01002698 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2699 dma_to_mm_pfn(last_vpfn))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002700 pr_err("Reserving iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002701 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002702 }
2703
Joerg Roedelaf1089c2015-07-21 15:45:19 +02002704 pr_debug("Mapping reserved region %llx-%llx\n", start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002705 /*
2706 * RMRR range might have overlap with physical memory range,
2707 * clear it first
2708 */
David Woodhousec5395d52009-06-28 16:35:56 +01002709 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002710
Peter Xu87684fd2018-05-04 10:34:53 +08002711 return __domain_mapping(domain, first_vpfn, NULL,
2712 first_vpfn, last_vpfn - first_vpfn + 1,
2713 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002714}
2715
Joerg Roedeld66ce542015-09-23 19:00:10 +02002716static int domain_prepare_identity_map(struct device *dev,
2717 struct dmar_domain *domain,
2718 unsigned long long start,
2719 unsigned long long end)
David Woodhouseb2132032009-06-26 18:50:28 +01002720{
David Woodhouse19943b02009-08-04 16:19:20 +01002721 /* For _hardware_ passthrough, don't bother. But for software
2722 passthrough, we do it anyway -- it may indicate a memory
2723 range which is reserved in E820, so which didn't get set
2724 up to start with in si_domain */
2725 if (domain == si_domain && hw_pass_through) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002726 pr_warn("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
2727 dev_name(dev), start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002728 return 0;
2729 }
2730
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002731 pr_info("Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
2732 dev_name(dev), start, end);
2733
David Woodhouse5595b522009-12-02 09:21:55 +00002734 if (end < start) {
2735 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2736 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2737 dmi_get_system_info(DMI_BIOS_VENDOR),
2738 dmi_get_system_info(DMI_BIOS_VERSION),
2739 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002740 return -EIO;
David Woodhouse5595b522009-12-02 09:21:55 +00002741 }
2742
David Woodhouse2ff729f2009-08-26 14:25:41 +01002743 if (end >> agaw_to_width(domain->agaw)) {
2744 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2745 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2746 agaw_to_width(domain->agaw),
2747 dmi_get_system_info(DMI_BIOS_VENDOR),
2748 dmi_get_system_info(DMI_BIOS_VERSION),
2749 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002750 return -EIO;
David Woodhouse2ff729f2009-08-26 14:25:41 +01002751 }
David Woodhouse19943b02009-08-04 16:19:20 +01002752
Joerg Roedeld66ce542015-09-23 19:00:10 +02002753 return iommu_domain_identity_map(domain, start, end);
2754}
2755
2756static int iommu_prepare_identity_map(struct device *dev,
2757 unsigned long long start,
2758 unsigned long long end)
2759{
2760 struct dmar_domain *domain;
2761 int ret;
2762
2763 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
2764 if (!domain)
2765 return -ENOMEM;
2766
2767 ret = domain_prepare_identity_map(dev, domain, start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002768 if (ret)
Joerg Roedeld66ce542015-09-23 19:00:10 +02002769 domain_exit(domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002770
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002771 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002772}
2773
2774static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
David Woodhouse0b9d9752014-03-09 15:48:15 -07002775 struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002776{
David Woodhouse0b9d9752014-03-09 15:48:15 -07002777 if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002778 return 0;
David Woodhouse0b9d9752014-03-09 15:48:15 -07002779 return iommu_prepare_identity_map(dev, rmrr->base_address,
2780 rmrr->end_address);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002781}
2782
Suresh Siddhad3f13812011-08-23 17:05:25 -07002783#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002784static inline void iommu_prepare_isa(void)
2785{
2786 struct pci_dev *pdev;
2787 int ret;
2788
2789 pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
2790 if (!pdev)
2791 return;
2792
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002793 pr_info("Prepare 0-16MiB unity mapping for LPC\n");
David Woodhouse0b9d9752014-03-09 15:48:15 -07002794 ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002795
2796 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002797 pr_err("Failed to create 0-16MiB identity map - floppy might not work\n");
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002798
Yijing Wang9b27e822014-05-20 20:37:52 +08002799 pci_dev_put(pdev);
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002800}
2801#else
2802static inline void iommu_prepare_isa(void)
2803{
2804 return;
2805}
Suresh Siddhad3f13812011-08-23 17:05:25 -07002806#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07002807
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002808static int md_domain_init(struct dmar_domain *domain, int guest_width);
David Woodhousec7ab48d2009-06-26 19:10:36 +01002809
Matt Kraai071e1372009-08-23 22:30:22 -07002810static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002811{
David Woodhousec7ab48d2009-06-26 19:10:36 +01002812 int nid, ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002813
Jiang Liuab8dfe22014-07-11 14:19:27 +08002814 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002815 if (!si_domain)
2816 return -EFAULT;
2817
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002818 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
2819 domain_exit(si_domain);
2820 return -EFAULT;
2821 }
2822
Joerg Roedel0dc79712015-07-21 15:40:06 +02002823 pr_debug("Identity mapping domain allocated\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002824
David Woodhouse19943b02009-08-04 16:19:20 +01002825 if (hw)
2826 return 0;
2827
David Woodhousec7ab48d2009-06-26 19:10:36 +01002828 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002829 unsigned long start_pfn, end_pfn;
2830 int i;
2831
2832 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2833 ret = iommu_domain_identity_map(si_domain,
2834 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2835 if (ret)
2836 return ret;
2837 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002838 }
2839
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002840 return 0;
2841}
2842
David Woodhouse9b226622014-03-09 14:03:28 -07002843static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002844{
2845 struct device_domain_info *info;
2846
2847 if (likely(!iommu_identity_mapping))
2848 return 0;
2849
David Woodhouse9b226622014-03-09 14:03:28 -07002850 info = dev->archdata.iommu;
Mike Traviscb452a42011-05-28 13:15:03 -05002851 if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
2852 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002853
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002854 return 0;
2855}
2856
Joerg Roedel28ccce02015-07-21 14:45:31 +02002857static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002858{
David Woodhouse0ac72662014-03-09 13:19:22 -07002859 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002860 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002861 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002862
David Woodhouse5913c9b2014-03-09 16:27:31 -07002863 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002864 if (!iommu)
2865 return -ENODEV;
2866
Joerg Roedel5db31562015-07-22 12:40:43 +02002867 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002868 if (ndomain != domain)
2869 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002870
2871 return 0;
2872}
2873
David Woodhouse0b9d9752014-03-09 15:48:15 -07002874static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002875{
2876 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002877 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002878 int i;
2879
Jiang Liu0e242612014-02-19 14:07:34 +08002880 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002881 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002882 /*
2883 * Return TRUE if this RMRR contains the device that
2884 * is passed in.
2885 */
2886 for_each_active_dev_scope(rmrr->devices,
2887 rmrr->devices_cnt, i, tmp)
David Woodhouse0b9d9752014-03-09 15:48:15 -07002888 if (tmp == dev) {
Jiang Liu0e242612014-02-19 14:07:34 +08002889 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002890 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002891 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002892 }
Jiang Liu0e242612014-02-19 14:07:34 +08002893 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002894 return false;
2895}
2896
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002897/*
2898 * There are a couple cases where we need to restrict the functionality of
2899 * devices associated with RMRRs. The first is when evaluating a device for
2900 * identity mapping because problems exist when devices are moved in and out
2901 * of domains and their respective RMRR information is lost. This means that
2902 * a device with associated RMRRs will never be in a "passthrough" domain.
2903 * The second is use of the device through the IOMMU API. This interface
2904 * expects to have full control of the IOVA space for the device. We cannot
2905 * satisfy both the requirement that RMRR access is maintained and have an
2906 * unencumbered IOVA space. We also have no ability to quiesce the device's
2907 * use of the RMRR space or even inform the IOMMU API user of the restriction.
2908 * We therefore prevent devices associated with an RMRR from participating in
2909 * the IOMMU API, which eliminates them from device assignment.
2910 *
2911 * In both cases we assume that PCI USB devices with RMRRs have them largely
2912 * for historical reasons and that the RMRR space is not actively used post
2913 * boot. This exclusion may change if vendors begin to abuse it.
David Woodhouse18436af2015-03-25 15:05:47 +00002914 *
2915 * The same exception is made for graphics devices, with the requirement that
2916 * any use of the RMRR regions will be torn down before assigning the device
2917 * to a guest.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002918 */
2919static bool device_is_rmrr_locked(struct device *dev)
2920{
2921 if (!device_has_rmrr(dev))
2922 return false;
2923
2924 if (dev_is_pci(dev)) {
2925 struct pci_dev *pdev = to_pci_dev(dev);
2926
David Woodhouse18436af2015-03-25 15:05:47 +00002927 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002928 return false;
2929 }
2930
2931 return true;
2932}
2933
David Woodhouse3bdb2592014-03-09 16:03:08 -07002934static int iommu_should_identity_map(struct device *dev, int startup)
David Woodhouse6941af22009-07-04 18:24:27 +01002935{
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002936
David Woodhouse3bdb2592014-03-09 16:03:08 -07002937 if (dev_is_pci(dev)) {
2938 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002939
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002940 if (device_is_rmrr_locked(dev))
David Woodhouse3bdb2592014-03-09 16:03:08 -07002941 return 0;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002942
Lu Baolu89a60792018-10-23 15:45:01 +08002943 /*
2944 * Prevent any device marked as untrusted from getting
2945 * placed into the statically identity mapping domain.
2946 */
2947 if (pdev->untrusted)
2948 return 0;
2949
David Woodhouse3bdb2592014-03-09 16:03:08 -07002950 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
2951 return 1;
David Woodhousee0fc7e02009-09-30 09:12:17 -07002952
David Woodhouse3bdb2592014-03-09 16:03:08 -07002953 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
2954 return 1;
2955
2956 if (!(iommu_identity_mapping & IDENTMAP_ALL))
2957 return 0;
2958
2959 /*
2960 * We want to start off with all devices in the 1:1 domain, and
2961 * take them out later if we find they can't access all of memory.
2962 *
2963 * However, we can't do this for PCI devices behind bridges,
2964 * because all PCI devices behind the same bridge will end up
2965 * with the same source-id on their transactions.
2966 *
2967 * Practically speaking, we can't change things around for these
2968 * devices at run-time, because we can't be sure there'll be no
2969 * DMA transactions in flight for any of their siblings.
2970 *
2971 * So PCI devices (unless they're on the root bus) as well as
2972 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
2973 * the 1:1 domain, just in _case_ one of their siblings turns out
2974 * not to be able to map all of memory.
2975 */
2976 if (!pci_is_pcie(pdev)) {
2977 if (!pci_is_root_bus(pdev->bus))
2978 return 0;
2979 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
2980 return 0;
2981 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
2982 return 0;
2983 } else {
2984 if (device_has_rmrr(dev))
2985 return 0;
2986 }
David Woodhouse6941af22009-07-04 18:24:27 +01002987
David Woodhouse3dfc8132009-07-04 19:11:08 +01002988 /*
David Woodhouse3dfc8132009-07-04 19:11:08 +01002989 * At boot time, we don't yet know if devices will be 64-bit capable.
David Woodhouse3bdb2592014-03-09 16:03:08 -07002990 * Assume that they will — if they turn out not to be, then we can
David Woodhouse3dfc8132009-07-04 19:11:08 +01002991 * take them out of the 1:1 domain later.
2992 */
Chris Wright8fcc5372011-05-28 13:15:02 -05002993 if (!startup) {
2994 /*
2995 * If the device's dma_mask is less than the system's memory
2996 * size then this is not a candidate for identity mapping.
2997 */
David Woodhouse3bdb2592014-03-09 16:03:08 -07002998 u64 dma_mask = *dev->dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05002999
David Woodhouse3bdb2592014-03-09 16:03:08 -07003000 if (dev->coherent_dma_mask &&
3001 dev->coherent_dma_mask < dma_mask)
3002 dma_mask = dev->coherent_dma_mask;
Chris Wright8fcc5372011-05-28 13:15:02 -05003003
David Woodhouse3bdb2592014-03-09 16:03:08 -07003004 return dma_mask >= dma_get_required_mask(dev);
Chris Wright8fcc5372011-05-28 13:15:02 -05003005 }
David Woodhouse6941af22009-07-04 18:24:27 +01003006
3007 return 1;
3008}
3009
David Woodhousecf04eee2014-03-21 16:49:04 +00003010static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw)
3011{
3012 int ret;
3013
3014 if (!iommu_should_identity_map(dev, 1))
3015 return 0;
3016
Joerg Roedel28ccce02015-07-21 14:45:31 +02003017 ret = domain_add_dev_info(si_domain, dev);
David Woodhousecf04eee2014-03-21 16:49:04 +00003018 if (!ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003019 pr_info("%s identity mapping for device %s\n",
3020 hw ? "Hardware" : "Software", dev_name(dev));
David Woodhousecf04eee2014-03-21 16:49:04 +00003021 else if (ret == -ENODEV)
3022 /* device not associated with an iommu */
3023 ret = 0;
3024
3025 return ret;
3026}
3027
3028
Matt Kraai071e1372009-08-23 22:30:22 -07003029static int __init iommu_prepare_static_identity_mapping(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003030{
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003031 struct pci_dev *pdev = NULL;
David Woodhousecf04eee2014-03-21 16:49:04 +00003032 struct dmar_drhd_unit *drhd;
3033 struct intel_iommu *iommu;
3034 struct device *dev;
3035 int i;
3036 int ret = 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003037
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003038 for_each_pci_dev(pdev) {
David Woodhousecf04eee2014-03-21 16:49:04 +00003039 ret = dev_prepare_static_identity_mapping(&pdev->dev, hw);
3040 if (ret)
3041 return ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003042 }
3043
David Woodhousecf04eee2014-03-21 16:49:04 +00003044 for_each_active_iommu(iommu, drhd)
3045 for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) {
3046 struct acpi_device_physical_node *pn;
3047 struct acpi_device *adev;
3048
3049 if (dev->bus != &acpi_bus_type)
3050 continue;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003051
David Woodhousecf04eee2014-03-21 16:49:04 +00003052 adev= to_acpi_device(dev);
3053 mutex_lock(&adev->physical_node_lock);
3054 list_for_each_entry(pn, &adev->physical_node_list, node) {
3055 ret = dev_prepare_static_identity_mapping(pn->dev, hw);
3056 if (ret)
3057 break;
3058 }
3059 mutex_unlock(&adev->physical_node_lock);
3060 if (ret)
3061 return ret;
3062 }
3063
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003064 return 0;
3065}
3066
Jiang Liuffebeb42014-11-09 22:48:02 +08003067static void intel_iommu_init_qi(struct intel_iommu *iommu)
3068{
3069 /*
3070 * Start from the sane iommu hardware state.
3071 * If the queued invalidation is already initialized by us
3072 * (for example, while enabling interrupt-remapping) then
3073 * we got the things already rolling from a sane state.
3074 */
3075 if (!iommu->qi) {
3076 /*
3077 * Clear any previous faults.
3078 */
3079 dmar_fault(-1, iommu);
3080 /*
3081 * Disable queued invalidation if supported and already enabled
3082 * before OS handover.
3083 */
3084 dmar_disable_qi(iommu);
3085 }
3086
3087 if (dmar_enable_qi(iommu)) {
3088 /*
3089 * Queued Invalidate not enabled, use Register Based Invalidate
3090 */
3091 iommu->flush.flush_context = __iommu_flush_context;
3092 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003093 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08003094 iommu->name);
3095 } else {
3096 iommu->flush.flush_context = qi_flush_context;
3097 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003098 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08003099 }
3100}
3101
Joerg Roedel091d42e2015-06-12 11:56:10 +02003102static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04003103 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02003104 struct context_entry **tbl,
3105 int bus, bool ext)
3106{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003107 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003108 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04003109 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003110 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003111 phys_addr_t old_ce_phys;
3112
3113 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04003114 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003115
3116 for (devfn = 0; devfn < 256; devfn++) {
3117 /* First calculate the correct index */
3118 idx = (ext ? devfn * 2 : devfn) % 256;
3119
3120 if (idx == 0) {
3121 /* First save what we may have and clean up */
3122 if (new_ce) {
3123 tbl[tbl_idx] = new_ce;
3124 __iommu_flush_cache(iommu, new_ce,
3125 VTD_PAGE_SIZE);
3126 pos = 1;
3127 }
3128
3129 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08003130 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003131
3132 ret = 0;
3133 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003134 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003135 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003136 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003137
3138 if (!old_ce_phys) {
3139 if (ext && devfn == 0) {
3140 /* No LCTP, try UCTP */
3141 devfn = 0x7f;
3142 continue;
3143 } else {
3144 goto out;
3145 }
3146 }
3147
3148 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003149 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3150 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003151 if (!old_ce)
3152 goto out;
3153
3154 new_ce = alloc_pgtable_page(iommu->node);
3155 if (!new_ce)
3156 goto out_unmap;
3157
3158 ret = 0;
3159 }
3160
3161 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003162 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003163
Joerg Roedelcf484d02015-06-12 12:21:46 +02003164 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003165 continue;
3166
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003167 did = context_domain_id(&ce);
3168 if (did >= 0 && did < cap_ndoms(iommu->cap))
3169 set_bit(did, iommu->domain_ids);
3170
Joerg Roedelcf484d02015-06-12 12:21:46 +02003171 /*
3172 * We need a marker for copied context entries. This
3173 * marker needs to work for the old format as well as
3174 * for extended context entries.
3175 *
3176 * Bit 67 of the context entry is used. In the old
3177 * format this bit is available to software, in the
3178 * extended format it is the PGE bit, but PGE is ignored
3179 * by HW if PASIDs are disabled (and thus still
3180 * available).
3181 *
3182 * So disable PASIDs first and then mark the entry
3183 * copied. This means that we don't copy PASID
3184 * translations from the old kernel, but this is fine as
3185 * faults there are not fatal.
3186 */
3187 context_clear_pasid_enable(&ce);
3188 context_set_copied(&ce);
3189
Joerg Roedel091d42e2015-06-12 11:56:10 +02003190 new_ce[idx] = ce;
3191 }
3192
3193 tbl[tbl_idx + pos] = new_ce;
3194
3195 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3196
3197out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003198 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003199
3200out:
3201 return ret;
3202}
3203
3204static int copy_translation_tables(struct intel_iommu *iommu)
3205{
3206 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003207 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003208 phys_addr_t old_rt_phys;
3209 int ctxt_table_entries;
3210 unsigned long flags;
3211 u64 rtaddr_reg;
3212 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003213 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003214
3215 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3216 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003217 new_ext = !!ecap_ecs(iommu->ecap);
3218
3219 /*
3220 * The RTT bit can only be changed when translation is disabled,
3221 * but disabling translation means to open a window for data
3222 * corruption. So bail out and don't copy anything if we would
3223 * have to change the bit.
3224 */
3225 if (new_ext != ext)
3226 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003227
3228 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3229 if (!old_rt_phys)
3230 return -EINVAL;
3231
Dan Williamsdfddb962015-10-09 18:16:46 -04003232 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003233 if (!old_rt)
3234 return -ENOMEM;
3235
3236 /* This is too big for the stack - allocate it from slab */
3237 ctxt_table_entries = ext ? 512 : 256;
3238 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003239 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003240 if (!ctxt_tbls)
3241 goto out_unmap;
3242
3243 for (bus = 0; bus < 256; bus++) {
3244 ret = copy_context_table(iommu, &old_rt[bus],
3245 ctxt_tbls, bus, ext);
3246 if (ret) {
3247 pr_err("%s: Failed to copy context table for bus %d\n",
3248 iommu->name, bus);
3249 continue;
3250 }
3251 }
3252
3253 spin_lock_irqsave(&iommu->lock, flags);
3254
3255 /* Context tables are copied, now write them to the root_entry table */
3256 for (bus = 0; bus < 256; bus++) {
3257 int idx = ext ? bus * 2 : bus;
3258 u64 val;
3259
3260 if (ctxt_tbls[idx]) {
3261 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3262 iommu->root_entry[bus].lo = val;
3263 }
3264
3265 if (!ext || !ctxt_tbls[idx + 1])
3266 continue;
3267
3268 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3269 iommu->root_entry[bus].hi = val;
3270 }
3271
3272 spin_unlock_irqrestore(&iommu->lock, flags);
3273
3274 kfree(ctxt_tbls);
3275
3276 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3277
3278 ret = 0;
3279
3280out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003281 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003282
3283 return ret;
3284}
3285
Joseph Cihulab7792602011-05-03 00:08:37 -07003286static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003287{
3288 struct dmar_drhd_unit *drhd;
3289 struct dmar_rmrr_unit *rmrr;
Joerg Roedela87f4912015-06-12 12:32:54 +02003290 bool copied_tables = false;
David Woodhouse832bd852014-03-07 15:08:36 +00003291 struct device *dev;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003292 struct intel_iommu *iommu;
Joerg Roedel13cf0172017-08-11 11:40:10 +02003293 int i, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003294
3295 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003296 * for each drhd
3297 * allocate root
3298 * initialize and program root entry to not present
3299 * endfor
3300 */
3301 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003302 /*
3303 * lock not needed as this is only incremented in the single
3304 * threaded kernel __init code path all other access are read
3305 * only
3306 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003307 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003308 g_num_of_iommus++;
3309 continue;
3310 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003311 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003312 }
3313
Jiang Liuffebeb42014-11-09 22:48:02 +08003314 /* Preallocate enough resources for IOMMU hot-addition */
3315 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3316 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3317
Weidong Hand9630fe2008-12-08 11:06:32 +08003318 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3319 GFP_KERNEL);
3320 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003321 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003322 ret = -ENOMEM;
3323 goto error;
3324 }
3325
Jiang Liu7c919772014-01-06 14:18:18 +08003326 for_each_active_iommu(iommu, drhd) {
Lu Baolu56283172018-07-14 15:46:54 +08003327 /*
3328 * Find the max pasid size of all IOMMU's in the system.
3329 * We need to ensure the system pasid table is no bigger
3330 * than the smallest supported.
3331 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003332 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003333 u32 temp = 2 << ecap_pss(iommu->ecap);
3334
3335 intel_pasid_max_id = min_t(u32, temp,
3336 intel_pasid_max_id);
3337 }
3338
Weidong Hand9630fe2008-12-08 11:06:32 +08003339 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003340
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003341 intel_iommu_init_qi(iommu);
3342
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003343 ret = iommu_init_domains(iommu);
3344 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003345 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003346
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003347 init_translation_status(iommu);
3348
Joerg Roedel091d42e2015-06-12 11:56:10 +02003349 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3350 iommu_disable_translation(iommu);
3351 clear_translation_pre_enabled(iommu);
3352 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3353 iommu->name);
3354 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003355
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003356 /*
3357 * TBD:
3358 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003359 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003360 */
3361 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003362 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003363 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003364
Joerg Roedel091d42e2015-06-12 11:56:10 +02003365 if (translation_pre_enabled(iommu)) {
3366 pr_info("Translation already enabled - trying to copy translation structures\n");
3367
3368 ret = copy_translation_tables(iommu);
3369 if (ret) {
3370 /*
3371 * We found the IOMMU with translation
3372 * enabled - but failed to copy over the
3373 * old root-entry table. Try to proceed
3374 * by disabling translation now and
3375 * allocating a clean root-entry table.
3376 * This might cause DMAR faults, but
3377 * probably the dump will still succeed.
3378 */
3379 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3380 iommu->name);
3381 iommu_disable_translation(iommu);
3382 clear_translation_pre_enabled(iommu);
3383 } else {
3384 pr_info("Copied translation tables from previous kernel for %s\n",
3385 iommu->name);
Joerg Roedela87f4912015-06-12 12:32:54 +02003386 copied_tables = true;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003387 }
3388 }
3389
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003390 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003391 hw_pass_through = 0;
David Woodhouse8a94ade2015-03-24 14:54:56 +00003392#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003393 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08003394 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00003395#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003396 }
3397
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003398 /*
3399 * Now that qi is enabled on all iommus, set the root entry and flush
3400 * caches. This is required on some Intel X58 chipsets, otherwise the
3401 * flush_context function will loop forever and the boot hangs.
3402 */
3403 for_each_active_iommu(iommu, drhd) {
3404 iommu_flush_write_buffer(iommu);
3405 iommu_set_root_entry(iommu);
3406 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3407 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3408 }
3409
David Woodhouse19943b02009-08-04 16:19:20 +01003410 if (iommu_pass_through)
David Woodhousee0fc7e02009-09-30 09:12:17 -07003411 iommu_identity_mapping |= IDENTMAP_ALL;
3412
Suresh Siddhad3f13812011-08-23 17:05:25 -07003413#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
David Woodhousee0fc7e02009-09-30 09:12:17 -07003414 iommu_identity_mapping |= IDENTMAP_GFX;
David Woodhouse19943b02009-08-04 16:19:20 +01003415#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003416
Ashok Raj21e722c2017-01-30 09:39:53 -08003417 check_tylersburg_isoch();
3418
Joerg Roedel86080cc2015-06-12 12:27:16 +02003419 if (iommu_identity_mapping) {
3420 ret = si_domain_init(hw_pass_through);
3421 if (ret)
3422 goto free_iommu;
3423 }
3424
David Woodhousee0fc7e02009-09-30 09:12:17 -07003425
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003426 /*
Joerg Roedela87f4912015-06-12 12:32:54 +02003427 * If we copied translations from a previous kernel in the kdump
3428 * case, we can not assign the devices to domains now, as that
3429 * would eliminate the old mappings. So skip this part and defer
3430 * the assignment to device driver initialization time.
3431 */
3432 if (copied_tables)
3433 goto domains_done;
3434
3435 /*
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003436 * If pass through is not set or not enabled, setup context entries for
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003437 * identity mappings for rmrr, gfx, and isa and may fall back to static
3438 * identity mapping if iommu_identity_mapping is set.
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003439 */
David Woodhouse19943b02009-08-04 16:19:20 +01003440 if (iommu_identity_mapping) {
3441 ret = iommu_prepare_static_identity_mapping(hw_pass_through);
3442 if (ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003443 pr_crit("Failed to setup IOMMU pass-through\n");
Jiang Liu989d51f2014-02-19 14:07:21 +08003444 goto free_iommu;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003445 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003446 }
David Woodhouse19943b02009-08-04 16:19:20 +01003447 /*
3448 * For each rmrr
3449 * for each dev attached to rmrr
3450 * do
3451 * locate drhd for dev, alloc domain for dev
3452 * allocate free domain
3453 * allocate page table entries for rmrr
3454 * if context not allocated for bus
3455 * allocate and init context
3456 * set present in root table for this bus
3457 * init context with domain, translation etc
3458 * endfor
3459 * endfor
3460 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003461 pr_info("Setting RMRR:\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003462 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08003463 /* some BIOS lists non-exist devices in DMAR table. */
3464 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
David Woodhouse832bd852014-03-07 15:08:36 +00003465 i, dev) {
David Woodhouse0b9d9752014-03-09 15:48:15 -07003466 ret = iommu_prepare_rmrr_dev(rmrr, dev);
David Woodhouse19943b02009-08-04 16:19:20 +01003467 if (ret)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003468 pr_err("Mapping reserved region failed\n");
David Woodhouse19943b02009-08-04 16:19:20 +01003469 }
3470 }
3471
3472 iommu_prepare_isa();
Keshavamurthy, Anil S49a04292007-10-21 16:41:57 -07003473
Joerg Roedela87f4912015-06-12 12:32:54 +02003474domains_done:
3475
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003476 /*
3477 * for each drhd
3478 * enable fault log
3479 * global invalidate context cache
3480 * global invalidate iotlb
3481 * enable translation
3482 */
Jiang Liu7c919772014-01-06 14:18:18 +08003483 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003484 if (drhd->ignored) {
3485 /*
3486 * we always have to disable PMRs or DMA may fail on
3487 * this device
3488 */
3489 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003490 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003491 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003492 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003493
3494 iommu_flush_write_buffer(iommu);
3495
David Woodhousea222a7f2015-10-07 23:35:18 +01003496#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003497 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01003498 ret = intel_svm_enable_prq(iommu);
3499 if (ret)
3500 goto free_iommu;
3501 }
3502#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003503 ret = dmar_set_interrupt(iommu);
3504 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003505 goto free_iommu;
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003506
Joerg Roedel8939ddf2015-06-12 14:40:01 +02003507 if (!translation_pre_enabled(iommu))
3508 iommu_enable_translation(iommu);
3509
David Woodhouseb94996c2009-09-19 15:28:12 -07003510 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003511 }
3512
3513 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003514
3515free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003516 for_each_active_iommu(iommu, drhd) {
3517 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003518 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003519 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003520
Weidong Hand9630fe2008-12-08 11:06:32 +08003521 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003522
Jiang Liu989d51f2014-02-19 14:07:21 +08003523error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003524 return ret;
3525}
3526
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003527/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003528static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003529 struct dmar_domain *domain,
3530 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003531{
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003532 unsigned long iova_pfn = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003533
David Woodhouse875764d2009-06-28 21:20:51 +01003534 /* Restrict dma_mask to the width that the iommu can handle */
3535 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
Robin Murphy8f6429c2015-07-16 19:40:12 +01003536 /* Ensure we reserve the whole size-aligned region */
3537 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003538
3539 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003540 /*
3541 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003542 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003543 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003544 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003545 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003546 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003547 if (iova_pfn)
3548 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003549 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003550 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3551 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003552 if (unlikely(!iova_pfn)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003553 pr_err("Allocating %ld-page iova for %s failed",
David Woodhouse207e3592014-03-09 16:12:32 -07003554 nrpages, dev_name(dev));
Omer Peleg2aac6302016-04-20 11:33:57 +03003555 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003556 }
3557
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003558 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003559}
3560
Lu Baolu9ddbfb42018-07-14 15:46:57 +08003561struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003562{
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003563 struct dmar_domain *domain, *tmp;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003564 struct dmar_rmrr_unit *rmrr;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003565 struct device *i_dev;
3566 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003567
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003568 domain = find_domain(dev);
3569 if (domain)
3570 goto out;
3571
3572 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3573 if (!domain)
3574 goto out;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003575
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003576 /* We have a new domain - setup possible RMRRs for the device */
3577 rcu_read_lock();
3578 for_each_rmrr_units(rmrr) {
3579 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3580 i, i_dev) {
3581 if (i_dev != dev)
3582 continue;
3583
3584 ret = domain_prepare_identity_map(dev, domain,
3585 rmrr->base_address,
3586 rmrr->end_address);
3587 if (ret)
3588 dev_err(dev, "Mapping reserved region failed\n");
3589 }
3590 }
3591 rcu_read_unlock();
3592
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003593 tmp = set_domain_for_dev(dev, domain);
3594 if (!tmp || domain != tmp) {
3595 domain_exit(domain);
3596 domain = tmp;
3597 }
3598
3599out:
3600
3601 if (!domain)
3602 pr_err("Allocating domain for %s failed\n", dev_name(dev));
3603
3604
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003605 return domain;
3606}
3607
David Woodhouseecb509e2014-03-09 16:29:55 -07003608/* Check if the dev needs to go through non-identity map and unmap process.*/
David Woodhouse73676832009-07-04 14:08:36 +01003609static int iommu_no_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003610{
3611 int found;
3612
David Woodhouse3d891942014-03-06 15:59:26 +00003613 if (iommu_dummy(dev))
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003614 return 1;
3615
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003616 if (!iommu_identity_mapping)
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003617 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003618
David Woodhouse9b226622014-03-09 14:03:28 -07003619 found = identity_mapping(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003620 if (found) {
David Woodhouseecb509e2014-03-09 16:29:55 -07003621 if (iommu_should_identity_map(dev, 0))
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003622 return 1;
3623 else {
3624 /*
3625 * 32 bit DMA is removed from si_domain and fall back
3626 * to non-identity mapping.
3627 */
Joerg Roedele6de0f82015-07-22 16:30:36 +02003628 dmar_remove_one_dev_info(si_domain, dev);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003629 pr_info("32bit %s uses non-identity mapping\n",
3630 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003631 return 0;
3632 }
3633 } else {
3634 /*
3635 * In case of a detached 64 bit DMA device from vm, the device
3636 * is put into si_domain for identity mapping.
3637 */
David Woodhouseecb509e2014-03-09 16:29:55 -07003638 if (iommu_should_identity_map(dev, 0)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003639 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02003640 ret = domain_add_dev_info(si_domain, dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003641 if (!ret) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003642 pr_info("64bit %s uses identity mapping\n",
3643 dev_name(dev));
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003644 return 1;
3645 }
3646 }
3647 }
3648
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003649 return 0;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003650}
3651
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003652static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3653 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003654{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003655 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003656 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003657 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003658 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003659 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003660 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003661 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003662
3663 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003664
David Woodhouse5040a912014-03-09 16:14:00 -07003665 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003666 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003667
David Woodhouse5040a912014-03-09 16:14:00 -07003668 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003669 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003670 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003671
Weidong Han8c11e792008-12-08 15:29:22 +08003672 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003673 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003674
Omer Peleg2aac6302016-04-20 11:33:57 +03003675 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3676 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003677 goto error;
3678
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003679 /*
3680 * Check if DMAR supports zero-length reads on write only
3681 * mappings..
3682 */
3683 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003684 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003685 prot |= DMA_PTE_READ;
3686 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3687 prot |= DMA_PTE_WRITE;
3688 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003689 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003690 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003691 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003692 * is not a big problem
3693 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003694 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003695 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003696 if (ret)
3697 goto error;
3698
Omer Peleg2aac6302016-04-20 11:33:57 +03003699 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003700 start_paddr += paddr & ~PAGE_MASK;
3701 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003702
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003703error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003704 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003705 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003706 pr_err("Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003707 dev_name(dev), size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003708 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003709}
3710
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003711static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3712 unsigned long offset, size_t size,
3713 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003714 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003715{
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003716 return __intel_map_single(dev, page_to_phys(page) + offset, size,
3717 dir, *dev->dma_mask);
3718}
3719
3720static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3721 size_t size, enum dma_data_direction dir,
3722 unsigned long attrs)
3723{
3724 return __intel_map_single(dev, phys_addr, size, dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003725}
3726
Omer Peleg769530e2016-04-20 11:33:25 +03003727static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003728{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003730 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003731 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003732 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003733 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003734 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003735
David Woodhouse73676832009-07-04 14:08:36 +01003736 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003737 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003738
David Woodhouse1525a292014-03-06 16:19:30 +00003739 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003740 BUG_ON(!domain);
3741
Weidong Han8c11e792008-12-08 15:29:22 +08003742 iommu = domain_get_iommu(domain);
3743
Omer Peleg2aac6302016-04-20 11:33:57 +03003744 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003745
Omer Peleg769530e2016-04-20 11:33:25 +03003746 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003747 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003748 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003749
David Woodhoused794dc92009-06-28 00:27:49 +01003750 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003751 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003752
David Woodhouseea8ea462014-03-05 17:09:32 +00003753 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003754
mark gross5e0d2a62008-03-04 15:22:08 -08003755 if (intel_iommu_strict) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003756 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003757 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003758 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003759 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003760 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003761 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003762 queue_iova(&domain->iovad, iova_pfn, nrpages,
3763 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003764 /*
3765 * queue up the release of the unmap to save the 1/6th of the
3766 * cpu used up by the iotlb flush operation...
3767 */
mark gross5e0d2a62008-03-04 15:22:08 -08003768 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003769}
3770
Jiang Liud41a4ad2014-07-11 14:19:34 +08003771static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3772 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003773 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003774{
Omer Peleg769530e2016-04-20 11:33:25 +03003775 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003776}
3777
David Woodhouse5040a912014-03-09 16:14:00 -07003778static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003779 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003780 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003781{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003782 struct page *page = NULL;
3783 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003784
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003785 size = PAGE_ALIGN(size);
3786 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003787
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003788 if (!iommu_no_mapping(dev))
3789 flags &= ~(GFP_DMA | GFP_DMA32);
3790 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3791 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
3792 flags |= GFP_DMA;
3793 else
3794 flags |= GFP_DMA32;
3795 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003796
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003797 if (gfpflags_allow_blocking(flags)) {
3798 unsigned int count = size >> PAGE_SHIFT;
3799
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003800 page = dma_alloc_from_contiguous(dev, count, order,
3801 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003802 if (page && iommu_no_mapping(dev) &&
3803 page_to_phys(page) + size > dev->coherent_dma_mask) {
3804 dma_release_from_contiguous(dev, page, count);
3805 page = NULL;
3806 }
3807 }
3808
3809 if (!page)
3810 page = alloc_pages(flags, order);
3811 if (!page)
3812 return NULL;
3813 memset(page_address(page), 0, size);
3814
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003815 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3816 DMA_BIDIRECTIONAL,
3817 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003818 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003819 return page_address(page);
3820 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3821 __free_pages(page, order);
3822
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003823 return NULL;
3824}
3825
David Woodhouse5040a912014-03-09 16:14:00 -07003826static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003827 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003828{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003829 int order;
3830 struct page *page = virt_to_page(vaddr);
3831
3832 size = PAGE_ALIGN(size);
3833 order = get_order(size);
3834
3835 intel_unmap(dev, dma_handle, size);
3836 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3837 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003838}
3839
David Woodhouse5040a912014-03-09 16:14:00 -07003840static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003841 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003842 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003843{
Omer Peleg769530e2016-04-20 11:33:25 +03003844 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3845 unsigned long nrpages = 0;
3846 struct scatterlist *sg;
3847 int i;
3848
3849 for_each_sg(sglist, sg, nelems, i) {
3850 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3851 }
3852
3853 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003854}
3855
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003856static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003857 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003858{
3859 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003860 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003861
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003862 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003863 BUG_ON(!sg_page(sg));
Robin Murphy29a90b72017-09-28 15:14:01 +01003864 sg->dma_address = sg_phys(sg);
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003865 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003866 }
3867 return nelems;
3868}
3869
David Woodhouse5040a912014-03-09 16:14:00 -07003870static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003871 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003872{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003873 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003874 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003875 size_t size = 0;
3876 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003877 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003878 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003879 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003880 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003881 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003882
3883 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003884 if (iommu_no_mapping(dev))
3885 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003886
David Woodhouse5040a912014-03-09 16:14:00 -07003887 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003888 if (!domain)
3889 return 0;
3890
Weidong Han8c11e792008-12-08 15:29:22 +08003891 iommu = domain_get_iommu(domain);
3892
David Woodhouseb536d242009-06-28 14:49:31 +01003893 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003894 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003895
Omer Peleg2aac6302016-04-20 11:33:57 +03003896 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003897 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003898 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003899 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003900 return 0;
3901 }
3902
3903 /*
3904 * Check if DMAR supports zero-length reads on write only
3905 * mappings..
3906 */
3907 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003908 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003909 prot |= DMA_PTE_READ;
3910 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3911 prot |= DMA_PTE_WRITE;
3912
Omer Peleg2aac6302016-04-20 11:33:57 +03003913 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003914
Fenghua Yuf5329592009-08-04 15:09:37 -07003915 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003916 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003917 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003918 start_vpfn + size - 1,
3919 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003920 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003921 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003922 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003923
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003924 return nelems;
3925}
3926
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003927static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003928 .alloc = intel_alloc_coherent,
3929 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003930 .map_sg = intel_map_sg,
3931 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003932 .map_page = intel_map_page,
3933 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003934 .map_resource = intel_map_resource,
3935 .unmap_resource = intel_unmap_page,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003936 .dma_supported = dma_direct_supported,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003937};
3938
3939static inline int iommu_domain_cache_init(void)
3940{
3941 int ret = 0;
3942
3943 iommu_domain_cache = kmem_cache_create("iommu_domain",
3944 sizeof(struct dmar_domain),
3945 0,
3946 SLAB_HWCACHE_ALIGN,
3947
3948 NULL);
3949 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003950 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003951 ret = -ENOMEM;
3952 }
3953
3954 return ret;
3955}
3956
3957static inline int iommu_devinfo_cache_init(void)
3958{
3959 int ret = 0;
3960
3961 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3962 sizeof(struct device_domain_info),
3963 0,
3964 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003965 NULL);
3966 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003967 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003968 ret = -ENOMEM;
3969 }
3970
3971 return ret;
3972}
3973
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003974static int __init iommu_init_mempool(void)
3975{
3976 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003977 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003978 if (ret)
3979 return ret;
3980
3981 ret = iommu_domain_cache_init();
3982 if (ret)
3983 goto domain_error;
3984
3985 ret = iommu_devinfo_cache_init();
3986 if (!ret)
3987 return ret;
3988
3989 kmem_cache_destroy(iommu_domain_cache);
3990domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003991 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003992
3993 return -ENOMEM;
3994}
3995
3996static void __init iommu_exit_mempool(void)
3997{
3998 kmem_cache_destroy(iommu_devinfo_cache);
3999 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004000 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004001}
4002
Dan Williams556ab452010-07-23 15:47:56 -07004003static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
4004{
4005 struct dmar_drhd_unit *drhd;
4006 u32 vtbar;
4007 int rc;
4008
4009 /* We know that this device on this chipset has its own IOMMU.
4010 * If we find it under a different IOMMU, then the BIOS is lying
4011 * to us. Hope that the IOMMU for this device is actually
4012 * disabled, and it needs no translation...
4013 */
4014 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
4015 if (rc) {
4016 /* "can't" happen */
4017 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
4018 return;
4019 }
4020 vtbar &= 0xffff0000;
4021
4022 /* we know that the this iommu should be at offset 0xa000 from vtbar */
4023 drhd = dmar_find_matched_drhd_unit(pdev);
4024 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
4025 TAINT_FIRMWARE_WORKAROUND,
4026 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
4027 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
4028}
4029DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
4030
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004031static void __init init_no_remapping_devices(void)
4032{
4033 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004034 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004035 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004036
4037 for_each_drhd_unit(drhd) {
4038 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004039 for_each_active_dev_scope(drhd->devices,
4040 drhd->devices_cnt, i, dev)
4041 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004042 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004043 if (i == drhd->devices_cnt)
4044 drhd->ignored = 1;
4045 }
4046 }
4047
Jiang Liu7c919772014-01-06 14:18:18 +08004048 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004049 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004050 continue;
4051
Jiang Liub683b232014-02-19 14:07:32 +08004052 for_each_active_dev_scope(drhd->devices,
4053 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004054 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004055 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004056 if (i < drhd->devices_cnt)
4057 continue;
4058
David Woodhousec0771df2011-10-14 20:59:46 +01004059 /* This IOMMU has *only* gfx devices. Either bypass it or
4060 set the gfx_mapped flag, as appropriate */
4061 if (dmar_map_gfx) {
4062 intel_iommu_gfx_mapped = 1;
4063 } else {
4064 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08004065 for_each_active_dev_scope(drhd->devices,
4066 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004067 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004068 }
4069 }
4070}
4071
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004072#ifdef CONFIG_SUSPEND
4073static int init_iommu_hw(void)
4074{
4075 struct dmar_drhd_unit *drhd;
4076 struct intel_iommu *iommu = NULL;
4077
4078 for_each_active_iommu(iommu, drhd)
4079 if (iommu->qi)
4080 dmar_reenable_qi(iommu);
4081
Joseph Cihulab7792602011-05-03 00:08:37 -07004082 for_each_iommu(iommu, drhd) {
4083 if (drhd->ignored) {
4084 /*
4085 * we always have to disable PMRs or DMA may fail on
4086 * this device
4087 */
4088 if (force_on)
4089 iommu_disable_protect_mem_regions(iommu);
4090 continue;
4091 }
4092
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004093 iommu_flush_write_buffer(iommu);
4094
4095 iommu_set_root_entry(iommu);
4096
4097 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004098 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004099 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4100 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004101 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004102 }
4103
4104 return 0;
4105}
4106
4107static void iommu_flush_all(void)
4108{
4109 struct dmar_drhd_unit *drhd;
4110 struct intel_iommu *iommu;
4111
4112 for_each_active_iommu(iommu, drhd) {
4113 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004114 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004115 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004116 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004117 }
4118}
4119
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004120static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004121{
4122 struct dmar_drhd_unit *drhd;
4123 struct intel_iommu *iommu = NULL;
4124 unsigned long flag;
4125
4126 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004127 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004128 GFP_ATOMIC);
4129 if (!iommu->iommu_state)
4130 goto nomem;
4131 }
4132
4133 iommu_flush_all();
4134
4135 for_each_active_iommu(iommu, drhd) {
4136 iommu_disable_translation(iommu);
4137
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004138 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004139
4140 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4141 readl(iommu->reg + DMAR_FECTL_REG);
4142 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4143 readl(iommu->reg + DMAR_FEDATA_REG);
4144 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4145 readl(iommu->reg + DMAR_FEADDR_REG);
4146 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4147 readl(iommu->reg + DMAR_FEUADDR_REG);
4148
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004149 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004150 }
4151 return 0;
4152
4153nomem:
4154 for_each_active_iommu(iommu, drhd)
4155 kfree(iommu->iommu_state);
4156
4157 return -ENOMEM;
4158}
4159
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004160static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004161{
4162 struct dmar_drhd_unit *drhd;
4163 struct intel_iommu *iommu = NULL;
4164 unsigned long flag;
4165
4166 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004167 if (force_on)
4168 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4169 else
4170 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004171 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004172 }
4173
4174 for_each_active_iommu(iommu, drhd) {
4175
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004176 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004177
4178 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4179 iommu->reg + DMAR_FECTL_REG);
4180 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4181 iommu->reg + DMAR_FEDATA_REG);
4182 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4183 iommu->reg + DMAR_FEADDR_REG);
4184 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4185 iommu->reg + DMAR_FEUADDR_REG);
4186
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004187 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004188 }
4189
4190 for_each_active_iommu(iommu, drhd)
4191 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004192}
4193
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004194static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004195 .resume = iommu_resume,
4196 .suspend = iommu_suspend,
4197};
4198
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004199static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004200{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004201 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004202}
4203
4204#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004205static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004206#endif /* CONFIG_PM */
4207
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004208
Jiang Liuc2a0b532014-11-09 22:47:56 +08004209int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004210{
4211 struct acpi_dmar_reserved_memory *rmrr;
Eric Auger0659b8d2017-01-19 20:57:53 +00004212 int prot = DMA_PTE_READ|DMA_PTE_WRITE;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004213 struct dmar_rmrr_unit *rmrru;
Eric Auger0659b8d2017-01-19 20:57:53 +00004214 size_t length;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004215
4216 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4217 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004218 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004219
4220 rmrru->hdr = header;
4221 rmrr = (struct acpi_dmar_reserved_memory *)header;
4222 rmrru->base_address = rmrr->base_address;
4223 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004224
4225 length = rmrr->end_address - rmrr->base_address + 1;
4226 rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
4227 IOMMU_RESV_DIRECT);
4228 if (!rmrru->resv)
4229 goto free_rmrru;
4230
Jiang Liu2e455282014-02-19 14:07:36 +08004231 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4232 ((void *)rmrr) + rmrr->header.length,
4233 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004234 if (rmrru->devices_cnt && rmrru->devices == NULL)
4235 goto free_all;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004236
Jiang Liu2e455282014-02-19 14:07:36 +08004237 list_add(&rmrru->list, &dmar_rmrr_units);
4238
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004239 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004240free_all:
4241 kfree(rmrru->resv);
4242free_rmrru:
4243 kfree(rmrru);
4244out:
4245 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004246}
4247
Jiang Liu6b197242014-11-09 22:47:58 +08004248static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4249{
4250 struct dmar_atsr_unit *atsru;
4251 struct acpi_dmar_atsr *tmp;
4252
4253 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4254 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4255 if (atsr->segment != tmp->segment)
4256 continue;
4257 if (atsr->header.length != tmp->header.length)
4258 continue;
4259 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4260 return atsru;
4261 }
4262
4263 return NULL;
4264}
4265
4266int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004267{
4268 struct acpi_dmar_atsr *atsr;
4269 struct dmar_atsr_unit *atsru;
4270
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004271 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004272 return 0;
4273
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004274 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004275 atsru = dmar_find_atsr(atsr);
4276 if (atsru)
4277 return 0;
4278
4279 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004280 if (!atsru)
4281 return -ENOMEM;
4282
Jiang Liu6b197242014-11-09 22:47:58 +08004283 /*
4284 * If memory is allocated from slab by ACPI _DSM method, we need to
4285 * copy the memory content because the memory buffer will be freed
4286 * on return.
4287 */
4288 atsru->hdr = (void *)(atsru + 1);
4289 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004290 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004291 if (!atsru->include_all) {
4292 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4293 (void *)atsr + atsr->header.length,
4294 &atsru->devices_cnt);
4295 if (atsru->devices_cnt && atsru->devices == NULL) {
4296 kfree(atsru);
4297 return -ENOMEM;
4298 }
4299 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004300
Jiang Liu0e242612014-02-19 14:07:34 +08004301 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004302
4303 return 0;
4304}
4305
Jiang Liu9bdc5312014-01-06 14:18:27 +08004306static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4307{
4308 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4309 kfree(atsru);
4310}
4311
Jiang Liu6b197242014-11-09 22:47:58 +08004312int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4313{
4314 struct acpi_dmar_atsr *atsr;
4315 struct dmar_atsr_unit *atsru;
4316
4317 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4318 atsru = dmar_find_atsr(atsr);
4319 if (atsru) {
4320 list_del_rcu(&atsru->list);
4321 synchronize_rcu();
4322 intel_iommu_free_atsr(atsru);
4323 }
4324
4325 return 0;
4326}
4327
4328int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4329{
4330 int i;
4331 struct device *dev;
4332 struct acpi_dmar_atsr *atsr;
4333 struct dmar_atsr_unit *atsru;
4334
4335 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4336 atsru = dmar_find_atsr(atsr);
4337 if (!atsru)
4338 return 0;
4339
Linus Torvalds194dc872016-07-27 20:03:31 -07004340 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004341 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4342 i, dev)
4343 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004344 }
Jiang Liu6b197242014-11-09 22:47:58 +08004345
4346 return 0;
4347}
4348
Jiang Liuffebeb42014-11-09 22:48:02 +08004349static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4350{
4351 int sp, ret = 0;
4352 struct intel_iommu *iommu = dmaru->iommu;
4353
4354 if (g_iommus[iommu->seq_id])
4355 return 0;
4356
4357 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004358 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004359 iommu->name);
4360 return -ENXIO;
4361 }
4362 if (!ecap_sc_support(iommu->ecap) &&
4363 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004364 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004365 iommu->name);
4366 return -ENXIO;
4367 }
4368 sp = domain_update_iommu_superpage(iommu) - 1;
4369 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004370 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004371 iommu->name);
4372 return -ENXIO;
4373 }
4374
4375 /*
4376 * Disable translation if already enabled prior to OS handover.
4377 */
4378 if (iommu->gcmd & DMA_GCMD_TE)
4379 iommu_disable_translation(iommu);
4380
4381 g_iommus[iommu->seq_id] = iommu;
4382 ret = iommu_init_domains(iommu);
4383 if (ret == 0)
4384 ret = iommu_alloc_root_entry(iommu);
4385 if (ret)
4386 goto out;
4387
David Woodhouse8a94ade2015-03-24 14:54:56 +00004388#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004389 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08004390 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004391#endif
4392
Jiang Liuffebeb42014-11-09 22:48:02 +08004393 if (dmaru->ignored) {
4394 /*
4395 * we always have to disable PMRs or DMA may fail on this device
4396 */
4397 if (force_on)
4398 iommu_disable_protect_mem_regions(iommu);
4399 return 0;
4400 }
4401
4402 intel_iommu_init_qi(iommu);
4403 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004404
4405#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004406 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004407 ret = intel_svm_enable_prq(iommu);
4408 if (ret)
4409 goto disable_iommu;
4410 }
4411#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004412 ret = dmar_set_interrupt(iommu);
4413 if (ret)
4414 goto disable_iommu;
4415
4416 iommu_set_root_entry(iommu);
4417 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4418 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4419 iommu_enable_translation(iommu);
4420
Jiang Liuffebeb42014-11-09 22:48:02 +08004421 iommu_disable_protect_mem_regions(iommu);
4422 return 0;
4423
4424disable_iommu:
4425 disable_dmar_iommu(iommu);
4426out:
4427 free_dmar_iommu(iommu);
4428 return ret;
4429}
4430
Jiang Liu6b197242014-11-09 22:47:58 +08004431int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4432{
Jiang Liuffebeb42014-11-09 22:48:02 +08004433 int ret = 0;
4434 struct intel_iommu *iommu = dmaru->iommu;
4435
4436 if (!intel_iommu_enabled)
4437 return 0;
4438 if (iommu == NULL)
4439 return -EINVAL;
4440
4441 if (insert) {
4442 ret = intel_iommu_add(dmaru);
4443 } else {
4444 disable_dmar_iommu(iommu);
4445 free_dmar_iommu(iommu);
4446 }
4447
4448 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004449}
4450
Jiang Liu9bdc5312014-01-06 14:18:27 +08004451static void intel_iommu_free_dmars(void)
4452{
4453 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4454 struct dmar_atsr_unit *atsru, *atsr_n;
4455
4456 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4457 list_del(&rmrru->list);
4458 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004459 kfree(rmrru->resv);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004460 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004461 }
4462
Jiang Liu9bdc5312014-01-06 14:18:27 +08004463 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4464 list_del(&atsru->list);
4465 intel_iommu_free_atsr(atsru);
4466 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004467}
4468
4469int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4470{
Jiang Liub683b232014-02-19 14:07:32 +08004471 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004472 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004473 struct pci_dev *bridge = NULL;
4474 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004475 struct acpi_dmar_atsr *atsr;
4476 struct dmar_atsr_unit *atsru;
4477
4478 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004479 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004480 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004481 /* If it's an integrated device, allow ATS */
4482 if (!bridge)
4483 return 1;
4484 /* Connected via non-PCIe: no ATS */
4485 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004486 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004487 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004488 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004489 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004490 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004491 }
4492
Jiang Liu0e242612014-02-19 14:07:34 +08004493 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004494 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4495 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4496 if (atsr->segment != pci_domain_nr(dev->bus))
4497 continue;
4498
Jiang Liub683b232014-02-19 14:07:32 +08004499 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004500 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004501 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004502
4503 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004504 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004505 }
Jiang Liub683b232014-02-19 14:07:32 +08004506 ret = 0;
4507out:
Jiang Liu0e242612014-02-19 14:07:34 +08004508 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004509
Jiang Liub683b232014-02-19 14:07:32 +08004510 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004511}
4512
Jiang Liu59ce0512014-02-19 14:07:35 +08004513int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4514{
4515 int ret = 0;
4516 struct dmar_rmrr_unit *rmrru;
4517 struct dmar_atsr_unit *atsru;
4518 struct acpi_dmar_atsr *atsr;
4519 struct acpi_dmar_reserved_memory *rmrr;
4520
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004521 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004522 return 0;
4523
4524 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4525 rmrr = container_of(rmrru->hdr,
4526 struct acpi_dmar_reserved_memory, header);
4527 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4528 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4529 ((void *)rmrr) + rmrr->header.length,
4530 rmrr->segment, rmrru->devices,
4531 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08004532 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004533 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004534 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004535 dmar_remove_dev_scope(info, rmrr->segment,
4536 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004537 }
4538 }
4539
4540 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4541 if (atsru->include_all)
4542 continue;
4543
4544 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4545 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4546 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4547 (void *)atsr + atsr->header.length,
4548 atsr->segment, atsru->devices,
4549 atsru->devices_cnt);
4550 if (ret > 0)
4551 break;
4552 else if(ret < 0)
4553 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004554 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004555 if (dmar_remove_dev_scope(info, atsr->segment,
4556 atsru->devices, atsru->devices_cnt))
4557 break;
4558 }
4559 }
4560
4561 return 0;
4562}
4563
Fenghua Yu99dcade2009-11-11 07:23:06 -08004564/*
4565 * Here we only respond to action of unbound device from driver.
4566 *
4567 * Added device is not attached to its DMAR domain here yet. That will happen
4568 * when mapping the device to iova.
4569 */
4570static int device_notifier(struct notifier_block *nb,
4571 unsigned long action, void *data)
4572{
4573 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004574 struct dmar_domain *domain;
4575
David Woodhouse3d891942014-03-06 15:59:26 +00004576 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004577 return 0;
4578
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004579 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004580 return 0;
4581
David Woodhouse1525a292014-03-06 16:19:30 +00004582 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004583 if (!domain)
4584 return 0;
4585
Joerg Roedele6de0f82015-07-22 16:30:36 +02004586 dmar_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004587 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004588 domain_exit(domain);
Alex Williamsona97590e2011-03-04 14:52:16 -07004589
Fenghua Yu99dcade2009-11-11 07:23:06 -08004590 return 0;
4591}
4592
4593static struct notifier_block device_nb = {
4594 .notifier_call = device_notifier,
4595};
4596
Jiang Liu75f05562014-02-19 14:07:37 +08004597static int intel_iommu_memory_notifier(struct notifier_block *nb,
4598 unsigned long val, void *v)
4599{
4600 struct memory_notify *mhp = v;
4601 unsigned long long start, end;
4602 unsigned long start_vpfn, last_vpfn;
4603
4604 switch (val) {
4605 case MEM_GOING_ONLINE:
4606 start = mhp->start_pfn << PAGE_SHIFT;
4607 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4608 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004609 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004610 start, end);
4611 return NOTIFY_BAD;
4612 }
4613 break;
4614
4615 case MEM_OFFLINE:
4616 case MEM_CANCEL_ONLINE:
4617 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4618 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4619 while (start_vpfn <= last_vpfn) {
4620 struct iova *iova;
4621 struct dmar_drhd_unit *drhd;
4622 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004623 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004624
4625 iova = find_iova(&si_domain->iovad, start_vpfn);
4626 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004627 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004628 start_vpfn);
4629 break;
4630 }
4631
4632 iova = split_and_remove_iova(&si_domain->iovad, iova,
4633 start_vpfn, last_vpfn);
4634 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004635 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004636 start_vpfn, last_vpfn);
4637 return NOTIFY_BAD;
4638 }
4639
David Woodhouseea8ea462014-03-05 17:09:32 +00004640 freelist = domain_unmap(si_domain, iova->pfn_lo,
4641 iova->pfn_hi);
4642
Jiang Liu75f05562014-02-19 14:07:37 +08004643 rcu_read_lock();
4644 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004645 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004646 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004647 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004648 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004649 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004650
4651 start_vpfn = iova->pfn_hi + 1;
4652 free_iova_mem(iova);
4653 }
4654 break;
4655 }
4656
4657 return NOTIFY_OK;
4658}
4659
4660static struct notifier_block intel_iommu_memory_nb = {
4661 .notifier_call = intel_iommu_memory_notifier,
4662 .priority = 0
4663};
4664
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004665static void free_all_cpu_cached_iovas(unsigned int cpu)
4666{
4667 int i;
4668
4669 for (i = 0; i < g_num_of_iommus; i++) {
4670 struct intel_iommu *iommu = g_iommus[i];
4671 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004672 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004673
4674 if (!iommu)
4675 continue;
4676
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004677 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004678 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004679
4680 if (!domain)
4681 continue;
4682 free_cpu_cached_iovas(cpu, &domain->iovad);
4683 }
4684 }
4685}
4686
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004687static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004688{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004689 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004690 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004691}
4692
Joerg Roedel161b28a2017-03-28 17:04:52 +02004693static void intel_disable_iommus(void)
4694{
4695 struct intel_iommu *iommu = NULL;
4696 struct dmar_drhd_unit *drhd;
4697
4698 for_each_iommu(iommu, drhd)
4699 iommu_disable_translation(iommu);
4700}
4701
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004702static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4703{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004704 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4705
4706 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004707}
4708
Alex Williamsona5459cf2014-06-12 16:12:31 -06004709static ssize_t intel_iommu_show_version(struct device *dev,
4710 struct device_attribute *attr,
4711 char *buf)
4712{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004713 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004714 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4715 return sprintf(buf, "%d:%d\n",
4716 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4717}
4718static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4719
4720static ssize_t intel_iommu_show_address(struct device *dev,
4721 struct device_attribute *attr,
4722 char *buf)
4723{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004724 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004725 return sprintf(buf, "%llx\n", iommu->reg_phys);
4726}
4727static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4728
4729static ssize_t intel_iommu_show_cap(struct device *dev,
4730 struct device_attribute *attr,
4731 char *buf)
4732{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004733 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004734 return sprintf(buf, "%llx\n", iommu->cap);
4735}
4736static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4737
4738static ssize_t intel_iommu_show_ecap(struct device *dev,
4739 struct device_attribute *attr,
4740 char *buf)
4741{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004742 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004743 return sprintf(buf, "%llx\n", iommu->ecap);
4744}
4745static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4746
Alex Williamson2238c082015-07-14 15:24:53 -06004747static ssize_t intel_iommu_show_ndoms(struct device *dev,
4748 struct device_attribute *attr,
4749 char *buf)
4750{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004751 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004752 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4753}
4754static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4755
4756static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4757 struct device_attribute *attr,
4758 char *buf)
4759{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004760 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004761 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4762 cap_ndoms(iommu->cap)));
4763}
4764static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4765
Alex Williamsona5459cf2014-06-12 16:12:31 -06004766static struct attribute *intel_iommu_attrs[] = {
4767 &dev_attr_version.attr,
4768 &dev_attr_address.attr,
4769 &dev_attr_cap.attr,
4770 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004771 &dev_attr_domains_supported.attr,
4772 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004773 NULL,
4774};
4775
4776static struct attribute_group intel_iommu_group = {
4777 .name = "intel-iommu",
4778 .attrs = intel_iommu_attrs,
4779};
4780
4781const struct attribute_group *intel_iommu_groups[] = {
4782 &intel_iommu_group,
4783 NULL,
4784};
4785
Lu Baolu89a60792018-10-23 15:45:01 +08004786static int __init platform_optin_force_iommu(void)
4787{
4788 struct pci_dev *pdev = NULL;
4789 bool has_untrusted_dev = false;
4790
4791 if (!dmar_platform_optin() || no_platform_optin)
4792 return 0;
4793
4794 for_each_pci_dev(pdev) {
4795 if (pdev->untrusted) {
4796 has_untrusted_dev = true;
4797 break;
4798 }
4799 }
4800
4801 if (!has_untrusted_dev)
4802 return 0;
4803
4804 if (no_iommu || dmar_disabled)
4805 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4806
4807 /*
4808 * If Intel-IOMMU is disabled by default, we will apply identity
4809 * map for all devices except those marked as being untrusted.
4810 */
4811 if (dmar_disabled)
4812 iommu_identity_mapping |= IDENTMAP_ALL;
4813
4814 dmar_disabled = 0;
4815#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
4816 swiotlb = 0;
4817#endif
4818 no_iommu = 0;
4819
4820 return 1;
4821}
4822
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004823int __init intel_iommu_init(void)
4824{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004825 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004826 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004827 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004828
Lu Baolu89a60792018-10-23 15:45:01 +08004829 /*
4830 * Intel IOMMU is required for a TXT/tboot launch or platform
4831 * opt in, so enforce that.
4832 */
4833 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004834
Jiang Liu3a5670e2014-02-19 14:07:33 +08004835 if (iommu_init_mempool()) {
4836 if (force_on)
4837 panic("tboot: Failed to initialize iommu memory\n");
4838 return -ENOMEM;
4839 }
4840
4841 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004842 if (dmar_table_init()) {
4843 if (force_on)
4844 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004845 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004846 }
4847
Suresh Siddhac2c72862011-08-23 17:05:19 -07004848 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004849 if (force_on)
4850 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004851 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004852 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004853
Joerg Roedelec154bf2017-10-06 15:00:53 +02004854 up_write(&dmar_global_lock);
4855
4856 /*
4857 * The bus notifier takes the dmar_global_lock, so lockdep will
4858 * complain later when we register it under the lock.
4859 */
4860 dmar_register_bus_notifier();
4861
4862 down_write(&dmar_global_lock);
4863
Joerg Roedel161b28a2017-03-28 17:04:52 +02004864 if (no_iommu || dmar_disabled) {
4865 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004866 * We exit the function here to ensure IOMMU's remapping and
4867 * mempool aren't setup, which means that the IOMMU's PMRs
4868 * won't be disabled via the call to init_dmars(). So disable
4869 * it explicitly here. The PMRs were setup by tboot prior to
4870 * calling SENTER, but the kernel is expected to reset/tear
4871 * down the PMRs.
4872 */
4873 if (intel_iommu_tboot_noforce) {
4874 for_each_iommu(iommu, drhd)
4875 iommu_disable_protect_mem_regions(iommu);
4876 }
4877
4878 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004879 * Make sure the IOMMUs are switched off, even when we
4880 * boot into a kexec kernel and the previous kernel left
4881 * them enabled
4882 */
4883 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004884 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004885 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004886
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004887 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004888 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004889
4890 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004891 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004892
Joseph Cihula51a63e62011-03-21 11:04:24 -07004893 if (dmar_init_reserved_ranges()) {
4894 if (force_on)
4895 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004896 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004897 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004898
4899 init_no_remapping_devices();
4900
Joseph Cihulab7792602011-05-03 00:08:37 -07004901 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004902 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004903 if (force_on)
4904 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004905 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004906 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004907 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004908 up_write(&dmar_global_lock);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004909 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004910
Christoph Hellwig4fac8072017-12-24 13:57:08 +01004911#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004912 swiotlb = 0;
4913#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004914 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004915
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004916 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004917
Joerg Roedel39ab9552017-02-01 16:56:46 +01004918 for_each_active_iommu(iommu, drhd) {
4919 iommu_device_sysfs_add(&iommu->iommu, NULL,
4920 intel_iommu_groups,
4921 "%s", iommu->name);
4922 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4923 iommu_device_register(&iommu->iommu);
4924 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06004925
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004926 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004927 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004928 if (si_domain && !hw_pass_through)
4929 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004930 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4931 intel_iommu_cpu_dead);
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004932 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07004933 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004934
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004935 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004936
4937out_free_reserved_range:
4938 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004939out_free_dmar:
4940 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004941 up_write(&dmar_global_lock);
4942 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004943 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004944}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004945
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004946static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004947{
4948 struct intel_iommu *iommu = opaque;
4949
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004950 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004951 return 0;
4952}
4953
4954/*
4955 * NB - intel-iommu lacks any sort of reference counting for the users of
4956 * dependent devices. If multiple endpoints have intersecting dependent
4957 * devices, unbinding the driver from any one of them will possibly leave
4958 * the others unable to operate.
4959 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004960static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004961{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004962 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004963 return;
4964
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004965 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004966}
4967
Joerg Roedel127c7612015-07-23 17:44:46 +02004968static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004969{
Weidong Hanc7151a82008-12-08 22:51:37 +08004970 struct intel_iommu *iommu;
4971 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004972
Joerg Roedel55d94042015-07-22 16:50:40 +02004973 assert_spin_locked(&device_domain_lock);
4974
Joerg Roedelb608ac32015-07-21 18:19:08 +02004975 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004976 return;
4977
Joerg Roedel127c7612015-07-23 17:44:46 +02004978 iommu = info->iommu;
4979
4980 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08004981 if (dev_is_pci(info->dev) && sm_supported(iommu))
4982 intel_pasid_tear_down_entry(iommu, info->dev,
4983 PASID_RID2PASID);
4984
Joerg Roedel127c7612015-07-23 17:44:46 +02004985 iommu_disable_dev_iotlb(info);
4986 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08004987 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02004988 }
4989
Joerg Roedelb608ac32015-07-21 18:19:08 +02004990 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004991
Joerg Roedeld160aca2015-07-22 11:52:53 +02004992 spin_lock_irqsave(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004993 domain_detach_iommu(info->domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004994 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004995
4996 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004997}
4998
Joerg Roedel55d94042015-07-22 16:50:40 +02004999static void dmar_remove_one_dev_info(struct dmar_domain *domain,
5000 struct device *dev)
5001{
Joerg Roedel127c7612015-07-23 17:44:46 +02005002 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02005003 unsigned long flags;
5004
Weidong Hanc7151a82008-12-08 22:51:37 +08005005 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005006 info = dev->archdata.iommu;
5007 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005008 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005009}
5010
5011static int md_domain_init(struct dmar_domain *domain, int guest_width)
5012{
5013 int adjust_width;
5014
Zhen Leiaa3ac942017-09-21 16:52:45 +01005015 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005016 domain_reserve_special_ranges(domain);
5017
5018 /* calculate AGAW */
5019 domain->gaw = guest_width;
5020 adjust_width = guestwidth_to_adjustwidth(guest_width);
5021 domain->agaw = width_to_agaw(adjust_width);
5022
Weidong Han5e98c4b2008-12-08 23:03:27 +08005023 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08005024 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01005025 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005026 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08005027
5028 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07005029 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005030 if (!domain->pgd)
5031 return -ENOMEM;
5032 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5033 return 0;
5034}
5035
Joerg Roedel00a77de2015-03-26 13:43:08 +01005036static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005037{
Joerg Roedel5d450802008-12-03 14:52:32 +01005038 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005039 struct iommu_domain *domain;
5040
5041 if (type != IOMMU_DOMAIN_UNMANAGED)
5042 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005043
Jiang Liuab8dfe22014-07-11 14:19:27 +08005044 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01005045 if (!dmar_domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005046 pr_err("Can't allocate dmar_domain\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01005047 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005048 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07005049 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005050 pr_err("Domain initialization failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08005051 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01005052 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005053 }
Allen Kay8140a952011-10-14 12:32:17 -07005054 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005055
Joerg Roedel00a77de2015-03-26 13:43:08 +01005056 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01005057 domain->geometry.aperture_start = 0;
5058 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5059 domain->geometry.force_aperture = true;
5060
Joerg Roedel00a77de2015-03-26 13:43:08 +01005061 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03005062}
Kay, Allen M38717942008-09-09 18:37:29 +03005063
Joerg Roedel00a77de2015-03-26 13:43:08 +01005064static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005065{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005066 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005067}
Kay, Allen M38717942008-09-09 18:37:29 +03005068
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005069static int intel_iommu_attach_device(struct iommu_domain *domain,
5070 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005071{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005072 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005073 struct intel_iommu *iommu;
5074 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005075 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005076
Alex Williamsonc875d2c2014-07-03 09:57:02 -06005077 if (device_is_rmrr_locked(dev)) {
5078 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5079 return -EPERM;
5080 }
5081
David Woodhouse7207d8f2014-03-09 16:31:06 -07005082 /* normally dev is not mapped */
5083 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005084 struct dmar_domain *old_domain;
5085
David Woodhouse1525a292014-03-06 16:19:30 +00005086 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005087 if (old_domain) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02005088 rcu_read_lock();
Joerg Roedelde7e8882015-07-22 11:58:07 +02005089 dmar_remove_one_dev_info(old_domain, dev);
Joerg Roedeld160aca2015-07-22 11:52:53 +02005090 rcu_read_unlock();
Joerg Roedel62c22162014-12-09 12:56:45 +01005091
5092 if (!domain_type_is_vm_or_si(old_domain) &&
5093 list_empty(&old_domain->devices))
5094 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005095 }
5096 }
5097
David Woodhouse156baca2014-03-09 14:00:57 -07005098 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005099 if (!iommu)
5100 return -ENODEV;
5101
5102 /* check if this iommu agaw is sufficient for max mapped address */
5103 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005104 if (addr_width > cap_mgaw(iommu->cap))
5105 addr_width = cap_mgaw(iommu->cap);
5106
5107 if (dmar_domain->max_addr > (1LL << addr_width)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005108 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005109 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01005110 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005111 return -EFAULT;
5112 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005113 dmar_domain->gaw = addr_width;
5114
5115 /*
5116 * Knock out extra levels of page tables if necessary
5117 */
5118 while (iommu->agaw < dmar_domain->agaw) {
5119 struct dma_pte *pte;
5120
5121 pte = dmar_domain->pgd;
5122 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005123 dmar_domain->pgd = (struct dma_pte *)
5124 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005125 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005126 }
5127 dmar_domain->agaw--;
5128 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005129
Joerg Roedel28ccce02015-07-21 14:45:31 +02005130 return domain_add_dev_info(dmar_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005131}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005132
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005133static void intel_iommu_detach_device(struct iommu_domain *domain,
5134 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005135{
Joerg Roedele6de0f82015-07-22 16:30:36 +02005136 dmar_remove_one_dev_info(to_dmar_domain(domain), dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005137}
Kay, Allen M38717942008-09-09 18:37:29 +03005138
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005139static int intel_iommu_map(struct iommu_domain *domain,
5140 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005141 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03005142{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005143 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005144 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005145 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005146 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005147
Joerg Roedeldde57a22008-12-03 15:04:09 +01005148 if (iommu_prot & IOMMU_READ)
5149 prot |= DMA_PTE_READ;
5150 if (iommu_prot & IOMMU_WRITE)
5151 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005152 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5153 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005154
David Woodhouse163cc522009-06-28 00:51:17 +01005155 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005156 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005157 u64 end;
5158
5159 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005160 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005161 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005162 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005163 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005164 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005165 return -EFAULT;
5166 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005167 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005168 }
David Woodhousead051222009-06-28 14:22:28 +01005169 /* Round up size to next multiple of PAGE_SIZE, if it and
5170 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005171 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005172 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5173 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005174 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005175}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005176
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005177static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00005178 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005179{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005180 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005181 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005182 unsigned long start_pfn, last_pfn;
5183 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005184 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005185
David Woodhouse5cf0a762014-03-19 16:07:49 +00005186 /* Cope with horrid API which requires us to unmap more than the
5187 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005188 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005189
5190 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5191 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5192
David Woodhouseea8ea462014-03-05 17:09:32 +00005193 start_pfn = iova >> VTD_PAGE_SHIFT;
5194 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5195
5196 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5197
5198 npages = last_pfn - start_pfn + 1;
5199
Shaokun Zhangf746a022018-03-22 18:18:06 +08005200 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005201 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5202 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005203
5204 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005205
David Woodhouse163cc522009-06-28 00:51:17 +01005206 if (dmar_domain->max_addr == iova + size)
5207 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005208
David Woodhouse5cf0a762014-03-19 16:07:49 +00005209 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005210}
Kay, Allen M38717942008-09-09 18:37:29 +03005211
Joerg Roedeld14d6572008-12-03 15:06:57 +01005212static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305213 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005214{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005215 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005216 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005217 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005218 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005219
David Woodhouse5cf0a762014-03-19 16:07:49 +00005220 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005221 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005222 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005223
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005224 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005225}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005226
Joerg Roedel5d587b82014-09-05 10:50:45 +02005227static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005228{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005229 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005230 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005231 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005232 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005233
Joerg Roedel5d587b82014-09-05 10:50:45 +02005234 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005235}
5236
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005237static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005238{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005239 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005240 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005241 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005242
Alex Williamsona5459cf2014-06-12 16:12:31 -06005243 iommu = device_to_iommu(dev, &bus, &devfn);
5244 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005245 return -ENODEV;
5246
Joerg Roedele3d10af2017-02-01 17:23:22 +01005247 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005248
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005249 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005250
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005251 if (IS_ERR(group))
5252 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005253
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005254 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005255 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005256}
5257
5258static void intel_iommu_remove_device(struct device *dev)
5259{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005260 struct intel_iommu *iommu;
5261 u8 bus, devfn;
5262
5263 iommu = device_to_iommu(dev, &bus, &devfn);
5264 if (!iommu)
5265 return;
5266
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005267 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005268
Joerg Roedele3d10af2017-02-01 17:23:22 +01005269 iommu_device_unlink(&iommu->iommu, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005270}
5271
Eric Auger0659b8d2017-01-19 20:57:53 +00005272static void intel_iommu_get_resv_regions(struct device *device,
5273 struct list_head *head)
5274{
5275 struct iommu_resv_region *reg;
5276 struct dmar_rmrr_unit *rmrr;
5277 struct device *i_dev;
5278 int i;
5279
5280 rcu_read_lock();
5281 for_each_rmrr_units(rmrr) {
5282 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5283 i, i_dev) {
5284 if (i_dev != device)
5285 continue;
5286
5287 list_add_tail(&rmrr->resv->list, head);
5288 }
5289 }
5290 rcu_read_unlock();
5291
5292 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5293 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005294 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005295 if (!reg)
5296 return;
5297 list_add_tail(&reg->list, head);
5298}
5299
5300static void intel_iommu_put_resv_regions(struct device *dev,
5301 struct list_head *head)
5302{
5303 struct iommu_resv_region *entry, *next;
5304
5305 list_for_each_entry_safe(entry, next, head, list) {
5306 if (entry->type == IOMMU_RESV_RESERVED)
5307 kfree(entry);
5308 }
Kay, Allen M38717942008-09-09 18:37:29 +03005309}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005310
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005311#ifdef CONFIG_INTEL_IOMMU_SVM
5312int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
5313{
5314 struct device_domain_info *info;
5315 struct context_entry *context;
5316 struct dmar_domain *domain;
5317 unsigned long flags;
5318 u64 ctx_lo;
5319 int ret;
5320
5321 domain = get_valid_domain_for_dev(sdev->dev);
5322 if (!domain)
5323 return -EINVAL;
5324
5325 spin_lock_irqsave(&device_domain_lock, flags);
5326 spin_lock(&iommu->lock);
5327
5328 ret = -EINVAL;
5329 info = sdev->dev->archdata.iommu;
5330 if (!info || !info->pasid_supported)
5331 goto out;
5332
5333 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5334 if (WARN_ON(!context))
5335 goto out;
5336
5337 ctx_lo = context[0].lo;
5338
5339 sdev->did = domain->iommu_did[iommu->seq_id];
5340 sdev->sid = PCI_DEVID(info->bus, info->devfn);
5341
5342 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005343 ctx_lo |= CONTEXT_PASIDE;
5344 context[0].lo = ctx_lo;
5345 wmb();
5346 iommu->flush.flush_context(iommu, sdev->did, sdev->sid,
5347 DMA_CCMD_MASK_NOBIT,
5348 DMA_CCMD_DEVICE_INVL);
5349 }
5350
5351 /* Enable PASID support in the device, if it wasn't already */
5352 if (!info->pasid_enabled)
5353 iommu_enable_dev_iotlb(info);
5354
5355 if (info->ats_enabled) {
5356 sdev->dev_iotlb = 1;
5357 sdev->qdep = info->ats_qdep;
5358 if (sdev->qdep >= QI_DEV_EIOTLB_MAX_INVS)
5359 sdev->qdep = 0;
5360 }
5361 ret = 0;
5362
5363 out:
5364 spin_unlock(&iommu->lock);
5365 spin_unlock_irqrestore(&device_domain_lock, flags);
5366
5367 return ret;
5368}
5369
5370struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5371{
5372 struct intel_iommu *iommu;
5373 u8 bus, devfn;
5374
5375 if (iommu_dummy(dev)) {
5376 dev_warn(dev,
5377 "No IOMMU translation for device; cannot enable SVM\n");
5378 return NULL;
5379 }
5380
5381 iommu = device_to_iommu(dev, &bus, &devfn);
5382 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07005383 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005384 return NULL;
5385 }
5386
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005387 return iommu;
5388}
5389#endif /* CONFIG_INTEL_IOMMU_SVM */
5390
Joerg Roedelb0119e82017-02-01 13:23:08 +01005391const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00005392 .capable = intel_iommu_capable,
5393 .domain_alloc = intel_iommu_domain_alloc,
5394 .domain_free = intel_iommu_domain_free,
5395 .attach_dev = intel_iommu_attach_device,
5396 .detach_dev = intel_iommu_detach_device,
5397 .map = intel_iommu_map,
5398 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00005399 .iova_to_phys = intel_iommu_iova_to_phys,
5400 .add_device = intel_iommu_add_device,
5401 .remove_device = intel_iommu_remove_device,
5402 .get_resv_regions = intel_iommu_get_resv_regions,
5403 .put_resv_regions = intel_iommu_put_resv_regions,
5404 .device_group = pci_device_group,
5405 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005406};
David Woodhouse9af88142009-02-13 23:18:03 +00005407
Daniel Vetter94526182013-01-20 23:50:13 +01005408static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
5409{
5410 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005411 pr_info("Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01005412 dmar_map_gfx = 0;
5413}
5414
5415DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
5416DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
5417DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
5418DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
5419DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
5420DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
5421DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
5422
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005423static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00005424{
5425 /*
5426 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01005427 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00005428 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005429 pr_info("Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00005430 rwbf_quirk = 1;
5431}
5432
5433DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01005434DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
5435DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
5436DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
5437DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
5438DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
5439DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07005440
Adam Jacksoneecfd572010-08-25 21:17:34 +01005441#define GGC 0x52
5442#define GGC_MEMORY_SIZE_MASK (0xf << 8)
5443#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
5444#define GGC_MEMORY_SIZE_1M (0x1 << 8)
5445#define GGC_MEMORY_SIZE_2M (0x3 << 8)
5446#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
5447#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
5448#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
5449#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
5450
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005451static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01005452{
5453 unsigned short ggc;
5454
Adam Jacksoneecfd572010-08-25 21:17:34 +01005455 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01005456 return;
5457
Adam Jacksoneecfd572010-08-25 21:17:34 +01005458 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005459 pr_info("BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01005460 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005461 } else if (dmar_map_gfx) {
5462 /* we have to ensure the gfx device is idle before we flush */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005463 pr_info("Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005464 intel_iommu_strict = 1;
5465 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01005466}
5467DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
5468DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
5469DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
5470DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
5471
David Woodhousee0fc7e02009-09-30 09:12:17 -07005472/* On Tylersburg chipsets, some BIOSes have been known to enable the
5473 ISOCH DMAR unit for the Azalia sound device, but not give it any
5474 TLB entries, which causes it to deadlock. Check for that. We do
5475 this in a function called from init_dmars(), instead of in a PCI
5476 quirk, because we don't want to print the obnoxious "BIOS broken"
5477 message if VT-d is actually disabled.
5478*/
5479static void __init check_tylersburg_isoch(void)
5480{
5481 struct pci_dev *pdev;
5482 uint32_t vtisochctrl;
5483
5484 /* If there's no Azalia in the system anyway, forget it. */
5485 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
5486 if (!pdev)
5487 return;
5488 pci_dev_put(pdev);
5489
5490 /* System Management Registers. Might be hidden, in which case
5491 we can't do the sanity check. But that's OK, because the
5492 known-broken BIOSes _don't_ actually hide it, so far. */
5493 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
5494 if (!pdev)
5495 return;
5496
5497 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
5498 pci_dev_put(pdev);
5499 return;
5500 }
5501
5502 pci_dev_put(pdev);
5503
5504 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
5505 if (vtisochctrl & 1)
5506 return;
5507
5508 /* Drop all bits other than the number of TLB entries */
5509 vtisochctrl &= 0x1c;
5510
5511 /* If we have the recommended number of TLB entries (16), fine. */
5512 if (vtisochctrl == 0x10)
5513 return;
5514
5515 /* Zero TLB entries? You get to ride the short bus to school. */
5516 if (!vtisochctrl) {
5517 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5518 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5519 dmi_get_system_info(DMI_BIOS_VENDOR),
5520 dmi_get_system_info(DMI_BIOS_VERSION),
5521 dmi_get_system_info(DMI_PRODUCT_VERSION));
5522 iommu_identity_mapping |= IDENTMAP_AZALIA;
5523 return;
5524 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005525
5526 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005527 vtisochctrl);
5528}