blob: 78188bf7e90d7a42f6dbc263f2e412c77de92e0c [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 Baolu8950dcd2019-01-24 10:31:32 +0800366static int intel_iommu_sm;
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 Baolu8950dcd2019-01-24 10:31:32 +0800459 } else if (!strncmp(str, "sm_on", 5)) {
460 pr_info("Intel-IOMMU: scalable mode supported\n");
461 intel_iommu_sm = 1;
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
Christoph Hellwig964f2312018-11-21 19:32:03 +01003652static dma_addr_t __intel_map_page(struct device *dev, struct page *page,
3653 unsigned long offset, size_t size, int dir,
3654 u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003655{
Christoph Hellwig964f2312018-11-21 19:32:03 +01003656 phys_addr_t paddr = page_to_phys(page) + offset;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003657 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003658 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003659 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003660 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003661 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003662 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003663 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003664
3665 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003666
David Woodhouse5040a912014-03-09 16:14:00 -07003667 if (iommu_no_mapping(dev))
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003668 return paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003669
David Woodhouse5040a912014-03-09 16:14:00 -07003670 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003671 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003672 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003673
Weidong Han8c11e792008-12-08 15:29:22 +08003674 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003675 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003676
Omer Peleg2aac6302016-04-20 11:33:57 +03003677 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3678 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003679 goto error;
3680
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003681 /*
3682 * Check if DMAR supports zero-length reads on write only
3683 * mappings..
3684 */
3685 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003686 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003687 prot |= DMA_PTE_READ;
3688 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3689 prot |= DMA_PTE_WRITE;
3690 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003691 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003692 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003693 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003694 * is not a big problem
3695 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003696 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003697 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003698 if (ret)
3699 goto error;
3700
Omer Peleg2aac6302016-04-20 11:33:57 +03003701 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003702 start_paddr += paddr & ~PAGE_MASK;
3703 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003704
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003705error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003706 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003707 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003708 pr_err("Device %s request: %zx@%llx dir %d --- failed\n",
David Woodhouse5040a912014-03-09 16:14:00 -07003709 dev_name(dev), size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003710 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003711}
3712
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003713static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3714 unsigned long offset, size_t size,
3715 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003716 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003717{
Christoph Hellwig964f2312018-11-21 19:32:03 +01003718 return __intel_map_page(dev, page, offset, size, dir, *dev->dma_mask);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003719}
3720
Omer Peleg769530e2016-04-20 11:33:25 +03003721static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003722{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003723 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003724 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003725 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003726 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003727 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003728 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003729
David Woodhouse73676832009-07-04 14:08:36 +01003730 if (iommu_no_mapping(dev))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003731 return;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003732
David Woodhouse1525a292014-03-06 16:19:30 +00003733 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003734 BUG_ON(!domain);
3735
Weidong Han8c11e792008-12-08 15:29:22 +08003736 iommu = domain_get_iommu(domain);
3737
Omer Peleg2aac6302016-04-20 11:33:57 +03003738 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003739
Omer Peleg769530e2016-04-20 11:33:25 +03003740 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003741 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003742 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003743
David Woodhoused794dc92009-06-28 00:27:49 +01003744 pr_debug("Device %s unmapping: pfn %lx-%lx\n",
David Woodhouse207e3592014-03-09 16:12:32 -07003745 dev_name(dev), start_pfn, last_pfn);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003746
David Woodhouseea8ea462014-03-05 17:09:32 +00003747 freelist = domain_unmap(domain, start_pfn, last_pfn);
David Woodhoused794dc92009-06-28 00:27:49 +01003748
mark gross5e0d2a62008-03-04 15:22:08 -08003749 if (intel_iommu_strict) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003750 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003751 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003752 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003753 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003754 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003755 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003756 queue_iova(&domain->iovad, iova_pfn, nrpages,
3757 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003758 /*
3759 * queue up the release of the unmap to save the 1/6th of the
3760 * cpu used up by the iotlb flush operation...
3761 */
mark gross5e0d2a62008-03-04 15:22:08 -08003762 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003763}
3764
Jiang Liud41a4ad2014-07-11 14:19:34 +08003765static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3766 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003767 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003768{
Omer Peleg769530e2016-04-20 11:33:25 +03003769 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003770}
3771
David Woodhouse5040a912014-03-09 16:14:00 -07003772static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003773 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003774 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003775{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003776 struct page *page = NULL;
3777 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003778
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003779 size = PAGE_ALIGN(size);
3780 order = get_order(size);
Alex Williamsone8bb9102009-11-04 15:59:34 -07003781
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003782 if (!iommu_no_mapping(dev))
3783 flags &= ~(GFP_DMA | GFP_DMA32);
3784 else if (dev->coherent_dma_mask < dma_get_required_mask(dev)) {
3785 if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
3786 flags |= GFP_DMA;
3787 else
3788 flags |= GFP_DMA32;
3789 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003790
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003791 if (gfpflags_allow_blocking(flags)) {
3792 unsigned int count = size >> PAGE_SHIFT;
3793
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003794 page = dma_alloc_from_contiguous(dev, count, order,
3795 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003796 if (page && iommu_no_mapping(dev) &&
3797 page_to_phys(page) + size > dev->coherent_dma_mask) {
3798 dma_release_from_contiguous(dev, page, count);
3799 page = NULL;
3800 }
3801 }
3802
3803 if (!page)
3804 page = alloc_pages(flags, order);
3805 if (!page)
3806 return NULL;
3807 memset(page_address(page), 0, size);
3808
Christoph Hellwig964f2312018-11-21 19:32:03 +01003809 *dma_handle = __intel_map_page(dev, page, 0, size, DMA_BIDIRECTIONAL,
3810 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003811 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003812 return page_address(page);
3813 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3814 __free_pages(page, order);
3815
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003816 return NULL;
3817}
3818
David Woodhouse5040a912014-03-09 16:14:00 -07003819static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003820 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003821{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003822 int order;
3823 struct page *page = virt_to_page(vaddr);
3824
3825 size = PAGE_ALIGN(size);
3826 order = get_order(size);
3827
3828 intel_unmap(dev, dma_handle, size);
3829 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3830 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003831}
3832
David Woodhouse5040a912014-03-09 16:14:00 -07003833static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003834 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003835 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003836{
Omer Peleg769530e2016-04-20 11:33:25 +03003837 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3838 unsigned long nrpages = 0;
3839 struct scatterlist *sg;
3840 int i;
3841
3842 for_each_sg(sglist, sg, nelems, i) {
3843 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3844 }
3845
3846 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003847}
3848
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003849static int intel_nontranslate_map_sg(struct device *hddev,
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003850 struct scatterlist *sglist, int nelems, int dir)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003851{
3852 int i;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003853 struct scatterlist *sg;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003854
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003855 for_each_sg(sglist, sg, nelems, i) {
FUJITA Tomonori12d4d402007-10-23 09:32:25 +02003856 BUG_ON(!sg_page(sg));
Robin Murphy29a90b72017-09-28 15:14:01 +01003857 sg->dma_address = sg_phys(sg);
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003858 sg->dma_length = sg->length;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003859 }
3860 return nelems;
3861}
3862
David Woodhouse5040a912014-03-09 16:14:00 -07003863static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003864 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003865{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003866 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003867 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003868 size_t size = 0;
3869 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003870 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003871 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003872 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003873 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003874 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003875
3876 BUG_ON(dir == DMA_NONE);
David Woodhouse5040a912014-03-09 16:14:00 -07003877 if (iommu_no_mapping(dev))
3878 return intel_nontranslate_map_sg(dev, sglist, nelems, dir);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003879
David Woodhouse5040a912014-03-09 16:14:00 -07003880 domain = get_valid_domain_for_dev(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003881 if (!domain)
3882 return 0;
3883
Weidong Han8c11e792008-12-08 15:29:22 +08003884 iommu = domain_get_iommu(domain);
3885
David Woodhouseb536d242009-06-28 14:49:31 +01003886 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003887 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003888
Omer Peleg2aac6302016-04-20 11:33:57 +03003889 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003890 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003891 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003892 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003893 return 0;
3894 }
3895
3896 /*
3897 * Check if DMAR supports zero-length reads on write only
3898 * mappings..
3899 */
3900 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003901 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003902 prot |= DMA_PTE_READ;
3903 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3904 prot |= DMA_PTE_WRITE;
3905
Omer Peleg2aac6302016-04-20 11:33:57 +03003906 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003907
Fenghua Yuf5329592009-08-04 15:09:37 -07003908 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003909 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003910 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003911 start_vpfn + size - 1,
3912 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003913 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003914 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003915 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003916
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003917 return nelems;
3918}
3919
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003920static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003921 .alloc = intel_alloc_coherent,
3922 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003923 .map_sg = intel_map_sg,
3924 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003925 .map_page = intel_map_page,
3926 .unmap_page = intel_unmap_page,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003927 .dma_supported = dma_direct_supported,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003928};
3929
3930static inline int iommu_domain_cache_init(void)
3931{
3932 int ret = 0;
3933
3934 iommu_domain_cache = kmem_cache_create("iommu_domain",
3935 sizeof(struct dmar_domain),
3936 0,
3937 SLAB_HWCACHE_ALIGN,
3938
3939 NULL);
3940 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003941 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003942 ret = -ENOMEM;
3943 }
3944
3945 return ret;
3946}
3947
3948static inline int iommu_devinfo_cache_init(void)
3949{
3950 int ret = 0;
3951
3952 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
3953 sizeof(struct device_domain_info),
3954 0,
3955 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003956 NULL);
3957 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003958 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003959 ret = -ENOMEM;
3960 }
3961
3962 return ret;
3963}
3964
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003965static int __init iommu_init_mempool(void)
3966{
3967 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003968 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003969 if (ret)
3970 return ret;
3971
3972 ret = iommu_domain_cache_init();
3973 if (ret)
3974 goto domain_error;
3975
3976 ret = iommu_devinfo_cache_init();
3977 if (!ret)
3978 return ret;
3979
3980 kmem_cache_destroy(iommu_domain_cache);
3981domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003982 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003983
3984 return -ENOMEM;
3985}
3986
3987static void __init iommu_exit_mempool(void)
3988{
3989 kmem_cache_destroy(iommu_devinfo_cache);
3990 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03003991 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003992}
3993
Dan Williams556ab452010-07-23 15:47:56 -07003994static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
3995{
3996 struct dmar_drhd_unit *drhd;
3997 u32 vtbar;
3998 int rc;
3999
4000 /* We know that this device on this chipset has its own IOMMU.
4001 * If we find it under a different IOMMU, then the BIOS is lying
4002 * to us. Hope that the IOMMU for this device is actually
4003 * disabled, and it needs no translation...
4004 */
4005 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
4006 if (rc) {
4007 /* "can't" happen */
4008 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
4009 return;
4010 }
4011 vtbar &= 0xffff0000;
4012
4013 /* we know that the this iommu should be at offset 0xa000 from vtbar */
4014 drhd = dmar_find_matched_drhd_unit(pdev);
4015 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
4016 TAINT_FIRMWARE_WORKAROUND,
4017 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
4018 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
4019}
4020DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
4021
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004022static void __init init_no_remapping_devices(void)
4023{
4024 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004025 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004026 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004027
4028 for_each_drhd_unit(drhd) {
4029 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004030 for_each_active_dev_scope(drhd->devices,
4031 drhd->devices_cnt, i, dev)
4032 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004033 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004034 if (i == drhd->devices_cnt)
4035 drhd->ignored = 1;
4036 }
4037 }
4038
Jiang Liu7c919772014-01-06 14:18:18 +08004039 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004040 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004041 continue;
4042
Jiang Liub683b232014-02-19 14:07:32 +08004043 for_each_active_dev_scope(drhd->devices,
4044 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004045 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004046 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004047 if (i < drhd->devices_cnt)
4048 continue;
4049
David Woodhousec0771df2011-10-14 20:59:46 +01004050 /* This IOMMU has *only* gfx devices. Either bypass it or
4051 set the gfx_mapped flag, as appropriate */
4052 if (dmar_map_gfx) {
4053 intel_iommu_gfx_mapped = 1;
4054 } else {
4055 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08004056 for_each_active_dev_scope(drhd->devices,
4057 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004058 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004059 }
4060 }
4061}
4062
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004063#ifdef CONFIG_SUSPEND
4064static int init_iommu_hw(void)
4065{
4066 struct dmar_drhd_unit *drhd;
4067 struct intel_iommu *iommu = NULL;
4068
4069 for_each_active_iommu(iommu, drhd)
4070 if (iommu->qi)
4071 dmar_reenable_qi(iommu);
4072
Joseph Cihulab7792602011-05-03 00:08:37 -07004073 for_each_iommu(iommu, drhd) {
4074 if (drhd->ignored) {
4075 /*
4076 * we always have to disable PMRs or DMA may fail on
4077 * this device
4078 */
4079 if (force_on)
4080 iommu_disable_protect_mem_regions(iommu);
4081 continue;
4082 }
4083
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004084 iommu_flush_write_buffer(iommu);
4085
4086 iommu_set_root_entry(iommu);
4087
4088 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004089 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004090 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4091 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004092 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004093 }
4094
4095 return 0;
4096}
4097
4098static void iommu_flush_all(void)
4099{
4100 struct dmar_drhd_unit *drhd;
4101 struct intel_iommu *iommu;
4102
4103 for_each_active_iommu(iommu, drhd) {
4104 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004105 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004106 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004107 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004108 }
4109}
4110
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004111static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004112{
4113 struct dmar_drhd_unit *drhd;
4114 struct intel_iommu *iommu = NULL;
4115 unsigned long flag;
4116
4117 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004118 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004119 GFP_ATOMIC);
4120 if (!iommu->iommu_state)
4121 goto nomem;
4122 }
4123
4124 iommu_flush_all();
4125
4126 for_each_active_iommu(iommu, drhd) {
4127 iommu_disable_translation(iommu);
4128
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004129 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004130
4131 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4132 readl(iommu->reg + DMAR_FECTL_REG);
4133 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4134 readl(iommu->reg + DMAR_FEDATA_REG);
4135 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4136 readl(iommu->reg + DMAR_FEADDR_REG);
4137 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4138 readl(iommu->reg + DMAR_FEUADDR_REG);
4139
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004140 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004141 }
4142 return 0;
4143
4144nomem:
4145 for_each_active_iommu(iommu, drhd)
4146 kfree(iommu->iommu_state);
4147
4148 return -ENOMEM;
4149}
4150
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004151static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004152{
4153 struct dmar_drhd_unit *drhd;
4154 struct intel_iommu *iommu = NULL;
4155 unsigned long flag;
4156
4157 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004158 if (force_on)
4159 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4160 else
4161 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004162 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004163 }
4164
4165 for_each_active_iommu(iommu, drhd) {
4166
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004167 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004168
4169 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4170 iommu->reg + DMAR_FECTL_REG);
4171 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4172 iommu->reg + DMAR_FEDATA_REG);
4173 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4174 iommu->reg + DMAR_FEADDR_REG);
4175 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4176 iommu->reg + DMAR_FEUADDR_REG);
4177
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004178 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004179 }
4180
4181 for_each_active_iommu(iommu, drhd)
4182 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004183}
4184
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004185static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004186 .resume = iommu_resume,
4187 .suspend = iommu_suspend,
4188};
4189
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004190static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004191{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004192 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004193}
4194
4195#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004196static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004197#endif /* CONFIG_PM */
4198
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004199
Jiang Liuc2a0b532014-11-09 22:47:56 +08004200int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004201{
4202 struct acpi_dmar_reserved_memory *rmrr;
Eric Auger0659b8d2017-01-19 20:57:53 +00004203 int prot = DMA_PTE_READ|DMA_PTE_WRITE;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004204 struct dmar_rmrr_unit *rmrru;
Eric Auger0659b8d2017-01-19 20:57:53 +00004205 size_t length;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004206
4207 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4208 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004209 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004210
4211 rmrru->hdr = header;
4212 rmrr = (struct acpi_dmar_reserved_memory *)header;
4213 rmrru->base_address = rmrr->base_address;
4214 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004215
4216 length = rmrr->end_address - rmrr->base_address + 1;
4217 rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
4218 IOMMU_RESV_DIRECT);
4219 if (!rmrru->resv)
4220 goto free_rmrru;
4221
Jiang Liu2e455282014-02-19 14:07:36 +08004222 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4223 ((void *)rmrr) + rmrr->header.length,
4224 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004225 if (rmrru->devices_cnt && rmrru->devices == NULL)
4226 goto free_all;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004227
Jiang Liu2e455282014-02-19 14:07:36 +08004228 list_add(&rmrru->list, &dmar_rmrr_units);
4229
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004230 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004231free_all:
4232 kfree(rmrru->resv);
4233free_rmrru:
4234 kfree(rmrru);
4235out:
4236 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004237}
4238
Jiang Liu6b197242014-11-09 22:47:58 +08004239static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4240{
4241 struct dmar_atsr_unit *atsru;
4242 struct acpi_dmar_atsr *tmp;
4243
4244 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4245 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4246 if (atsr->segment != tmp->segment)
4247 continue;
4248 if (atsr->header.length != tmp->header.length)
4249 continue;
4250 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4251 return atsru;
4252 }
4253
4254 return NULL;
4255}
4256
4257int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004258{
4259 struct acpi_dmar_atsr *atsr;
4260 struct dmar_atsr_unit *atsru;
4261
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004262 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004263 return 0;
4264
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004265 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004266 atsru = dmar_find_atsr(atsr);
4267 if (atsru)
4268 return 0;
4269
4270 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004271 if (!atsru)
4272 return -ENOMEM;
4273
Jiang Liu6b197242014-11-09 22:47:58 +08004274 /*
4275 * If memory is allocated from slab by ACPI _DSM method, we need to
4276 * copy the memory content because the memory buffer will be freed
4277 * on return.
4278 */
4279 atsru->hdr = (void *)(atsru + 1);
4280 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004281 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004282 if (!atsru->include_all) {
4283 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4284 (void *)atsr + atsr->header.length,
4285 &atsru->devices_cnt);
4286 if (atsru->devices_cnt && atsru->devices == NULL) {
4287 kfree(atsru);
4288 return -ENOMEM;
4289 }
4290 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004291
Jiang Liu0e242612014-02-19 14:07:34 +08004292 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004293
4294 return 0;
4295}
4296
Jiang Liu9bdc5312014-01-06 14:18:27 +08004297static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4298{
4299 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4300 kfree(atsru);
4301}
4302
Jiang Liu6b197242014-11-09 22:47:58 +08004303int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4304{
4305 struct acpi_dmar_atsr *atsr;
4306 struct dmar_atsr_unit *atsru;
4307
4308 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4309 atsru = dmar_find_atsr(atsr);
4310 if (atsru) {
4311 list_del_rcu(&atsru->list);
4312 synchronize_rcu();
4313 intel_iommu_free_atsr(atsru);
4314 }
4315
4316 return 0;
4317}
4318
4319int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4320{
4321 int i;
4322 struct device *dev;
4323 struct acpi_dmar_atsr *atsr;
4324 struct dmar_atsr_unit *atsru;
4325
4326 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4327 atsru = dmar_find_atsr(atsr);
4328 if (!atsru)
4329 return 0;
4330
Linus Torvalds194dc872016-07-27 20:03:31 -07004331 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004332 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4333 i, dev)
4334 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004335 }
Jiang Liu6b197242014-11-09 22:47:58 +08004336
4337 return 0;
4338}
4339
Jiang Liuffebeb42014-11-09 22:48:02 +08004340static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4341{
4342 int sp, ret = 0;
4343 struct intel_iommu *iommu = dmaru->iommu;
4344
4345 if (g_iommus[iommu->seq_id])
4346 return 0;
4347
4348 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004349 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004350 iommu->name);
4351 return -ENXIO;
4352 }
4353 if (!ecap_sc_support(iommu->ecap) &&
4354 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004355 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004356 iommu->name);
4357 return -ENXIO;
4358 }
4359 sp = domain_update_iommu_superpage(iommu) - 1;
4360 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004361 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004362 iommu->name);
4363 return -ENXIO;
4364 }
4365
4366 /*
4367 * Disable translation if already enabled prior to OS handover.
4368 */
4369 if (iommu->gcmd & DMA_GCMD_TE)
4370 iommu_disable_translation(iommu);
4371
4372 g_iommus[iommu->seq_id] = iommu;
4373 ret = iommu_init_domains(iommu);
4374 if (ret == 0)
4375 ret = iommu_alloc_root_entry(iommu);
4376 if (ret)
4377 goto out;
4378
David Woodhouse8a94ade2015-03-24 14:54:56 +00004379#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004380 if (pasid_supported(iommu))
Lu Baolud9737952018-07-14 15:47:02 +08004381 intel_svm_init(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004382#endif
4383
Jiang Liuffebeb42014-11-09 22:48:02 +08004384 if (dmaru->ignored) {
4385 /*
4386 * we always have to disable PMRs or DMA may fail on this device
4387 */
4388 if (force_on)
4389 iommu_disable_protect_mem_regions(iommu);
4390 return 0;
4391 }
4392
4393 intel_iommu_init_qi(iommu);
4394 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004395
4396#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004397 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004398 ret = intel_svm_enable_prq(iommu);
4399 if (ret)
4400 goto disable_iommu;
4401 }
4402#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004403 ret = dmar_set_interrupt(iommu);
4404 if (ret)
4405 goto disable_iommu;
4406
4407 iommu_set_root_entry(iommu);
4408 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4409 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4410 iommu_enable_translation(iommu);
4411
Jiang Liuffebeb42014-11-09 22:48:02 +08004412 iommu_disable_protect_mem_regions(iommu);
4413 return 0;
4414
4415disable_iommu:
4416 disable_dmar_iommu(iommu);
4417out:
4418 free_dmar_iommu(iommu);
4419 return ret;
4420}
4421
Jiang Liu6b197242014-11-09 22:47:58 +08004422int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4423{
Jiang Liuffebeb42014-11-09 22:48:02 +08004424 int ret = 0;
4425 struct intel_iommu *iommu = dmaru->iommu;
4426
4427 if (!intel_iommu_enabled)
4428 return 0;
4429 if (iommu == NULL)
4430 return -EINVAL;
4431
4432 if (insert) {
4433 ret = intel_iommu_add(dmaru);
4434 } else {
4435 disable_dmar_iommu(iommu);
4436 free_dmar_iommu(iommu);
4437 }
4438
4439 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004440}
4441
Jiang Liu9bdc5312014-01-06 14:18:27 +08004442static void intel_iommu_free_dmars(void)
4443{
4444 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4445 struct dmar_atsr_unit *atsru, *atsr_n;
4446
4447 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4448 list_del(&rmrru->list);
4449 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004450 kfree(rmrru->resv);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004451 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004452 }
4453
Jiang Liu9bdc5312014-01-06 14:18:27 +08004454 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4455 list_del(&atsru->list);
4456 intel_iommu_free_atsr(atsru);
4457 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004458}
4459
4460int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4461{
Jiang Liub683b232014-02-19 14:07:32 +08004462 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004463 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004464 struct pci_dev *bridge = NULL;
4465 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004466 struct acpi_dmar_atsr *atsr;
4467 struct dmar_atsr_unit *atsru;
4468
4469 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004470 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004471 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004472 /* If it's an integrated device, allow ATS */
4473 if (!bridge)
4474 return 1;
4475 /* Connected via non-PCIe: no ATS */
4476 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004477 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004478 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004479 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004480 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004481 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004482 }
4483
Jiang Liu0e242612014-02-19 14:07:34 +08004484 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004485 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4486 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4487 if (atsr->segment != pci_domain_nr(dev->bus))
4488 continue;
4489
Jiang Liub683b232014-02-19 14:07:32 +08004490 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004491 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004492 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004493
4494 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004495 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004496 }
Jiang Liub683b232014-02-19 14:07:32 +08004497 ret = 0;
4498out:
Jiang Liu0e242612014-02-19 14:07:34 +08004499 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004500
Jiang Liub683b232014-02-19 14:07:32 +08004501 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004502}
4503
Jiang Liu59ce0512014-02-19 14:07:35 +08004504int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4505{
4506 int ret = 0;
4507 struct dmar_rmrr_unit *rmrru;
4508 struct dmar_atsr_unit *atsru;
4509 struct acpi_dmar_atsr *atsr;
4510 struct acpi_dmar_reserved_memory *rmrr;
4511
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004512 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004513 return 0;
4514
4515 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4516 rmrr = container_of(rmrru->hdr,
4517 struct acpi_dmar_reserved_memory, header);
4518 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4519 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4520 ((void *)rmrr) + rmrr->header.length,
4521 rmrr->segment, rmrru->devices,
4522 rmrru->devices_cnt);
Jiang Liu27e24952014-06-20 15:08:06 +08004523 if(ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004524 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004525 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004526 dmar_remove_dev_scope(info, rmrr->segment,
4527 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004528 }
4529 }
4530
4531 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4532 if (atsru->include_all)
4533 continue;
4534
4535 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4536 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4537 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4538 (void *)atsr + atsr->header.length,
4539 atsr->segment, atsru->devices,
4540 atsru->devices_cnt);
4541 if (ret > 0)
4542 break;
4543 else if(ret < 0)
4544 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004545 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004546 if (dmar_remove_dev_scope(info, atsr->segment,
4547 atsru->devices, atsru->devices_cnt))
4548 break;
4549 }
4550 }
4551
4552 return 0;
4553}
4554
Fenghua Yu99dcade2009-11-11 07:23:06 -08004555/*
4556 * Here we only respond to action of unbound device from driver.
4557 *
4558 * Added device is not attached to its DMAR domain here yet. That will happen
4559 * when mapping the device to iova.
4560 */
4561static int device_notifier(struct notifier_block *nb,
4562 unsigned long action, void *data)
4563{
4564 struct device *dev = data;
Fenghua Yu99dcade2009-11-11 07:23:06 -08004565 struct dmar_domain *domain;
4566
David Woodhouse3d891942014-03-06 15:59:26 +00004567 if (iommu_dummy(dev))
David Woodhouse44cd6132009-12-02 10:18:30 +00004568 return 0;
4569
Joerg Roedel1196c2f2014-09-30 13:02:03 +02004570 if (action != BUS_NOTIFY_REMOVED_DEVICE)
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004571 return 0;
4572
David Woodhouse1525a292014-03-06 16:19:30 +00004573 domain = find_domain(dev);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004574 if (!domain)
4575 return 0;
4576
Joerg Roedele6de0f82015-07-22 16:30:36 +02004577 dmar_remove_one_dev_info(domain, dev);
Jiang Liuab8dfe22014-07-11 14:19:27 +08004578 if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
Jiang Liu7e7dfab2014-02-19 14:07:23 +08004579 domain_exit(domain);
Alex Williamsona97590e2011-03-04 14:52:16 -07004580
Fenghua Yu99dcade2009-11-11 07:23:06 -08004581 return 0;
4582}
4583
4584static struct notifier_block device_nb = {
4585 .notifier_call = device_notifier,
4586};
4587
Jiang Liu75f05562014-02-19 14:07:37 +08004588static int intel_iommu_memory_notifier(struct notifier_block *nb,
4589 unsigned long val, void *v)
4590{
4591 struct memory_notify *mhp = v;
4592 unsigned long long start, end;
4593 unsigned long start_vpfn, last_vpfn;
4594
4595 switch (val) {
4596 case MEM_GOING_ONLINE:
4597 start = mhp->start_pfn << PAGE_SHIFT;
4598 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4599 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004600 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004601 start, end);
4602 return NOTIFY_BAD;
4603 }
4604 break;
4605
4606 case MEM_OFFLINE:
4607 case MEM_CANCEL_ONLINE:
4608 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4609 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4610 while (start_vpfn <= last_vpfn) {
4611 struct iova *iova;
4612 struct dmar_drhd_unit *drhd;
4613 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004614 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004615
4616 iova = find_iova(&si_domain->iovad, start_vpfn);
4617 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004618 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004619 start_vpfn);
4620 break;
4621 }
4622
4623 iova = split_and_remove_iova(&si_domain->iovad, iova,
4624 start_vpfn, last_vpfn);
4625 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004626 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004627 start_vpfn, last_vpfn);
4628 return NOTIFY_BAD;
4629 }
4630
David Woodhouseea8ea462014-03-05 17:09:32 +00004631 freelist = domain_unmap(si_domain, iova->pfn_lo,
4632 iova->pfn_hi);
4633
Jiang Liu75f05562014-02-19 14:07:37 +08004634 rcu_read_lock();
4635 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004636 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004637 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004638 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004639 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004640 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004641
4642 start_vpfn = iova->pfn_hi + 1;
4643 free_iova_mem(iova);
4644 }
4645 break;
4646 }
4647
4648 return NOTIFY_OK;
4649}
4650
4651static struct notifier_block intel_iommu_memory_nb = {
4652 .notifier_call = intel_iommu_memory_notifier,
4653 .priority = 0
4654};
4655
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004656static void free_all_cpu_cached_iovas(unsigned int cpu)
4657{
4658 int i;
4659
4660 for (i = 0; i < g_num_of_iommus; i++) {
4661 struct intel_iommu *iommu = g_iommus[i];
4662 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004663 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004664
4665 if (!iommu)
4666 continue;
4667
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004668 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004669 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004670
4671 if (!domain)
4672 continue;
4673 free_cpu_cached_iovas(cpu, &domain->iovad);
4674 }
4675 }
4676}
4677
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004678static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004679{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004680 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004681 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004682}
4683
Joerg Roedel161b28a2017-03-28 17:04:52 +02004684static void intel_disable_iommus(void)
4685{
4686 struct intel_iommu *iommu = NULL;
4687 struct dmar_drhd_unit *drhd;
4688
4689 for_each_iommu(iommu, drhd)
4690 iommu_disable_translation(iommu);
4691}
4692
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004693static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4694{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004695 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4696
4697 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004698}
4699
Alex Williamsona5459cf2014-06-12 16:12:31 -06004700static ssize_t intel_iommu_show_version(struct device *dev,
4701 struct device_attribute *attr,
4702 char *buf)
4703{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004704 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004705 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4706 return sprintf(buf, "%d:%d\n",
4707 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4708}
4709static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4710
4711static ssize_t intel_iommu_show_address(struct device *dev,
4712 struct device_attribute *attr,
4713 char *buf)
4714{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004715 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004716 return sprintf(buf, "%llx\n", iommu->reg_phys);
4717}
4718static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4719
4720static ssize_t intel_iommu_show_cap(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->cap);
4726}
4727static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4728
4729static ssize_t intel_iommu_show_ecap(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->ecap);
4735}
4736static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4737
Alex Williamson2238c082015-07-14 15:24:53 -06004738static ssize_t intel_iommu_show_ndoms(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 Williamson2238c082015-07-14 15:24:53 -06004743 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4744}
4745static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4746
4747static ssize_t intel_iommu_show_ndoms_used(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, "%d\n", bitmap_weight(iommu->domain_ids,
4753 cap_ndoms(iommu->cap)));
4754}
4755static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4756
Alex Williamsona5459cf2014-06-12 16:12:31 -06004757static struct attribute *intel_iommu_attrs[] = {
4758 &dev_attr_version.attr,
4759 &dev_attr_address.attr,
4760 &dev_attr_cap.attr,
4761 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06004762 &dev_attr_domains_supported.attr,
4763 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06004764 NULL,
4765};
4766
4767static struct attribute_group intel_iommu_group = {
4768 .name = "intel-iommu",
4769 .attrs = intel_iommu_attrs,
4770};
4771
4772const struct attribute_group *intel_iommu_groups[] = {
4773 &intel_iommu_group,
4774 NULL,
4775};
4776
Lu Baolu89a60792018-10-23 15:45:01 +08004777static int __init platform_optin_force_iommu(void)
4778{
4779 struct pci_dev *pdev = NULL;
4780 bool has_untrusted_dev = false;
4781
4782 if (!dmar_platform_optin() || no_platform_optin)
4783 return 0;
4784
4785 for_each_pci_dev(pdev) {
4786 if (pdev->untrusted) {
4787 has_untrusted_dev = true;
4788 break;
4789 }
4790 }
4791
4792 if (!has_untrusted_dev)
4793 return 0;
4794
4795 if (no_iommu || dmar_disabled)
4796 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
4797
4798 /*
4799 * If Intel-IOMMU is disabled by default, we will apply identity
4800 * map for all devices except those marked as being untrusted.
4801 */
4802 if (dmar_disabled)
4803 iommu_identity_mapping |= IDENTMAP_ALL;
4804
4805 dmar_disabled = 0;
4806#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
4807 swiotlb = 0;
4808#endif
4809 no_iommu = 0;
4810
4811 return 1;
4812}
4813
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004814int __init intel_iommu_init(void)
4815{
Jiang Liu9bdc5312014-01-06 14:18:27 +08004816 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09004817 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08004818 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004819
Lu Baolu89a60792018-10-23 15:45:01 +08004820 /*
4821 * Intel IOMMU is required for a TXT/tboot launch or platform
4822 * opt in, so enforce that.
4823 */
4824 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004825
Jiang Liu3a5670e2014-02-19 14:07:33 +08004826 if (iommu_init_mempool()) {
4827 if (force_on)
4828 panic("tboot: Failed to initialize iommu memory\n");
4829 return -ENOMEM;
4830 }
4831
4832 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004833 if (dmar_table_init()) {
4834 if (force_on)
4835 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004836 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004837 }
4838
Suresh Siddhac2c72862011-08-23 17:05:19 -07004839 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004840 if (force_on)
4841 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004842 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004843 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07004844
Joerg Roedelec154bf2017-10-06 15:00:53 +02004845 up_write(&dmar_global_lock);
4846
4847 /*
4848 * The bus notifier takes the dmar_global_lock, so lockdep will
4849 * complain later when we register it under the lock.
4850 */
4851 dmar_register_bus_notifier();
4852
4853 down_write(&dmar_global_lock);
4854
Joerg Roedel161b28a2017-03-28 17:04:52 +02004855 if (no_iommu || dmar_disabled) {
4856 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07004857 * We exit the function here to ensure IOMMU's remapping and
4858 * mempool aren't setup, which means that the IOMMU's PMRs
4859 * won't be disabled via the call to init_dmars(). So disable
4860 * it explicitly here. The PMRs were setup by tboot prior to
4861 * calling SENTER, but the kernel is expected to reset/tear
4862 * down the PMRs.
4863 */
4864 if (intel_iommu_tboot_noforce) {
4865 for_each_iommu(iommu, drhd)
4866 iommu_disable_protect_mem_regions(iommu);
4867 }
4868
4869 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02004870 * Make sure the IOMMUs are switched off, even when we
4871 * boot into a kexec kernel and the previous kernel left
4872 * them enabled
4873 */
4874 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004875 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02004876 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07004877
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004878 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004879 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004880
4881 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004882 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004883
Joseph Cihula51a63e62011-03-21 11:04:24 -07004884 if (dmar_init_reserved_ranges()) {
4885 if (force_on)
4886 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08004887 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07004888 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004889
4890 init_no_remapping_devices();
4891
Joseph Cihulab7792602011-05-03 00:08:37 -07004892 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004893 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07004894 if (force_on)
4895 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004896 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08004897 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004898 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08004899 up_write(&dmar_global_lock);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004900 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004901
Christoph Hellwig4fac8072017-12-24 13:57:08 +01004902#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09004903 swiotlb = 0;
4904#endif
David Woodhouse19943b02009-08-04 16:19:20 +01004905 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07004906
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004907 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01004908
Joerg Roedel39ab9552017-02-01 16:56:46 +01004909 for_each_active_iommu(iommu, drhd) {
4910 iommu_device_sysfs_add(&iommu->iommu, NULL,
4911 intel_iommu_groups,
4912 "%s", iommu->name);
4913 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
4914 iommu_device_register(&iommu->iommu);
4915 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06004916
Joerg Roedel4236d97d2011-09-06 17:56:07 +02004917 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Fenghua Yu99dcade2009-11-11 07:23:06 -08004918 bus_register_notifier(&pci_bus_type, &device_nb);
Jiang Liu75f05562014-02-19 14:07:37 +08004919 if (si_domain && !hw_pass_through)
4920 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004921 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
4922 intel_iommu_cpu_dead);
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004923 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07004924 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02004925
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004926 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08004927
4928out_free_reserved_range:
4929 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08004930out_free_dmar:
4931 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08004932 up_write(&dmar_global_lock);
4933 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08004934 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004935}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07004936
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004937static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
Alex Williamson579305f2014-07-03 09:51:43 -06004938{
4939 struct intel_iommu *iommu = opaque;
4940
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004941 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Alex Williamson579305f2014-07-03 09:51:43 -06004942 return 0;
4943}
4944
4945/*
4946 * NB - intel-iommu lacks any sort of reference counting for the users of
4947 * dependent devices. If multiple endpoints have intersecting dependent
4948 * devices, unbinding the driver from any one of them will possibly leave
4949 * the others unable to operate.
4950 */
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004951static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
Han, Weidong3199aa62009-02-26 17:31:12 +08004952{
David Woodhouse0bcb3e22014-03-06 17:12:03 +00004953 if (!iommu || !dev || !dev_is_pci(dev))
Han, Weidong3199aa62009-02-26 17:31:12 +08004954 return;
4955
Joerg Roedel2452d9d2015-07-23 16:20:14 +02004956 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
Han, Weidong3199aa62009-02-26 17:31:12 +08004957}
4958
Joerg Roedel127c7612015-07-23 17:44:46 +02004959static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08004960{
Weidong Hanc7151a82008-12-08 22:51:37 +08004961 struct intel_iommu *iommu;
4962 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08004963
Joerg Roedel55d94042015-07-22 16:50:40 +02004964 assert_spin_locked(&device_domain_lock);
4965
Joerg Roedelb608ac32015-07-21 18:19:08 +02004966 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08004967 return;
4968
Joerg Roedel127c7612015-07-23 17:44:46 +02004969 iommu = info->iommu;
4970
4971 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08004972 if (dev_is_pci(info->dev) && sm_supported(iommu))
4973 intel_pasid_tear_down_entry(iommu, info->dev,
4974 PASID_RID2PASID);
4975
Joerg Roedel127c7612015-07-23 17:44:46 +02004976 iommu_disable_dev_iotlb(info);
4977 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08004978 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02004979 }
4980
Joerg Roedelb608ac32015-07-21 18:19:08 +02004981 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07004982
Joerg Roedeld160aca2015-07-22 11:52:53 +02004983 spin_lock_irqsave(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004984 domain_detach_iommu(info->domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02004985 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004986
4987 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08004988}
4989
Joerg Roedel55d94042015-07-22 16:50:40 +02004990static void dmar_remove_one_dev_info(struct dmar_domain *domain,
4991 struct device *dev)
4992{
Joerg Roedel127c7612015-07-23 17:44:46 +02004993 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02004994 unsigned long flags;
4995
Weidong Hanc7151a82008-12-08 22:51:37 +08004996 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02004997 info = dev->archdata.iommu;
4998 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08004999 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005000}
5001
5002static int md_domain_init(struct dmar_domain *domain, int guest_width)
5003{
5004 int adjust_width;
5005
Zhen Leiaa3ac942017-09-21 16:52:45 +01005006 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005007 domain_reserve_special_ranges(domain);
5008
5009 /* calculate AGAW */
5010 domain->gaw = guest_width;
5011 adjust_width = guestwidth_to_adjustwidth(guest_width);
5012 domain->agaw = width_to_agaw(adjust_width);
5013
Weidong Han5e98c4b2008-12-08 23:03:27 +08005014 domain->iommu_coherency = 0;
Sheng Yangc5b15252009-08-06 13:31:56 +08005015 domain->iommu_snooping = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01005016 domain->iommu_superpage = 0;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005017 domain->max_addr = 0;
Weidong Han5e98c4b2008-12-08 23:03:27 +08005018
5019 /* always allocate the top pgd */
Suresh Siddha4c923d42009-10-02 11:01:24 -07005020 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005021 if (!domain->pgd)
5022 return -ENOMEM;
5023 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5024 return 0;
5025}
5026
Joerg Roedel00a77de2015-03-26 13:43:08 +01005027static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005028{
Joerg Roedel5d450802008-12-03 14:52:32 +01005029 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005030 struct iommu_domain *domain;
5031
5032 if (type != IOMMU_DOMAIN_UNMANAGED)
5033 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005034
Jiang Liuab8dfe22014-07-11 14:19:27 +08005035 dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
Joerg Roedel5d450802008-12-03 14:52:32 +01005036 if (!dmar_domain) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005037 pr_err("Can't allocate dmar_domain\n");
Joerg Roedel00a77de2015-03-26 13:43:08 +01005038 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005039 }
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07005040 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005041 pr_err("Domain initialization failed\n");
Jiang Liu92d03cc2014-02-19 14:07:28 +08005042 domain_exit(dmar_domain);
Joerg Roedel00a77de2015-03-26 13:43:08 +01005043 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005044 }
Allen Kay8140a952011-10-14 12:32:17 -07005045 domain_update_iommu_cap(dmar_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005046
Joerg Roedel00a77de2015-03-26 13:43:08 +01005047 domain = &dmar_domain->domain;
Joerg Roedel8a0e7152012-01-26 19:40:54 +01005048 domain->geometry.aperture_start = 0;
5049 domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5050 domain->geometry.force_aperture = true;
5051
Joerg Roedel00a77de2015-03-26 13:43:08 +01005052 return domain;
Kay, Allen M38717942008-09-09 18:37:29 +03005053}
Kay, Allen M38717942008-09-09 18:37:29 +03005054
Joerg Roedel00a77de2015-03-26 13:43:08 +01005055static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005056{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005057 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005058}
Kay, Allen M38717942008-09-09 18:37:29 +03005059
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005060static int intel_iommu_attach_device(struct iommu_domain *domain,
5061 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005062{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005063 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005064 struct intel_iommu *iommu;
5065 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005066 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005067
Alex Williamsonc875d2c2014-07-03 09:57:02 -06005068 if (device_is_rmrr_locked(dev)) {
5069 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5070 return -EPERM;
5071 }
5072
David Woodhouse7207d8f2014-03-09 16:31:06 -07005073 /* normally dev is not mapped */
5074 if (unlikely(domain_context_mapped(dev))) {
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005075 struct dmar_domain *old_domain;
5076
David Woodhouse1525a292014-03-06 16:19:30 +00005077 old_domain = find_domain(dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005078 if (old_domain) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02005079 rcu_read_lock();
Joerg Roedelde7e8882015-07-22 11:58:07 +02005080 dmar_remove_one_dev_info(old_domain, dev);
Joerg Roedeld160aca2015-07-22 11:52:53 +02005081 rcu_read_unlock();
Joerg Roedel62c22162014-12-09 12:56:45 +01005082
5083 if (!domain_type_is_vm_or_si(old_domain) &&
5084 list_empty(&old_domain->devices))
5085 domain_exit(old_domain);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005086 }
5087 }
5088
David Woodhouse156baca2014-03-09 14:00:57 -07005089 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005090 if (!iommu)
5091 return -ENODEV;
5092
5093 /* check if this iommu agaw is sufficient for max mapped address */
5094 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005095 if (addr_width > cap_mgaw(iommu->cap))
5096 addr_width = cap_mgaw(iommu->cap);
5097
5098 if (dmar_domain->max_addr > (1LL << addr_width)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005099 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005100 "sufficient for the mapped address (%llx)\n",
Tom Lyona99c47a2010-05-17 08:20:45 +01005101 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005102 return -EFAULT;
5103 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005104 dmar_domain->gaw = addr_width;
5105
5106 /*
5107 * Knock out extra levels of page tables if necessary
5108 */
5109 while (iommu->agaw < dmar_domain->agaw) {
5110 struct dma_pte *pte;
5111
5112 pte = dmar_domain->pgd;
5113 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005114 dmar_domain->pgd = (struct dma_pte *)
5115 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005116 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005117 }
5118 dmar_domain->agaw--;
5119 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005120
Joerg Roedel28ccce02015-07-21 14:45:31 +02005121 return domain_add_dev_info(dmar_domain, dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005122}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005123
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005124static void intel_iommu_detach_device(struct iommu_domain *domain,
5125 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005126{
Joerg Roedele6de0f82015-07-22 16:30:36 +02005127 dmar_remove_one_dev_info(to_dmar_domain(domain), dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005128}
Kay, Allen M38717942008-09-09 18:37:29 +03005129
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005130static int intel_iommu_map(struct iommu_domain *domain,
5131 unsigned long iova, phys_addr_t hpa,
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005132 size_t size, int iommu_prot)
Kay, Allen M38717942008-09-09 18:37:29 +03005133{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005134 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005135 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005136 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005137 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005138
Joerg Roedeldde57a22008-12-03 15:04:09 +01005139 if (iommu_prot & IOMMU_READ)
5140 prot |= DMA_PTE_READ;
5141 if (iommu_prot & IOMMU_WRITE)
5142 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005143 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5144 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005145
David Woodhouse163cc522009-06-28 00:51:17 +01005146 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005147 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005148 u64 end;
5149
5150 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005151 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005152 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005153 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005154 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005155 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005156 return -EFAULT;
5157 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005158 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005159 }
David Woodhousead051222009-06-28 14:22:28 +01005160 /* Round up size to next multiple of PAGE_SIZE, if it and
5161 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005162 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005163 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5164 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005165 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005166}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005167
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005168static size_t intel_iommu_unmap(struct iommu_domain *domain,
David Woodhouseea8ea462014-03-05 17:09:32 +00005169 unsigned long iova, size_t size)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005170{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005171 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005172 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005173 unsigned long start_pfn, last_pfn;
5174 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005175 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005176
David Woodhouse5cf0a762014-03-19 16:07:49 +00005177 /* Cope with horrid API which requires us to unmap more than the
5178 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005179 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005180
5181 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5182 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5183
David Woodhouseea8ea462014-03-05 17:09:32 +00005184 start_pfn = iova >> VTD_PAGE_SHIFT;
5185 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5186
5187 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5188
5189 npages = last_pfn - start_pfn + 1;
5190
Shaokun Zhangf746a022018-03-22 18:18:06 +08005191 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005192 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5193 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005194
5195 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005196
David Woodhouse163cc522009-06-28 00:51:17 +01005197 if (dmar_domain->max_addr == iova + size)
5198 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005199
David Woodhouse5cf0a762014-03-19 16:07:49 +00005200 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005201}
Kay, Allen M38717942008-09-09 18:37:29 +03005202
Joerg Roedeld14d6572008-12-03 15:06:57 +01005203static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305204 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005205{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005206 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005207 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005208 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005209 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005210
David Woodhouse5cf0a762014-03-19 16:07:49 +00005211 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005212 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005213 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005214
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005215 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005216}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005217
Joerg Roedel5d587b82014-09-05 10:50:45 +02005218static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005219{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005220 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005221 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005222 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005223 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005224
Joerg Roedel5d587b82014-09-05 10:50:45 +02005225 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005226}
5227
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005228static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005229{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005230 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005231 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005232 u8 bus, devfn;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005233
Alex Williamsona5459cf2014-06-12 16:12:31 -06005234 iommu = device_to_iommu(dev, &bus, &devfn);
5235 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005236 return -ENODEV;
5237
Joerg Roedele3d10af2017-02-01 17:23:22 +01005238 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005239
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005240 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005241
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005242 if (IS_ERR(group))
5243 return PTR_ERR(group);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005244
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005245 iommu_group_put(group);
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005246 return 0;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005247}
5248
5249static void intel_iommu_remove_device(struct device *dev)
5250{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005251 struct intel_iommu *iommu;
5252 u8 bus, devfn;
5253
5254 iommu = device_to_iommu(dev, &bus, &devfn);
5255 if (!iommu)
5256 return;
5257
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005258 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005259
Joerg Roedele3d10af2017-02-01 17:23:22 +01005260 iommu_device_unlink(&iommu->iommu, dev);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005261}
5262
Eric Auger0659b8d2017-01-19 20:57:53 +00005263static void intel_iommu_get_resv_regions(struct device *device,
5264 struct list_head *head)
5265{
5266 struct iommu_resv_region *reg;
5267 struct dmar_rmrr_unit *rmrr;
5268 struct device *i_dev;
5269 int i;
5270
5271 rcu_read_lock();
5272 for_each_rmrr_units(rmrr) {
5273 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5274 i, i_dev) {
5275 if (i_dev != device)
5276 continue;
5277
5278 list_add_tail(&rmrr->resv->list, head);
5279 }
5280 }
5281 rcu_read_unlock();
5282
5283 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5284 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005285 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005286 if (!reg)
5287 return;
5288 list_add_tail(&reg->list, head);
5289}
5290
5291static void intel_iommu_put_resv_regions(struct device *dev,
5292 struct list_head *head)
5293{
5294 struct iommu_resv_region *entry, *next;
5295
5296 list_for_each_entry_safe(entry, next, head, list) {
Gerald Schaefer198bc322019-01-16 20:11:44 +01005297 if (entry->type == IOMMU_RESV_MSI)
Eric Auger0659b8d2017-01-19 20:57:53 +00005298 kfree(entry);
5299 }
Kay, Allen M38717942008-09-09 18:37:29 +03005300}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005301
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005302#ifdef CONFIG_INTEL_IOMMU_SVM
5303int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
5304{
5305 struct device_domain_info *info;
5306 struct context_entry *context;
5307 struct dmar_domain *domain;
5308 unsigned long flags;
5309 u64 ctx_lo;
5310 int ret;
5311
5312 domain = get_valid_domain_for_dev(sdev->dev);
5313 if (!domain)
5314 return -EINVAL;
5315
5316 spin_lock_irqsave(&device_domain_lock, flags);
5317 spin_lock(&iommu->lock);
5318
5319 ret = -EINVAL;
5320 info = sdev->dev->archdata.iommu;
5321 if (!info || !info->pasid_supported)
5322 goto out;
5323
5324 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5325 if (WARN_ON(!context))
5326 goto out;
5327
5328 ctx_lo = context[0].lo;
5329
5330 sdev->did = domain->iommu_did[iommu->seq_id];
5331 sdev->sid = PCI_DEVID(info->bus, info->devfn);
5332
5333 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005334 ctx_lo |= CONTEXT_PASIDE;
5335 context[0].lo = ctx_lo;
5336 wmb();
5337 iommu->flush.flush_context(iommu, sdev->did, sdev->sid,
5338 DMA_CCMD_MASK_NOBIT,
5339 DMA_CCMD_DEVICE_INVL);
5340 }
5341
5342 /* Enable PASID support in the device, if it wasn't already */
5343 if (!info->pasid_enabled)
5344 iommu_enable_dev_iotlb(info);
5345
5346 if (info->ats_enabled) {
5347 sdev->dev_iotlb = 1;
5348 sdev->qdep = info->ats_qdep;
5349 if (sdev->qdep >= QI_DEV_EIOTLB_MAX_INVS)
5350 sdev->qdep = 0;
5351 }
5352 ret = 0;
5353
5354 out:
5355 spin_unlock(&iommu->lock);
5356 spin_unlock_irqrestore(&device_domain_lock, flags);
5357
5358 return ret;
5359}
5360
5361struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5362{
5363 struct intel_iommu *iommu;
5364 u8 bus, devfn;
5365
5366 if (iommu_dummy(dev)) {
5367 dev_warn(dev,
5368 "No IOMMU translation for device; cannot enable SVM\n");
5369 return NULL;
5370 }
5371
5372 iommu = device_to_iommu(dev, &bus, &devfn);
5373 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07005374 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005375 return NULL;
5376 }
5377
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005378 return iommu;
5379}
5380#endif /* CONFIG_INTEL_IOMMU_SVM */
5381
Joerg Roedelb0119e82017-02-01 13:23:08 +01005382const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00005383 .capable = intel_iommu_capable,
5384 .domain_alloc = intel_iommu_domain_alloc,
5385 .domain_free = intel_iommu_domain_free,
5386 .attach_dev = intel_iommu_attach_device,
5387 .detach_dev = intel_iommu_detach_device,
5388 .map = intel_iommu_map,
5389 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00005390 .iova_to_phys = intel_iommu_iova_to_phys,
5391 .add_device = intel_iommu_add_device,
5392 .remove_device = intel_iommu_remove_device,
5393 .get_resv_regions = intel_iommu_get_resv_regions,
5394 .put_resv_regions = intel_iommu_put_resv_regions,
5395 .device_group = pci_device_group,
5396 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005397};
David Woodhouse9af88142009-02-13 23:18:03 +00005398
Daniel Vetter94526182013-01-20 23:50:13 +01005399static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
5400{
5401 /* G4x/GM45 integrated gfx dmar support is totally busted. */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005402 pr_info("Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01005403 dmar_map_gfx = 0;
5404}
5405
5406DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
5407DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
5408DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
5409DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
5410DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
5411DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
5412DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
5413
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005414static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00005415{
5416 /*
5417 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01005418 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00005419 */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005420 pr_info("Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00005421 rwbf_quirk = 1;
5422}
5423
5424DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01005425DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
5426DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
5427DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
5428DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
5429DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
5430DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07005431
Adam Jacksoneecfd572010-08-25 21:17:34 +01005432#define GGC 0x52
5433#define GGC_MEMORY_SIZE_MASK (0xf << 8)
5434#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
5435#define GGC_MEMORY_SIZE_1M (0x1 << 8)
5436#define GGC_MEMORY_SIZE_2M (0x3 << 8)
5437#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
5438#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
5439#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
5440#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
5441
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08005442static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01005443{
5444 unsigned short ggc;
5445
Adam Jacksoneecfd572010-08-25 21:17:34 +01005446 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01005447 return;
5448
Adam Jacksoneecfd572010-08-25 21:17:34 +01005449 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005450 pr_info("BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01005451 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005452 } else if (dmar_map_gfx) {
5453 /* we have to ensure the gfx device is idle before we flush */
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005454 pr_info("Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07005455 intel_iommu_strict = 1;
5456 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01005457}
5458DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
5459DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
5460DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
5461DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
5462
David Woodhousee0fc7e02009-09-30 09:12:17 -07005463/* On Tylersburg chipsets, some BIOSes have been known to enable the
5464 ISOCH DMAR unit for the Azalia sound device, but not give it any
5465 TLB entries, which causes it to deadlock. Check for that. We do
5466 this in a function called from init_dmars(), instead of in a PCI
5467 quirk, because we don't want to print the obnoxious "BIOS broken"
5468 message if VT-d is actually disabled.
5469*/
5470static void __init check_tylersburg_isoch(void)
5471{
5472 struct pci_dev *pdev;
5473 uint32_t vtisochctrl;
5474
5475 /* If there's no Azalia in the system anyway, forget it. */
5476 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
5477 if (!pdev)
5478 return;
5479 pci_dev_put(pdev);
5480
5481 /* System Management Registers. Might be hidden, in which case
5482 we can't do the sanity check. But that's OK, because the
5483 known-broken BIOSes _don't_ actually hide it, so far. */
5484 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
5485 if (!pdev)
5486 return;
5487
5488 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
5489 pci_dev_put(pdev);
5490 return;
5491 }
5492
5493 pci_dev_put(pdev);
5494
5495 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
5496 if (vtisochctrl & 1)
5497 return;
5498
5499 /* Drop all bits other than the number of TLB entries */
5500 vtisochctrl &= 0x1c;
5501
5502 /* If we have the recommended number of TLB entries (16), fine. */
5503 if (vtisochctrl == 0x10)
5504 return;
5505
5506 /* Zero TLB entries? You get to ride the short bus to school. */
5507 if (!vtisochctrl) {
5508 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
5509 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
5510 dmi_get_system_info(DMI_BIOS_VENDOR),
5511 dmi_get_system_info(DMI_BIOS_VERSION),
5512 dmi_get_system_info(DMI_PRODUCT_VERSION));
5513 iommu_identity_mapping |= IDENTMAP_AZALIA;
5514 return;
5515 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005516
5517 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07005518 vtisochctrl);
5519}